OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 10957|回复: 8

STM32F767 ADC多通道+DMA采集

[复制链接]

1

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2017-7-31
在线时间
10 小时
发表于 2018-5-24 16:56:34 | 显示全部楼层 |阅读模式
10金钱
目的:通过DMA实现ADC1的通道1、2、3电压采集,对三个通道连续采集10次,采集的数据储存于一个二维数组中u16 uhADCxConvertedValue[10][3]。
现象:实际采集时,数组的前4个元素仅更新一次后不再更新,后面的数据可以正常更新,仿真结果如图:
微信图片_20180524164550.png    DMA设置的memaddr跟数组地址是一致的,但是前4个数据不会更新。如果用一维数组u16 uhADCxConvertedValue[3]储存三个通道的数据就完全不更新了。贴出代码,求大佬们解答。

ADC配置代码如下:

/* ADC handler declaration */
ADC_HandleTypeDef    AdcHandle;
/* Variable used to get converted value */
u16 uhADCxConvertedValue[10][3] = {0};

void bsp_ADC_Init(void)
{
        ADC_ChannelConfTypeDef sConfig;
       
        /*##-1- Configure the ADC peripheral #######################################*/
        AdcHandle.Instance                           = ADC1;
        AdcHandle.Init.ClockPrescaler        = ADC_CLOCKPRESCALER_PCLK_DIV4;
        AdcHandle.Init.Resolution            = ADC_RESOLUTION_12B;
        AdcHandle.Init.ScanConvMode          = ENABLE;                        /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
        AdcHandle.Init.ContinuousConvMode    = ENABLE;                        /* Continuous mode disabled to have only 1 conversion at each conversion trig */
        AdcHandle.Init.DiscontinuousConvMode = DISABLE;                       /* Parameter discarded because sequencer is disabled */
        AdcHandle.Init.NbrOfDiscConversion   = 0;
        AdcHandle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE;        /* Conversion start trigged at each external event */
        AdcHandle.Init.ExternalTrigConv      = ADC_EXTERNALTRIGCONV_T1_CC1;
        AdcHandle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;
        AdcHandle.Init.NbrOfConversion       = 3;
        AdcHandle.Init.DMAContinuousRequests = ENABLE;
        AdcHandle.Init.EOCSelection          = DISABLE;
       
        HAL_ADC_Init(&AdcHandle);
       
        /*##-2- Configure ADC regular channel ######################################*/
    sConfig.Channel      = ADC_CHANNEL_1;
    sConfig.Rank         = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    sConfig.Offset       = 0;  
    HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
       
    sConfig.Channel      = ADC_CHANNEL_2;
    sConfig.Rank         = 2;
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    sConfig.Offset       = 0;
    HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);

    sConfig.Channel      = ADC_CHANNEL_3;
    sConfig.Rank         = 3;
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    sConfig.Offset       = 0;
    HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);

    HAL_ADC_Start_DMA(&AdcHandle,(u32*)uhADCxConvertedValue,30);
}


/**
  * @brief ADC MSP Initialization
  *        This function configures the hardware resources used in this example:
  *           - Peripheral's clock enable
  *           - Peripheral's GPIO Configuration
  * @param hadc: ADC handle pointer
  * @retval None
  */
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
  GPIO_InitTypeDef          GPIO_InitStruct;
  static DMA_HandleTypeDef  hdma_adc;

  /*##-1- Enable peripherals and GPIO Clocks #################################*/
  /* ADC1 Periph clock enable */
  __HAL_RCC_ADC1_CLK_ENABLE();
  /* Enable GPIO clock ****************************************/
  __HAL_RCC_GPIOA_CLK_ENABLE();
  /* Enable DMA2 clock */
  __HAL_RCC_DMA2_CLK_ENABLE();

  /*##-2- Configure peripheral GPIO ##########################################*/
  /* ADC Channel GPIO pin configuration */
  GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);

  /*##-3- Configure the DMA streams ##########################################*/
  /* Set the parameters to be configured */
  hdma_adc.Instance = DMA2_Stream0;
  hdma_adc.Init.Channel  = DMA_CHANNEL_0;
  hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;
  hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_adc.Init.MemInc = DMA_MINC_ENABLE;
  hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  hdma_adc.Init.Mode = DMA_CIRCULAR;
  hdma_adc.Init.Priority = DMA_PRIORITY_HIGH;
  hdma_adc.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  hdma_adc.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
  hdma_adc.Init.MemBurst = DMA_MBURST_SINGLE;
  hdma_adc.Init.PeriphBurst = DMA_PBURST_SINGLE;

  HAL_DMA_Init(&hdma_adc);

  /* Associate the initialized DMA handle to the ADC handle */
  __HAL_LINKDMA(hadc, DMA_Handle, hdma_adc);

  /*##-4- Configure the NVIC for DMA #########################################*/
  /* NVIC configuration for DMA transfer complete interrupt */
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 8);
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}

void DMA2_Stream0_IRQHandler(void)
{
  HAL_DMA_IRQHandler(AdcHandle.DMA_Handle);
}



最佳答案

查看完整内容[请看2#楼]

第二个问题在论坛里找到解决办法,需要关闭Cache再去读取,读取后再打开。 http://www.openedv.com/forum.php?mod=viewthread&tid=94381&extra=
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2017-7-31
在线时间
10 小时
 楼主| 发表于 2018-5-24 16:56:35 | 显示全部楼层
本帖最后由 Xcy 于 2018-5-24 19:13 编辑

第二个问题在论坛里找到解决办法,需要关闭Cache再去读取,读取后再打开。
http://www.openedv.com/forum.php?mod=viewthread&tid=94381&extra=
回复

使用道具 举报

1

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2017-7-31
在线时间
10 小时
 楼主| 发表于 2018-5-24 18:55:02 | 显示全部楼层
后面屏蔽了其他外设功能及FreeRTOS测了一下,裸机跑功能是正常的。但是又出了一个奇怪的现象,在main函数里启动ADC后,在while循环里 计算各通道电压,只要调用uhADCxConvertedValue这个数组,DMA就出现问题,能进DMA中断,但是uhADCxConvertedValue数据不再更新。难道调用时需要暂停DMA? 我在STM32F1里都是直接调用计算的,没出现过这种情况。有人做过的,能否解答一下。

int main(void)
{
        u32 is_boot=0;
        u16 adc[3]={0};
       
        SCB->VTOR = FLASH_BASE | 0x20000;//设置偏移量

        Cache_Enable();                 //打开L1-Cache
        HAL_Init();                         //初始化HAL库
        Stm32_Clock_Init(432,25,2,9);   //设置时钟,216Mhz   
        bsp_Init();                     //板子外设初始化
   
        /* Infinite loop */
        while (1)
        {
                Model_Info.P_Power = uhADCxConvertedValue[1][0]*3300/4096;
                Model_Info.N_Power = uhADCxConvertedValue[1][1]*3300/4096;        
                HAL_Delay(10);
        }
}
回复

使用道具 举报

2

主题

6

帖子

0

精华

初级会员

Rank: 2

积分
75
金钱
75
注册时间
2017-11-23
在线时间
10 小时
发表于 2018-11-1 14:02:06 | 显示全部楼层
根据楼主和其他论坛说明,调试通过 DMA_ADC程序,基于原子 阿波罗F767开发板。上传个例程方便测试。

阿波罗F767_ADC_DMA.rar

13.52 MB, 下载次数: 1446

回复

使用道具 举报

6

主题

108

帖子

1

精华

高级会员

Rank: 4

积分
716
金钱
716
注册时间
2017-4-25
在线时间
203 小时
发表于 2018-11-20 00:23:58 | 显示全部楼层
不错
回复

使用道具 举报

7

主题

27

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2019-4-21
在线时间
23 小时
发表于 2019-6-3 15:03:32 | 显示全部楼层
老铁,定时器哪里可以发一下吗,配置我没有找到怎么弄
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
2
金钱
2
注册时间
2021-7-19
在线时间
0 小时
发表于 2021-7-19 16:21:21 | 显示全部楼层
各位老铁们,有个问题不知道你们碰到过没有,sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES,多通道ADC+DMA模式,只有设置成480CYCLES才能采样到数据,其他采样周期都不行
回复

使用道具 举报

0

主题

13

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2021-7-19
在线时间
9 小时
发表于 2021-7-19 16:48:34 | 显示全部楼层
厉害了
回复

使用道具 举报

2

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
72
金钱
72
注册时间
2021-3-30
在线时间
15 小时
发表于 2021-10-22 20:46:09 | 显示全部楼层
谢谢,学习了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 19:41

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表