STM32CubeMX配置ADC采样(轮询、中断、DMA)

转载:原文链接:https://blog.csdn.net/weixin_46461874/article/details/128686185

STM32CubeMX能够极大减小STM32外设配置的工作量,因此作者也借助空闲时间对STM32CubeMX相关配置进行了学习,本文介绍如何利用STM32CubeMX配置ADC采样,记录了作者学习过程中遇到的问题及解决办法,使大家少走弯路,并方便以后复习

目录

1、单通道轮询

在这里插入图片描述
先选择所使用的MCU,这里我使用的是STM32F407ZGT系列
在这里插入图片描述
修改一下DEBUG功能,否则后续无法调试
在这里插入图片描述
修改时钟,采用外部晶振
在这里插入图片描述
配置一串口,用于打印采集的ADC值
在这里插入图片描述
这里我采用ADC1的通道0,并开启连续采样模式,否则每次开启ADC采样后只进行一次采样
在这里插入图片描述
开启ADC全局中断(如果只采用轮询采样就不用开启,这里开启是为了方便后面演示中断采样)
在这里插入图片描述
修改一下ADC全局中断的优先级
在这里插入图片描述
在HCLK处输入其时钟最高频率168,按回车,其余时钟会自动配置好,一般情况下无需改动
在这里插入图片描述
在这里插入图片描述
勾选上后,每个外设会单独保存至一个.c文件,便于查看
在这里插入图片描述
在这里插入图片描述
生成并打开文件
在这里插入图片描述
在main.h中包含头文件stdio.h
在这里插入图片描述
在usart.c文件中加入fputc函数,加入后才能使用printf函数进行打印数据
在这里插入图片描述

在while循环中添加以上代码,由于开启了连续转换模式,即hadc1.Init.ContinuousConvMode = ENABLE;因此每次转换完成后都要调用HAL_ADC_Stop来关闭ADC;如果不想每次都调用该函数来关闭ADC,可以关闭连续转换模式,即hadc1.Init.ContinuousConvMode = DISABLE,这样每次开启ADC转换以后只会进行一次采样,这样就不需要每次都关闭ADC了
实验现象如下图:
在这里插入图片描述

2、单通道中断

单通道中断采样配置过程与单通道轮询采样相同,利用cubemx配置完成后有两种开始ADC采样的方法
方法一
在这里插入图片描述
在主函数中加入上述代码,__HAL_ADC_ENABLE_IT(&hadc1,ADC_IT_EOC);用于打开ADC转换完成中断,HAL_ADC_Start(&hadc1);用于开启ADC采样,这两个函数一定要放到外设初始化函数的后面,否则串口函数初始化未完成,在ADC中断中使用printf函数可能会卡死
在这里插入图片描述
在adc.c文件中加入上面代码,HAL_ADC_ConvCpltCallback是ADC中断的回调函数,其原型是个弱函数,重新定义后原来的函数就失去作用了
在这里插入图片描述
最后将adc.c文件中的通道转换结束标准修改为ADC_EOC_SEQ_CONV,否则只会进入一次中断
ADC_EOC_SEQ_CONV:在所有通道转换完成后进入中断
ADC_EOC_SINGLE_CONV:单个通道转换完成后进入中断
多个通道时,两种均可采用,单通道采样时需使用ADC_EOC_SEQ_CONV才能连续进入中断(经测试)
最后将程序下载到单片机中,现象如下:
在这里插入图片描述
方法二
我们利用HAL_ADC_Start_IT开启adc中断,该函数比较特殊,调用一次该函数就打开了ADC转换完成中断和开启ADC采样
在这里插入图片描述
在主函数中直接调用HAL_ADC_Start_IT即可

3、单通道DMA

dma有两种模式,分别为circular和normal
circular模式:dma的circular模式只需要调用一次dma开启函数,dma就会持续的搬运数据,提高了数据的刷新速度,但是在circular模式下,不管adc新的一轮数据采集是否完成,有可能直接将旧数据搬运走
normal模式:该模式下,dma启动函数调用一次,dma通道只会搬运一次数据,这样每调一次dma启动函数,dma只会搬运一次数据,等待数据传输完成后再次开启dma启动函数,这样更能保证adc数据采集的可靠性
circular模式:
cubemux配置步骤如下(时钟配置等已略去):
在这里插入图片描述
这里我们同样用ADC1的通道IN0来测试,开启adc连续采集模式
在这里插入图片描述
修改ADC采样时间,通常采样时间越长,adc采样精度越高
在这里插入图片描述
选用dma的circular模式
在这里插入图片描述
返回开启dma连续请求(若不开启,只能进入一次dma采集完成中断函数)

 uint16_t AD_value=0;
 float f_AD_value;

打开工程文件,在文件中添加上面代码,AD_value用于保存测量的adc原值,f_AD_value保存计算得到的电压值

 HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&AD_value,sizeof(AD_value));

在主函数中调用HAL_ADC_Start_DMA开启adc采样,同时开启dma传输数据(调用一次即可)
在这里插入图片描述
最后在dma中断函数中添加上述代码,将adc采集完成的数据打印出来
normal模式:
normal模式下,我们的想法是调用一次HAL_ADC_Start_DMA函数,adc进行一次数据采集,dma搬运一次数据,我们在上面配置完成的代码中做简单修改就能实现
在这里插入图片描述
关闭adc连续采集模式,这样开启一次adc,只会进行一次数据采集
在这里插入图片描述

将dma模式修改为normal
在这里插入图片描述
修改dma中断函数

 HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&AD_value,sizeof(AD_value));

最后在主函数中调用HAL_ADC_Start_DMA开启adc采样,同时开启dma传输数据(每调用一次只会采集一次数据)

4、多通道轮询

在这里插入图片描述
这里用ADC1的通道IN0、IN1、IN2、IN3四个通道作演示,多个通道时必须开启间断模式,并且每个间断组中只有一个通道,否则每次只能读取到每组最后一个通道的值
在这里插入图片描述
设置通道转换顺序

uint16_t AD_value[4]={0};

打开工程文件,创建一数组用于存储四个通道的ADC值

for(i=0;i<4;i++){
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1,10);
AD_value[i]=HAL_ADC_GetValue(&hadc1);
printf("PA%d:%d\r\n",i,AD_value[i]);
printf("PA%d:%.3f v\r\n",i,AD_value[i]*3.3/4096);
}
HAL_Delay(500);

在主循环中添加上述代码,HAL_ADC_Start必须放在for循环中,否则只能采集第一个通道的ADC值;HAL_ADC_PollForConversion用于轮询转换,是一个阻塞函数,等待转换完成,参数10是阻塞时间

5、多通道中断

多通道情况下使用中断来读取数据理论上是可行的,但是读取的数据会混淆,即无法确定读取的数据是属于哪一个通道的,因此我们不使用

6、多通道DMA

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
开启DMA并采用circular模式

uint16_t AD_value[4]={0};

定义一数组用于保存ADC采样值
在这里插入图片描述
在外设初始化函数下面调用 HAL_ADC_Start_DMA(&hadc1,(uint32_t*)AD_value,sizeof(AD_value));启动ADC转换和DMA数据传输
在这里插入图片描述
最后在DMA接收完成中断中将采集到的ADC数据打印出来
经测试:DMA接收中断在数据接收缓冲区满了后触发,这里的缓冲区是数据AD_value[4]

注意:
通常为了方便使用一些滤波算法,我们可以将缓冲区数据创建的更大一些(为通道数的整数倍),这里我们采用了4个通道,我们可以将缓冲数组创建为AD_value[40]
则AD_value[0]、AD_value[4]、AD_value[8]…AD_value[36]均为通道IN0的值
AD_value[1]、AD_value[5]、AD_value[9]…AD_value[37]均为通道IN1的值,
AD_value[2]、AD_value[6]、AD_value[10]…AD_value[38]均为通道IN2的值,
AD_value[3]、AD_value[7]、AD_value[11]…AD_value[39]均为通道IN3的值,

在这里插入图片描述
我们同样在dma接收完成中断中将数据打印出来
在这里插入图片描述
实验现象如上,只打印了一次数据,表示只进入了一次DMA中断中,并且主循环中的程序也不再继续执行,程序卡死了
在这里插入图片描述
可以在进入DMA中断函数时调用HAL_ADC_Stop_DMA来关闭ADC采集,当需要采集ADC的时候再调用 HAL_ADC_Start_DMA即可,这里为了演示在中断函数结束时又重新开启了ADC
在这里插入图片描述
这样就能连续采集打印数据了

  • 30
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值