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

STM32CUBEMX + ADC(单通道,双通道DMA)

[复制链接]
STMCU小助手 发布时间:2022-11-1 17:10
1.工具
IAR
STM32CUBEMX
开发板STM32F411VET6

2.工程配置
2.1 单通道

2.1.1系统时钟RCC、SYS配置

62a4cd2f2edc4af387c7f65f0421ee2b.png

2.1.2 ADC配置,这里强调2点,

使用ADC1——>IN4(通道4),本案例使用F4开发版,在12bit分辨率下,最小转换时间为15周期(最小转换时间 > 采样时间,具体可以百度),本案例转换时间为 15/16M = 0.937us

(F4)最小转换时间:

​ 12bit——>15周期

​ 10bit——>13周期

​ 8bit——>11周期

​ 6bit——> 9周期

45553ec08a544a9e83894809fc42b944.png

注入模式,可以这样理解:把注入模式看作为中断,若果有注入,注入优先(相较于规则),完成之后在继续规则模式

06f78b4705fc41299c95c7bab4e18624.png

2.1.3 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目

main.c

  1. #include "main.h"
  2. #include "adc.h"
  3. #include "usart.h"
  4. #include "gpio.h"
  5. #include "stdio.h"
  6. void SystemClock_Config(void);

  7. uint32_t ADC_Value;

  8. int main(void)
  9. {
  10.   HAL_Init();
  11.   SystemClock_Config();

  12.   MX_GPIO_Init();
  13.   MX_ADC1_Init();
  14.   MX_USART2_UART_Init();

  15.   printf("start\r\n");
  16.   while (1)
  17.   {
  18.      HAL_ADC_Start(&hadc1);     //启动ADC转换
  19.      HAL_ADC_PollForConversion(&hadc1, 50);   //等待转换完成,50为最大等待时间,单位为ms

  20.      if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
  21.     {
  22.       ADC_Value = HAL_ADC_GetValue(&hadc1);   //获取AD值

  23.       printf("ADC1 Reading : %d \r\n",ADC_Value);//采样的值
  24.       printf("PA4 True Voltage value : %.4f \r\n",ADC_Value*3.3f/4096);
  25.           //转化后的电压值
  26.       }
  27.           HAL_Delay(1000);
  28.   }
  29. }
复制代码

2.2 单通道+DMA
2.2.1 STM32CUBEMX配置与单通道大致一样,需要修改的见下图(开启DMA请求,并在DMA配置中添加ADC1)

ddf17ffe5ce64e89af7b8eac1f9cfd48.png

——>注意:DMA配置里要选择 Mode选择Circular,Data Width选择 Word,(如果是HalfWord,则会将采集到的数值进行合并,范围超出2^12 = 4096)

c488036bbd5b456d8052ef2cc487438f.png

2.2.2 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目

main.c
  1. #include "main.h"
  2. #include "adc.h"
  3. #include "dma.h"
  4. #include "usart.h"
  5. #include "gpio.h"
  6. #include "stdio.h"

  7. void SystemClock_Config(void);

  8. uint32_t ADC_Value[100];
  9. uint8_t i;
  10. float ad1 = 0;

  11. int main(void)
  12. {
  13.   HAL_Init();
  14.   SystemClock_Config();

  15.   MX_GPIO_Init();
  16.   MX_DMA_Init();
  17.   MX_ADC1_Init();
  18.   MX_USART2_UART_Init();
  19.   //开启ADC_DMA采集
  20.   HAL_ADC_Start_DMA(&hadc1, ADC_Value, 100);//DMA自动把对应的通道值放入ADC_Value数组内

  21.   while (1)
  22.   {
  23.     //数据处理 与 DMA存值 不同步 ,在这里判断下转换是否完成,完成则进行数据处理
  24.      if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
  25.      {         
  26.                   for(i = 0; i < 100; i++)//数据处理 与 DMA存值 不同步  
  27.                   {
  28.                         ad1 += ADC_Value<i>;      
  29.                   }  
  30.                        ad1 /=  100.0;
  31.                        printf("PA4 Reading Vol Value: %.4f \r\n", ad1*3.3f/4096);
  32.                        HAL_Delay(500);
  33.         
  34.      }

  35.   }
  36.   /* USER CODE END 3 */
  37. }</i>
复制代码

DMA:搬运数据思想
将一块内存的数据搬到另外一块内存,(注意内存可位于系统内部,也可位于外部设备,其实就是一块地址,形象的可理解为buf[], 某个寄存器等。)
在搬运的时候,1次搬运的数据大小必须是2的n次方(n= 0,1…),只要设置好相应外设的dma映射通道号(这一部分是由hardware designer设计的),以及其他相应配置,并使能DMA功能, 它就自动开始搬运了,(内存到内存这种方式是相对较快的)。

2.3 多通道+DMA
2.3.1 STM32CUBEMX配置与单通道+DMA大致一样,需要修改的见下图(2个通道IN4、IN6, 开启连续扫描模式;并注意Rank下选择不同的通道,不配置默认通道 相同,我刚开始没有配置,结果2个引脚采集的值一样,浪费了半天时间找原因…)

b72fff4c88c243a2a0382b90a9a193a7.png
6c1dc734495f40d099b7646fc5c47ffd.png

2.3.2 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目

main.c

  1. #include "main.h"
  2. #include "adc.h"
  3. #include "dma.h"
  4. #include "usart.h"
  5. #include "gpio.h"
  6. #include "stdio.h"

  7. uint32_t ADC_1 = 0, ADC_2 = 0;
  8. uint32_t ADC_Value[100];
  9. uint8_t i;

  10. int main(void)
  11. {
  12.   HAL_Init();

  13.   SystemClock_Config();

  14.   MX_GPIO_Init();
  15.   MX_DMA_Init();
  16.   MX_ADC1_Init();
  17.   MX_USART2_UART_Init();

  18.   HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 100);//100数据量
  19.   printf("ADC Sampling start\r\n");

  20.   while (1)
  21.   {

  22.       HAL_Delay(500);//这里不加延时,采集输出值第一次为0
  23.       for(i=0; i<100;)
  24.      {
  25.       ADC_1 = ADC_Value[i++];   
  26.       ADC_2 = ADC_Value[i++];
  27.      }
  28.       printf("double channel ADC test\r\n");
  29.       printf("ADC_1 = %1.4f\r\n", ADC_1*3.3f/4096);
  30.       printf("ADC_2 = %1.4f\r\n", ADC_2*3.3f/4096);

  31.   }



  32. }
复制代码

函数HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);//第三个参数我还是不明白,但是支持数据量,库函数这样解释:

很多人说是数据量,不是长度,我很纳闷(数据量分2种情况:

1.单通道 1次将采集的length个数据存放到存储区,然后执行下一次采集存放,
2.多通道 1次将采集的length个数据存放到存储区,然后执行下一次采集存放,length应为通道数的倍数 保证每个通道的数据量持平
————————————————
版权声明:gfanbei


f38a2a0d7066494a9a6e62bbd4d9d7be.png
收藏 评论0 发布时间:2022-11-1 17:10

举报

0个回答

所属标签

相似分享

官网相关资源

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