本帖最后由 风雨欲来ds 于 2021-8-31 19:38 编辑

在实际项目开发中,经常都有使用ADC的做模数转换的应用,比如电池电量的采集,温度采集,电机应用中的过电流的检测等,都需要要用到模数转换等。普通的单片机里面一般都具备ADC模块,一般都是12bit分辨率的,且具备多种工作模式,比如单次采样,单周期顺序采样,单周期任意次序采样,循环采样等等,各种模式搭配使用,极大方便了多种应用场景中更灵活的应用。
在这选用任意通道工作模式来分析,探究实现采样功能的使用以及配置流程。
1. ADC模块基本采样模式
根据ADC的转换特性,ADC支持单通道单次转换和多通道多次转换。
1.1  单通道、单次转换模式
在此模式下,ADC 执行单个通i道的单次转换(单次采样)(请参见图1),并在转换完成后停止。
ADC1.png

图1
        此模式可用于测量缓慢变化的电池电压,以确定是否可做出低压告警启动保护动作。启动保护动作前应反复测量电池电压:如果电池电压低,马上针对“电池电量低”做相关的处理。
1.2  单通道连续转换模式
单通道连续转换模式可在常规通道转换中对单个通道进行连续不断的转换,即ADC 执行单个通i道的连续(循环)转换(请参见图2)。
ADC2.png
图2
此连续模式允许 ADC 在后台工作。因此,ADC 可在没有任何 CPU 干预的情况下连续转换通道。此外,还可以在循环模式下使用 DMA,从而降低 CPU 负载。还可对多次采样到的值做平滑滤波等运算,从而得到更精准的采样结果;
ADC 模式可用于监视缓慢变化的外部温度等应用。
在用于监测温度时,系统将读取温度并与用户设置的温度进行比较。当温度达到所需温度时,可以做下一步的判断与告警等动作。
1.3  多通道(扫描)、单次转换模式
此模式对一些设定的通道进行依次转换。通过 ADC 默认的顺序,可以使用该 ADC 模式以相同的采样时间和固定的采样顺序对多个通道(最多 10+2个)依次进行配置(请参见图3)。通过这种方式,用户不必在转换过程中停止 ADC,即可以对不同的采样通道进行采样。此模式可以避免额外的 CPU 负载以及繁重的软件设置动作。
ADC3.png
图3
ADC 设定采样率,采样保持时间,使能转换通道,以顺序方式转换 n个通道;
ADC5.png
图4
在应用中还可以结合定时器去触发 ADC进行采样, 或者通过外部引脚的输入信号来触发单次多通道的转换;
当系统的动作取决于多路ADC的采样得到的值(例如,在电机多相电流过电流保护中系统中),可以使用此模式。此模式还可以用于单次测量多个信号(电压、压力、温度等)以确定是否可以启动相应的判断,从而确保设备运行在安全可控范围。
此模式同样可以用于对来自多路温度传感器的信号进行转换,以确定物体的不同温度值。
1.4  多通道(扫描)连续转换模式
多通道(或扫描)连续模式可用于在 ADC 处于独立模式时对一些通道进行依次转换。通过固定序列,能对多个通道以固定的序列的通道(最多 10+2 个)依次进行采样。此模式与多通道单次转换模式相似,只是在完成序列的最后一个通道后不会停止转换,而是从第一个通道重新开始转换并无限继续下去。
参见图 5.        多通道、连续转换模式
                                                 ADC6.png                                                 
图5
2. 任意顺序多通道模式
当前测试使用的MCU中具备ADC 任意通道采样模式,可以配置为任意顺序单次多通道转换(配置为单周期扫描模式);如果只有一个通道,则等同于单通道单次转换模式;
在任意通道配置使能后, 其优先级高于常规通道配置。后续的转换按任意通道配置的方式转换。

ADC7.png
具体功能与详细描述,可以参考单片机的参考手册ADC章节 。
2.1  单次单通道转换模式
在单次单通道转换模式下,A/D 转换相应通道上只执行一次,具体流程如下:
• 软件设置寄存器ADC_ANY_CFGADC_CHANY0ADC_CHANY1,设置转换通道,置CHANY_MDEN(单次转换模式,只需设置CHANY_SEL0)
• 通过软件、外部触发输入及定时器溢出置位ADCR 寄存器的ADST,开始A/D 转换。
A/D 转换完成时,A/D 转换的数据值将存储于数据寄存器ADDATA ADDRn 中。
A/D 转换完成时,状态寄存器ADSTA ADIF 位置1。若此时控制寄存器ADCR ADIE位置1,将产生AD 转换结束中断请求。
A/D 转换期间,ADST 位保持为1A/D 通道采样结束后,ADST 位自动清0A/D 转换器进入空闲模式。
• 若在A/D 转换过程中,软件更新ADC_ANY_CFGADC_CHANY0ADC_CHANY1,硬件不会立即更新这些配置,只会在当前设置的通道都转换结束时更新,然后等待下一次软件置位ADST
该模式仍然支持通过过配置当外部事件(比如TIM TrigExti)触发转换时序。
按上述流程,实现对通道5做单通道单次转换为配置:
void ADC1_AnyChanSingleChannelInit(void)
  • {
  •     RCC->AHBENR |= RCC_AHBENR_GPIOA; //enable GPIOA clock
  •     RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //enableADC1clock
  •     GPIOA->CRL &=  ~(GPIO_CNF_MODE_MASK << GPIO_CRL_CNF_MODE_5_Pos);
  •     GPIOA->CRL |= GPIO_CNF_MODE_AIN << GPIO_CRL_CNF_MODE_5_Pos;
  •     RCC->APB2RSTR |= RCC_APB2RSTR_ADC1RST; //ADC1reset
  •     RCC->APB2RSTR &= ~(RCC_APB2RSTR_ADC1RST); //reset   end
  •     //ADC configure soft trigger, single period mode
  •     //8 fractional frequency
  •     MODIFY_REG(ADC1->ADCFG, ADC_CFGR_PRE, ADCFG_ADCPRE_8);                     
  •     MODIFY_REG(ADC1->ADCR, \
  •                ADCR_ADMD_PERIOD | ADCR_ADMD_CONTINUE | ADCR_ALIGN_LEFT, \
  •                ADCR_ADMD_PERIOD);
  •     //single PERIOD mode , Data right-ALIGNED, discontinue
  •     //enable 3 channels
  •     WRITE_REG(ADC1->ANYCFG, 1);
  •     //Enable chan 5
  •     MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL0, 5<<ADC1_CHANY0_SEL0_Pos);
  •     ADC1->ADCFG |= ADCFG_ADEN;//ADC1enable
  • }
  • 复制代码
    2.2  单次多通道任意顺序转换模式
    在单次多通道任意顺序转换模式下,A/D 转换相应通道上执行一遍按配定顺序的转换,具体流程如下:
    软件设置寄存器ADC_ANY_CFGADC_CHANY0ADC_CHANY1,将需要转换的通道、数量设置好,然后置位CHANY_MDEN
    • 通过软件、外部触发置位ADCR 寄存器的ADST,外部触发可软件配置触发延时,A/D转换方向从CHANY_SEL0 CHANY_SEL15,转换通道数量由CHANY_NUM 配置,CHANY_SEL0 CHANY_SEL15 是任意配置的,可以完全相同,或完全不相同。
    • 每路A/D 转换完成时,A/D 转换的数据值将有序装载到相应通道的数据寄存器中,ADIF转换结束标志被设置,若此时控制寄存器ADCR ADIE 位置1,将产生AD 转换结束中断请求。
    A/D 最后一个通道采样结束后,ADST 位自动清0A/D 转换器进入空闲模式。
    • 若在A/D 转换过程中,软件更新ADC_ANY_CFGADC_CHANY0ADC_CHANY1,硬件不会立即更新这些配置,只会在当前设置的通道都转换结束时更新,然后等待下一次
    软件软件置位ADST
    在一些场景中,需要在执行一遍上述采样后,对采样顺序做调整;或减少采样通道数,以减少采样总体时间,可以通过简单的配置一两个寄存器实现灵活的配置;
    第一次初始化配置与设置转换通道数与顺序:
    void ADC1_AnyChanMultiChannelInit(void)
  • {
  •     RCC->AHBENR |= RCC_AHBENR_GPIOA; //enable GPIOA clock
  •     RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //enableADC1clock
  •     GPIOA->CRL &=  ~(GPIO_CNF_MODE_MASK << GPIO_CRL_CNF_MODE_0_Pos);
  •     GPIOA->CRL |= GPIO_CNF_MODE_AIN << GPIO_CRL_CNF_MODE_0_Pos;
  •     GPIOA->CRL &=  ~(GPIO_CNF_MODE_MASK << GPIO_CRL_CNF_MODE_2_Pos);
  •     GPIOA->CRL |= GPIO_CNF_MODE_AIN << GPIO_CRL_CNF_MODE_2_Pos;
  •     GPIOA->CRL &=  ~(GPIO_CNF_MODE_MASK << GPIO_CRL_CNF_MODE_5_Pos);
  •     GPIOA->CRL |= GPIO_CNF_MODE_AIN << GPIO_CRL_CNF_MODE_5_Pos;
  •     GPIOA->CRL &=  ~(GPIO_CNF_MODE_MASK << GPIO_CRL_CNF_MODE_7_Pos);
  •     GPIOA->CRL |= GPIO_CNF_MODE_AIN << GPIO_CRL_CNF_MODE_7_Pos;
  •     RCC->APB2RSTR |= RCC_APB2RSTR_ADC1RST; //ADC1reset
  •     RCC->APB2RSTR &= ~(RCC_APB2RSTR_ADC1RST); //reset   end
  •     //ADC configure soft trigger, single period mode
  •     //8 fractional frequency
  •     MODIFY_REG(ADC1->ADCFG, ADC_CFGR_PRE, ADCFG_ADCPRE_8);                     
  •     MODIFY_REG(ADC1->ADCR, \
  •                ADCR_ADMD_PERIOD | ADCR_ADMD_CONTINUE | ADCR_ALIGN_LEFT, \
  •                ADCR_ADMD_PERIOD);
  •     //single PERIOD mode , Data right-ALIGNED, discontinue
  •     //enable 3 channels
  •     WRITE_REG(ADC1->ANYCFG, 4);
  •     //Enable chan 0,2,5, 7
  •     MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL0, 0<<ADC1_CHANY0_SEL0_Pos);
  •     MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL1, 2<<ADC1_CHANY0_SEL1_Pos);
  •     MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL2, 5<<ADC1_CHANY0_SEL2_Pos);
  •     MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL3, 7<<ADC1_CHANY0_SEL3_Pos);
  •     ADC1->ADCFG |= ADCFG_ADEN;//ADC1enable
  • }
  • 复制代码
    第二次变换通道:
    void Modidfied_AnyChanMultiChannel(void)
  • {
  •     MODIFY_REG( ADC1->CHANY0, \
  •                 ADC1_CHANY0_SEL0 | ADC1_CHANY0_SEL1 | \
  •                 ADC1_CHANY0_SEL2 |ADC1_CHANY0_SEL3, \
  •                 (2<<ADC1_CHANY0_SEL0_Pos) | (0<<ADC1_CHANY0_SEL1_Pos) |\
  •                 (7<<ADC1_CHANY0_SEL0_Pos) | (5<<ADC1_CHANY0_SEL1_Pos));
  • }
  • 复制代码
    第三次变化通道:
    void Modidfied_AnyChanMultiChannelB(void)
  • {
  •     MODIFY_REG( ADC1->CHANY0, \
  •                 ADC1_CHANY0_SEL0 | ADC1_CHANY0_SEL1 | \
  •                 ADC1_CHANY0_SEL2 |ADC1_CHANY0_SEL3, \
  •                 (5<<ADC1_CHANY0_SEL0_Pos) | (0<<ADC1_CHANY0_SEL1_Pos) |\
  •                 (2<<ADC1_CHANY0_SEL0_Pos) | (7<<ADC1_CHANY0_SEL1_Pos));
  • }
  • 复制代码
    2.3  多通道任意顺序连续扫描模式
    在连续扫描模式下,A/D 转换通道依软件配置一直执行,直到软件禁止。具体流程可以认为是单次多通道任意顺序转换模式的自动多次循环。相关的应用还可以结合外部触发功能与DMA传输,实现更多灵活的应用。