平台:STM32F407ZGT6
STM32CUBEMX-V6.6.1+STM32F4-1.27.1固件包+MDK5.27
目录
前言
STM32F407 有三组 ADC 控制器,其中 ADC1 有多达19个复用通道,可测量16个外部源,芯片内部温度传感器,Vrefint 和 Vbat。
在转换时可分为两组,regular and injected。在转换的过程中,为了转换的顺序可控。这两组都有自己的转换序列,regular 中最多有16个转换序列,injected 最多有4个转换序列。regular 中关于转换序列的规则通道及其顺序,还有转换的总数,都需要写入ADC_SQRx寄存器。injected 中关于转换序列的规则通道及其顺序,还有转换的总数,都需要写入 ADC_JQSR寄存器,详见相关寄存器描述。
在转换的过程中,还有转换模式的选择,有 single,continous,scan,discontinuous 四种模式。
以下实验只讨论 regular 转换组
single
在 single 转换模式下,ADC 只执行一次转换,若是 regular 转换,则将转换数据存储在 ADC_DR 寄存器中。
在 CUBEMX 中的配置参考图1,我这里开启了 IN4 和 IN5 两个通道。
图1
因为配置了 IN4 和 IN5 两个通道,所以在 signal 模式下需要重新配置通道来达到不同通道采集 ADC 的功能,为此,我编写了以下函数,请参考图2。
图2
scan + discontinous
scan + discontinuous 模式,在这转换的四种模式中,并不是每一种都可以单独拿来用。开启 scan 模式是为了扫描转换序列,也就是扫描 ADC_SQRx 寄存器中所选择的所有通道。开启 discontinuous 模式为了单次转换小于等于8个的转换序列。当触发转换时,会在 ADC_SQRx寄存器中去转换接下来的 n 个转换。
所以 scan + discontinuous 模式实现了单次转换数量可配置且非连续,外部触发或软件触发去转换定义在 ADC_SQRx 寄存器中转换序列的功能。这里需要注意的是,由于转换数据只能存储在 ADC_DR 寄存器,加上没有开启 DMA 搬运的功能,所以在这种情况下,为了防止转换数据覆盖而导致丢失, discontinous 的单次转换序列需要选择为1。CUBEMX 的配置请参考图3。
图3
在转换完一条通道之后,会接着按转换序列中定义通道去转换下一条通道,并不需要手动的通道切换。请参考图4 的读程序。
图4
scan+continous+DMA
因为在 regular 转换中,转换的结果只能存放在 ADC_DR 寄存器中,若此刻开启 scan + continous 模式或者单次转换大于一个序列的 scan + discontinuous 模式,在启动转换过程后。是来不及去准确的从 ADC_DR 寄存器读取到对应通道数据的,那么就只能采取 DMA 搬运的方式。参考图5、图6 CUBEMX 的配置,这里采用 scan + continous 的模式去循环转换 IN4 IN5 两个通道的数据,并采用 DMA 搬运的方式。
图5
图6
经过图5,图6的配置后,在工程中添加如下代码,请参考图7。
图7
这里需要注意的是 ad_value 的变量形式,因为 DMA Data Width 设置为 Half Word,所以需要定义为 uint16_t 类型。 HAL_ADC_Start_DMA 函数的第二个传入形参为 uint32_t 类型的指针,所以我们这里要强转为 (uint32_t *)。
遇到的问题
现象:
无论是单次转换模式,还是连续转换+DMA传输的模式,都会遇到一个问题,那就是通道之间会相互干扰。即一个通道电压的变化会微量的影响到其它通道电压的变化。
原因:
多个通道是通过模拟多路开关自动切换的,这就导致,在切换的瞬间上一个通道的电压值会干扰到下一个通道,切换速度越快,影响越大,切换的时间间隔越久,影响越小
解决办法:
1:增大Sampling Time可以一定程度上减小影响
2:在单次转换模式中,可以在转换之间插入一定延时,也可以采用平均求值的方式
3:将通过1和通道2配置到 ADC1 和 ADC2 上面,彻底隔离,单次转换中试过此方法,连续转换+DMA中没试过,有待验证。
4:在AD通道管脚上并联一个100nf左右的电容,没试过,有待验证。