你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

关于STM32l476的多路ADC+DMA采集电压的问题

[复制链接]
ccmm520 提问时间:2018-3-16 09:50 /
本帖最后由 ccmm520 于 2018-3-16 16:00 编辑

主要的代码如下:adc.c 代码:
  1. ADC_HandleTypeDef hadc1;
  2. DMA_HandleTypeDef hdma_adc1;
  3. void MX_ADC1_Init(void)
  4. {
  5.   ADC_ChannelConfTypeDef sConfig;

  6.   /**Configure the global features of the ADC (Clock, Resolution, Data

  7. Alignment and number of conversion) */
  8.   hadc1.Instance = ADC1;
  9.   hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
  10.   hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  11.   hadc1.Init.ScanConvMode = ENABLE;
  12.   hadc1.Init.ContinuousConvMode = ENABLE;
  13.   hadc1.Init.DiscontinuousConvMode = DISABLE;
  14.   hadc1.Init.ExternalTrigConvEdge = ADC_SOFTWARE_START;
  15.   hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  16.   hadc1.Init.NbrOfConversion = 2;
  17.   hadc1.Init.DMAContinuousRequests = ENABLE;
  18.   hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  19.   HAL_ADC_Init(&hadc1);

  20.   /**Configure for the selected ADC regular channel its corresponding

  21. rank in the sequencer and its sample time. */
  22.   sConfig.Channel = ADC_CHANNEL_5;
  23.   sConfig.Rank = 1;
  24.   sConfig.SamplingTime = ADC_SAMPLETIME_6CYCLES_5;
  25.   HAL_ADC_ConfigChannel(&hadc1, &sConfig);

  26.   /**Configure for the selected ADC regular channel its corresponding

  27. rank in the sequencer and its sample time. */
  28.   sConfig.Channel = ADC_CHANNEL_3;
  29.   sConfig.Rank = 2;
  30.   HAL_ADC_ConfigChannel(&hadc1, &sConfig);

  31. }

  32. void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
  33. {
  34.   GPIO_InitTypeDef GPIO_InitStruct;
  35.   if(hadc->Instance==ADC1)
  36.   {
  37.     /* Peripheral clock enable */
  38.     __HAL_RCC_ADC_CLK_ENABLE();
  39.   
  40.     /**ADC1 GPIO Configuration   
  41.     PA0-WKUP     ------> ADC1_IN5
  42.     PC2     ------> ADC1_IN3 */
  43.     GPIO_InitStruct.Pin = GPIO_PIN_0;
  44.     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  45.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  46.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  47.                
  48.     GPIO_InitStruct.Pin = GPIO_PIN_2;
  49.     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  50.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  51.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  52.     /* Peripheral DMA init*/
  53.     hdma_adc1.Instance = DMA1_Channel1;
  54.     hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
  55.     hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
  56.     hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
  57.     hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  58.     hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
  59.     hdma_adc1.Init.Mode = DMA_CIRCULAR;
  60.     hdma_adc1.Init.Priority = DMA_PRIORITY_MEDIUM;
  61.     HAL_DMA_Init(&hdma_adc1);

  62.     __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
  63.   }
  64. }

  65. void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
  66. {

  67.   if(hadc->Instance==ADC1)
  68.   {
  69.     /* Peripheral clock disable */
  70.     __HAL_RCC_ADC_CLK_DISABLE();
  71.   
  72.     /**ADC1 GPIO Configuration   
  73.     PA0-WKUP     ------> ADC1_IN5
  74.     PC2     ------> ADC1_IN3 */
  75.     HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0);
  76.     HAL_GPIO_DeInit(GPIOC, GPIO_PIN_2);
  77.     /* Peripheral DMA DeInit*/
  78.     HAL_DMA_DeInit(hadc->DMA_Handle);
  79.   }
  80. }
复制代码
main.c 代码:
  1. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);
  2. /* USER CODE BEGIN 0 */
  3. uint32_t uhADCxConvertedValue[2];
  4. unsigned long shijian=0;
  5. volatile uint8_t dmaflage=0;
  6. /* USER CODE END 0 */
  7. int main(void)
  8. {

  9.   /* USER CODE BEGIN 1 */        
  10.   uint16_t ad1=0, ad2=0;
  11.   /* USER CODE END 1 */

  12.   /* MCU

  13. Configuration----------------------------------------------------------

  14. */

  15.   /* Reset of all peripherals, Initializes the Flash interface and the

  16. Systick. */
  17.   HAL_Init();

  18.   /* Configure the system clock */
  19.   SystemClock_Config();

  20.   /* Initialize all configured peripherals */
  21.   MX_GPIO_Init();

  22.   MX_DMA_Init();
  23.   MX_ADC1_Init();
  24.   /* USER CODE BEGIN 2 */
  25. #if DEBUG_ENABLE
  26.    debugInit(115200);
  27. #endif

  28.   shijian=HAL_GetTick();
  29.   HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&uhADCxConvertedValue,2);
  30.   printf("HAL_ADC_Start_DMA\r\n");
  31.   while (1)
  32.   {
  33.     if(HAL_GetTick()-shijian>=500)
  34.     {
  35.       if(dmaflage==1)
  36.       {
  37.         dmaflage=0;
  38.         ad1 = uhADCxConvertedValue[0];
  39.         ad2 = uhADCxConvertedValue[1];
  40.         printf("ad1=%d, ad2=%d, Vad1=%0.2fV, Vad2=%0.2fV \r\n",ad1,ad2,

  41. ad1*3.3/4096,ad2*3.3/4096);
  42.         ad1 = (ad1*330)/4096; //扩大100倍 ,3.3V, 4096=12bit
  43.         ad2 = (ad2*330)/4096;
  44.         printf("V100ad1=%d, V100ad2=%d\r\n",ad1,ad2);
  45.         HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&uhADCxConvertedValue,2);        
  46.         ad1 = 0;
  47.         ad2 = 0;
  48.       }
  49.       shijian=HAL_GetTick();        
  50.     }
  51.   }
  52. }

  53. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
  54. {
  55.   dmaflage=1;
  56.   HAL_ADC_Stop_DMA(&hadc1);
  57. }
复制代码
dma.c 代码:
  1. void MX_DMA_Init(void)
  2. {
  3.   /* DMA controller clock enable */
  4.   //  __HAL_RCC_DMA2_CLK_ENABLE();
  5.   __HAL_RCC_DMA1_CLK_ENABLE();
  6.         
  7.   /* NVIC configuration for DMA Input data interrupt */
  8.   HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 5, 0);
  9.   HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);  

  10. }
复制代码
stm32l4xx_it.c 代码
  1. extern DMA_HandleTypeDef hdma_adc1;

  2. /**
  3. * @brief This function handles DMA1 channel1 global interrupt.
  4. */
  5. void DMA1_Channel1_IRQHandler(void)
  6. {
  7.   HAL_DMA_IRQHandler(&hdma_adc1);
  8. }
复制代码

复制代码
大致的代码就是上面,采用ADC1,PA0通道5,PC2通道3;PA0口直接接3.3V,PC2口直接接地。
问题:
   使用上面的代码,转出来的两个通道的电压值都是0.4~0.45V,理论上应该分别采集到的是3.3V和0V的,不知道为什么?是不是我哪里配置不对啊,求大神帮忙~


QQ图片20180315215136.png
收藏 评论17 发布时间:2018-3-16 09:50

举报

17个回答
ccmm520 回答时间:2018-3-16 10:20:01
wenyangzeng 发表于 2018-3-16 10:05
楼主设置DMA中断,中断返回函数却是ADC中断,

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

我在stm32l4xx_it.c中也进行了
  1. /**
  2. * @brief This function handles DMA1 channel1 global interrupt.
  3. */
  4. void DMA1_Channel1_IRQHandler(void)
  5. {
  6.   /* USER CODE BEGIN DMA2_Stream0_IRQn 0 */

  7.   /* USER CODE END DMA2_Stream0_IRQn 0 */
  8.   HAL_DMA_IRQHandler(&hdma_adc1);
  9.   /* USER CODE BEGIN DMA2_Stream0_IRQn 1 */

  10.   /* USER CODE END DMA2_Stream0_IRQn 1 */
  11. }
复制代码


我也是刚学没多久,而且是参考别人的例子来写的这个callback,请问具体我要怎么操作呢
ccmm520 回答时间:2018-3-16 15:47:51
本帖最后由 ccmm520 于 2018-3-16 15:48 编辑
butterflyspring 发表于 2018-3-16 11:13
我建议你看看我们的例程:
\Repository\STM32Cube_FW_L4_V1.10.0\Projects\STM32L476G_EVAL\Examples\ADC\AD ...

file:///C:/Users/Administrator/Desktop/QQ%E5%9B%BE%E7%89%8720180315215136.png

采用ADC1,PA0通道5,PC2通道3;PA0口直接接3.3V,PC2口直接接地。MCU是stm32l476RC

转出来的电压值都是0.4~0.45V,理论上应该分别采集到的是3.3V和0V的,不知道为什么?
QQ图片20180315215136.png
ccmm520 回答时间:2018-3-16 10:51:03
wenyangzeng 发表于 2018-3-16 10:32
DMA中断调用应该是:
void DMA1_Channel1_IRQHandler(void)
{}

转换的值不用在中断读取吧,因为DMA的转换返回值是在HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&uhADCxConvertedValue,2);中的uhADCxConvertedValue就转好了,而且是循环连续转换的,我们只要在while(1)中不断获取转换即可吧。

另外,你附件的demo好像我没看出我的错在哪
wenyangzeng 回答时间:2018-3-16 10:05:56
楼主设置DMA中断,中断返回函数却是ADC中断,

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

如何读到正确的数据?

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

wenyangzeng 回答时间:2018-3-16 10:32:30
本帖最后由 wenyangzeng 于 2018-3-16 10:33 编辑
ccmm520 发表于 2018-3-16 10:20
我在stm32l4xx_it.c中也进行了

DMA中断调用应该是:
void DMA1_Channel1_IRQHandler(void)
{}
但是你在DMA中断中并没有读取数据。
ST官方例程很多,可以参考: ADC_RegularConversion_DMA.rar (61.71 KB, 下载次数: 172)
butterflyspring 回答时间:2018-3-16 11:13:31
我建议你看看我们的例程:
\Repository\STM32Cube_FW_L4_V1.10.0\Projects\STM32L476G_EVAL\Examples\ADC\ADC_DMA_Transfer

然后__weak void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)这个是个虚函数,你不能在main在次声明,直接实现就好了.只是规范一下,你能进去代表不影响.

我建议你一个个channel单独试一下,但后看看你硬件的参考电压是多少等等..

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

wenyangzeng 回答时间:2018-3-16 11:24:28
ccmm520 发表于 2018-3-16 10:51
转换的值不用在中断读取吧,因为DMA的转换返回值是在HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&uhADCxConve ...

可是你在ADC中断里关闭了DMA
HAL_ADC_Stop_DMA(&hadc1);
ccmm520 回答时间:2018-3-16 12:23:36
wenyangzeng 发表于 2018-3-16 11:24
可是你在ADC中断里关闭了DMA
HAL_ADC_Stop_DMA(&hadc1);

我在while(1)里面又开启HAL_ADC_Start_DMA了,应该可以的吧?
wenyangzeng 回答时间:2018-3-16 12:36:08
ccmm520 发表于 2018-3-16 12:23
我在while(1)里面又开启HAL_ADC_Start_DMA了,应该可以的吧?

DMA重新启动好像还要初始化ADC和DMA
ccmm520 回答时间:2018-3-16 15:41:55
wenyangzeng 发表于 2018-3-16 12:36
DMA重新启动好像还要初始化ADC和DMA

重新初始化与否都可以,刚试了,目前这个问题很纠结。参考例程也看了,还是不知道哪里出了问题
wenyangzeng 回答时间:2018-3-16 16:23:35
ccmm520 发表于 2018-3-16 15:41
重新初始化与否都可以,刚试了,目前这个问题很纠结。参考例程也看了,还是不知道哪里出了问题 ...

其实你需要处理的数据量不多,建议不使用DMA,直接ADC中断取数据应该能成功
ccmm520 回答时间:2018-3-16 17:11:51
wenyangzeng 发表于 2018-3-16 16:23
其实你需要处理的数据量不多,建议不使用DMA,直接ADC中断取数据应该能成功 ...

不是了,现在只是简单的转换,后面项目要大数据量转换的
wenyangzeng 回答时间:2018-3-16 22:08:45
ccmm520 发表于 2018-3-16 15:41
重新初始化与否都可以,刚试了,目前这个问题很纠结。参考例程也看了,还是不知道哪里出了问题 ...

先去掉DMA,调试到ADC正常后再增加DMA,总是比较容易找到问题。
埃斯提爱慕 回答时间:2018-3-19 18:14:36
提示: 作者被禁止或删除 内容自动屏蔽
12下一页

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版