打印
[其他ST产品]

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

[复制链接]
手机看帖
扫描二维码
随时随地手机跟帖
21
在adc.c文件中加入上面代码,HAL_ADC_ConvCpltCallback是ADC中断的回调函数,其原型是个弱函数,重新定义后原来的函数就失去作用了


使用特权

评论回复
22
工程师犹饿死|  楼主 | 2023-4-18 22:57 | 只看该作者
最后将adc.c文件中的通道转换结束标准修改为ADC_EOC_SEQ_CONV,否则只会进入一次中断
ADC_EOC_SEQ_CONV:在所有通道转换完成后进入中断
ADC_EOC_SINGLE_CONV:单个通道转换完成后进入中断
多个通道时,两种均可采用,单通道采样时需使用ADC_EOC_SEQ_CONV才能连续进入中断(经测试)

使用特权

评论回复
23
工程师犹饿死|  楼主 | 2023-4-18 22:58 | 只看该作者
最后将程序下载到单片机中,现象如下:

使用特权

评论回复
24
工程师犹饿死|  楼主 | 2023-4-18 22:58 | 只看该作者
方法二:
我们利用HAL_ADC_Start_IT开启adc中断,该函数比较特殊,调用一次该函数就打开了ADC转换完成中断和开启ADC采样


使用特权

评论回复
25
工程师犹饿死|  楼主 | 2023-4-18 22:59 | 只看该作者
在主函数中直接调用HAL_ADC_Start_IT即可

使用特权

评论回复
26
工程师犹饿死|  楼主 | 2023-4-18 22:59 | 只看该作者
3、单通道DMA

dma有两种模式,分别为circular和normal
circular模式:dma的circular模式只需要调用一次dma开启函数,dma就会持续的搬运数据,提高了数据的刷新速度,但是在circular模式下,不管adc新的一轮数据采集是否完成,有可能直接将旧数据搬运走
normal模式:该模式下,dma启动函数调用一次,dma通道只会搬运一次数据,这样每调一次dma启动函数,dma只会搬运一次数据,等待数据传输完成后再次开启dma启动函数,这样更能保证adc数据采集的可靠性

使用特权

评论回复
27
工程师犹饿死|  楼主 | 2023-4-18 22:59 | 只看该作者
circular模式:
cubemux配置步骤如下(时钟配置等已略去):

使用特权

评论回复
28
工程师犹饿死|  楼主 | 2023-4-18 23:00 | 只看该作者
修改ADC采样时间,通常采样时间越长,adc采样精度越高

使用特权

评论回复
29
工程师犹饿死|  楼主 | 2023-4-18 23:00 | 只看该作者
选用dma的circular模式

使用特权

评论回复
30
工程师犹饿死|  楼主 | 2023-4-18 23:00 | 只看该作者
返回开启dma连续请求(若不开启,只能进入一次dma采集完成中断函数)

uint16_t AD_value=0;
float f_AD_value;

使用特权

评论回复
31
工程师犹饿死|  楼主 | 2023-4-18 23:01 | 只看该作者
打开工程文件,在文件中添加上面代码,AD_value用于保存测量的adc原值,f_AD_value保存计算得到的电压值
 HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&AD_value,sizeof(AD_value));

使用特权

评论回复
32
工程师犹饿死|  楼主 | 2023-4-18 23:01 | 只看该作者
在主函数中调用HAL_ADC_Start_DMA开启adc采样,同时开启dma传输数据(调用一次即可)

使用特权

评论回复
33
工程师犹饿死|  楼主 | 2023-4-18 23:01 | 只看该作者
最后在dma中断函数中添加上述代码,将adc采集完成的数据打印出来

使用特权

评论回复
34
工程师犹饿死|  楼主 | 2023-4-18 23:02 | 只看该作者
normal模式:
normal模式下,我们的想法是调用一次HAL_ADC_Start_DMA函数,adc进行一次数据采集,dma搬运一次数据,我们在上面配置完成的代码中做简单修改就能实现

使用特权

评论回复
35
工程师犹饿死|  楼主 | 2023-4-18 23:02 | 只看该作者
关闭adc连续采集模式,这样开启一次adc,只会进行一次数据采集

使用特权

评论回复
36
工程师犹饿死|  楼主 | 2023-4-18 23:02 | 只看该作者
将dma模式修改为normal

使用特权

评论回复
37
工程师犹饿死|  楼主 | 2023-4-18 23:02 | 只看该作者
修改dma中断函数

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



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

使用特权

评论回复
38
工程师犹饿死|  楼主 | 2023-4-18 23:03 | 只看该作者
4、多通道轮询

这里用ADC1的通道IN0、IN1、IN2、IN3四个通道作演示,多个通道时必须开启间断模式,并且每个间断组中只有一个通道,否则每次只能读取到每组最后一个通道的值

使用特权

评论回复
39
工程师犹饿死|  楼主 | 2023-4-18 23:03 | 只看该作者


设置通道转换顺序

uint16_t AD_value[4]={0};

使用特权

评论回复
40
工程师犹饿死|  楼主 | 2023-4-18 23:03 | 只看该作者
打开工程文件,创建一数组用于存储四个通道的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是阻塞时间

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则