前言
ADC转换是一个比较简单的模块,但是其中有很多的细节问题需要处理到,这些问题也是我在写程序的时候遇到的。如果是用ADC+DMA,或者是ADC多通道,这些问题相信你也会遇到,接下来将详细展开讨论。
先来看一下开发板中为我们准备的对应资源---电位器。两个的变化范围都是0~3.3v。
其实在另外一个模块中隐藏了一个特殊的电位器。在这个可编程电阻(MCP4017)的W引脚上的位置接入PB14,而PB14刚好有ADC1_IN5的资源,而且它的电阻可变,所以这一点的电位是可以改变的,我们就可以用ADC读取这一点的电位值,到时候可以进行相应的定量计算。
HAL库配置
我的配置以方便写程序出发用的是ADC+DMA的组合,其中包含了单通道(ADC2),还有多通道(ADC1)。
ADC配置
ADC1---有两个通道,对应的引脚如下
先去开启DMA
再回到具体的配置界面
ADC2的配置也是如此,同样记得开启DMA,采样周期也设置成对应的。接下来说说几个我遇到的问题。
ADC问题解析
开启DMA中断导致程序卡死:
在NVIC中查看,DMA的中断是默认开启并且是灰色不可修改的状态。在我自己的程序设计中我并没有用上DMA中断,所以我是关闭的。它造成程序卡死的原因是,ADC开启了连续转换,DMA也设置为软件触发(Circular),所以DMA是一直在快速的不停的调用,这就导致程序在运行的时候会频繁的进入DMA的中断程序,实际上就只是在执行DMA的中断程序,没有执行main函数中的内容,就出现了程序卡死的现象。
解决办法有二:其一就是直接关闭DMA的这个两个中断;其二就是更改采样时间,经过我的测试,对于这个型号的芯片,采样时间至少要设置为247.5Cycles程序就会正常,但是这样设置有个弊端,就是如果你在程序中使用了LCD的显示函数,你会发现启动程序的时候LCD的屏幕是慢慢刷新出来的,说明DMA还是在频繁进入中断,只不过是因为ADC的采样周期设置长了点有了一定的缓冲,使得DMA进入中断的时间间隔拉长了,这个办法我认为没必要采用。
采样周期至少要为6.5Cycles:
这个设置只是我在实际操作的时候发现的,你们要是也出现这种情况就也可以这样设置来修正,有更长的采样周期这个数值就越精确,没什么负面影响。
如果用的是默认的最短的采样周期,我在旋转R37电位器的时候,R38电位器的值有微小的改变,理论上来说他们应该是互相独立的,我R37的改变不应该会改变R38的值。既然二者会互相干扰,那我们就设置更长的采样周期来保证读取数据的精确,来修正这个干扰因素。
ADC数值的存储要用uint16_t而不是uint32_t:
首先我们要知道,ADC的数据范围是0~4095,即它是一个12位的数据,理论上来说按照数据位的对齐,只要有一个合理的数据大小,ADC的值都可以用它们来存储。如果ADC的值较小,就算用uint8_t来存储都没问题,用uint32_t来存储,多余的数据位就会补0,也不会有什么影响。前面所描述的情况都是在ADC单通道转换的情况下,这样的设置都不会有问题,如果是多通道,我们就用数组来存储,但这个数组要设置为存储多大的数据位才行呢。
我的这个BUG就出现在了使用DMA进行ADC多通道读取数据,使用的是这个函数
HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_t Length)
其中出问题就出在 uint32_t *pData,这个指针参数。由于它使用的是uint32_t的数据类型,我就定义了 uint32_t ADC_Data[2],这样一个数组,结果在实操的时候显示出来的ADC的数据非常的奇怪,具体表现在一个通道 ADC_Data[0]的值是一个远远大于4095的数字,超过了它的最大范围,ADC_Data[1]就没有值一直显示为0。最后我把数组的数据类型修改为uint16_t,在传参的时候把数据类型强转为uint32_t就可以正常显示了。后来我又去查找ADC数据位对齐的资料,最后从学姐那得到了具体的解答。(向学姐致敬
标签:赛道,---,DMA,void,蓝桥,LCD,ADC,Data,uint32 From: https://blog.csdn.net/aldrich_131/article/details/143817379