【STM32+cubemx】0008 HAL库开发:ADC的四种用法:轮询、中断、DMA、定时器触发
ADC即模数转换器,能把模拟量(电压)转换为数字量。
这一节我们讲讲stm32的ADC用法,stm32自带的ADC有四种用法:轮询、中断、DMA、定时器触发。
1)ADC轮询的用法
我们在之前的串口中断工程上修改,以便于打印数值查看。
使用cubemx打开串口中断的工程,然后另存为ADC工程,增加如下设置,启用ADC及其中断:
可以看到选择ADC1,勾选IN0后,右侧PA0引脚自动配置成了ADC输入;在NVIC选项卡下勾选ADC中断使能,这样我们可以在这个工程里演示轮询和中断模式。
到时钟设置选项卡下,更改ADC时钟,因为我们使用的主时钟是72M,ADC的时钟不能太高,所以要分频,如下是分到12M:
然后生成工程代码,在keil中打开,我们先试验轮询模式,即软件开始ADC转换后,一直等到转换完成后,才向后执行,代码如下:
这个代码在初始化ADC之后执行一次校准(不执行这一步也可以,但精度可能会低一些);然后就可以使用ADC轮询转换了,只需要三步:启动转换、等待转换完成、读取转换数据,即可完成一次ADC转换。
这里将转换结果通过串口发出来了,可以看到右下角的串口调试助手的结果显示。Stm32的adc是12位,这里拆成两个字节发送。
2)ADC中断用法
仍然使用上述代码工程,添加中断方式的代码:
在主循环前,启动一次中断转换;然后在主循环中检查标志位,是否已经完成转换(ADC转换完成中断);如果已经转换完成,则读取结果,上传;再启动下一次中断转换:
回调函数中,只修改标志位,使得主循环中可以检测到已发生了转换完成中断:
注意上面的主函数里,使用了一个100ms的延时;主要是因为stm32的ADC转换是很快的,如果不使用延时,会有大量数据通过串口上传,不方便观察。
3)ADC的DMA多通道转换
仍然使用上面的cubemx工程,这次我们配置多个AD通道,使用DMA连续传输。
如下图,选择IN0和IN1两个通道,并启用DMA循环模式:
由于ad值为12位,所以这里DMA传输半字就可以了;当然也可以传输整个字。
然后设置ADC的通道,如下图:
解释一下需要修改的地方:
scan conversion mode是使能扫描模式,因为我们开了两个通道IN0和IN1,两个通道都要有转换;
continuous conversion mode是设置连续转换,即一次完成以后,自动进行下一次转换;
Number of conversion设置为2,因为我们有两个通道;
两个Rank下面设置通道号,因为我们有两个通道IN0和IN1,所以一个rank下选通道0,另一个rank下选择通道1。
Sampling time采样时间,如果资源允许可以选长一点的时间,转换结果更准确。
然后就可以生成工程代码了。
在keil中打开工程,主函数中添加代码如下:
注意这里的HAL_ADC_Start_DMA(&hadc1, ADC_Value, 16); 最后这个参数16,表示的是DMA搬移数据的次数;向ADC_Value及其之后的地址搬移16个数据;我们这里设置了2个通道,所以从首地址开始填入的是交替的两个通道的数据:ADC0、ADC1、ADC0、ADC1…一共16个数。
这里设置为16,是因为太小的数值很快就会执行完一个循环,产生DMA传输中断,时间太短的话会频繁产生中断,导致一直在中断中执行,没有时间执行主循环中的语句。这里是增加搬移数据的次数;也可以设置AD采样时间长一些,那么每次的转换时间变长,也不会产生过多的中断。
另外这里的校准函数一定要放在启动ADC、DMA之前,否则会占用一个通道,之后的AD通道顺序会有问题。
4)定时器触发ADC采样
顾名思义,就是由定时器设定时间,到点就启动ADC采样,这样可以精确控制采样率。
首先设置定时器的计时参数,这里设置为1s(可以不开启定时器中断):
ADC的设置中,要关闭连续转换模式,并且设置为定时器触发:
这里如果连续转换不关闭,会自动连续运行,不受定时器触发的控制。所以要disable。
最后,还要开启ADC中断。
设置好之后就可以生成工程代码了。
在keil中打开工程,重写ADC中断的回调函数,以指示ADC转换好:
main函数中添加如下代码,检测是否转换好,并读取AD值回传:
下载到板子运行,可以看到每1s输出一个ad值,说明实现了定时器触发adc转换的功能。
好了,这一节的内容基本讲完了。
欢迎关注我的公众号,可留言“资料”获取相关资料和软件: