6. 模数转换器ADC
6.1 ADC结构及寄存器说明
6.2 ADC设计实例
6.2.1 用ADC1规则通道实现外部模拟信号的模数转换
6.2.2 用ADC1注入通道实现内部温度传感器的温度测量
6.1 ADC结构及寄存器说明
- 模数转换器ADC的主要功能是将模拟信号转化为数字信号以便于微控制器进行数据处理
- ADC按转换原理分为逐次比较型、双积分型和∑-∆型
- 逐次比较型ADC通过逐次比较将模拟信号转化为数字信号转换速度快,但精度较低,是最常用的ADC
- 双积分型ADC通过两次积分将模拟信号转化为数字信号,精度高,抗干扰能力强,但速度较慢,主要用于万用表等测量仪器
- ∑-∆型ADC具有逐次比较型和双积分型的双重优点,正在逐步广泛地得到应用
- STM32ADC是12位逐次比较器,多达18个通道,可测量16个外部和2个内部信号源,各通道的转换可以单词、连续、扫描或间断模式执行,转换结果可以左对齐或右对齐方式存储在16位数据寄存器中
- STM32ADC的模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阈值
- 输入时钟不得超过14MHz,由PCLK2经分频产生
- STM32ADC主要由模拟多路开关、模拟至数字转换器、数据寄存器和触发选择等部分组成
- 转换通道分为规则通道和注入通道两组
- 规则通道由最多16个通道组成,按顺序转换
- 注入通道由最多4个通道组成,可插入转换
- ADC使用的GPIO引脚
- ADC1的通道16内部与温度传感器相连
通道17内部与参考电源VREFINT相连
- ADC通过20个寄存器进行操作
6.2 ADC设计实例
6.2.1 用ADC1规则通道实现外部模拟信号的模数转换
- 规则通道相关的寄存器及其内容
- ADC规则通道初始化子程序
//ADC1初始化子程序
void Adc1_Init(void)
{
RCC->APB2ENR |= 1<<3; //开启GPIOB时钟
RCC->APB2ENR |= 1<<9; //开启ADC1时钟
GPIOB->CRL &=0xffffff00; //PB.01(IN9)、PB.00(IN8)模拟输入
ADC1->CR1 |= 1<<8; //扫描模式
ADC1->CR2 |= 1<<20; //规则通道外部触发:TIM1_CH1
ADC1->SQR1 |= 1<<20; //规则通道序列长度:2
ADC1->SQR3 |= 9; //第1个转换通道:IN9
ADC1->SQR3 |= 8<<5; //第2个转换通道:IN8
ADC1->CR2 |= 1; //开启ADC
ADC1->CR2 |= 1<<2; //校准ADC
while(ADC1->CR2 & 1<<2); //等待校准完成
}
- ADC规则通道处理子程序
//ADC1处理子程序
void Adc1_Proc(void)
{
if(ADC1->SR & 2) //EOC=1(转换结束)
{
adc1_dat[adc1_num] = ADC1->DR; //读取转换值
if(++adc1_num == 2)
adc1_num = 0;
}
}
6.2.2 用ADC1注入通道实现内部温度传感器的温度测量
- STM32中有一个温度传感器,与ADC1的通道16相连,可以用来测量芯片的温度
- 温度传感器的最大采样时间为17.1ms,温度范围为-40~125°C,温度计算公式如下:
其中:V为温度传感器电压值,N为模数转换后的数字值
- 注入通道相关的寄存器及其内容
- ADC注入通道初始化子程序
//ADC1初始化子程序
void Adc1_Init(void)
{
RCC->APB2ENR |= 1<<3; //开启GPIOB时钟
RCC->APB2ENR |= 1<<9; //开启ADC1时钟
GPIOB->CRL &=0xffffff00; //PB.01(IN9)、PB.00(IN8)模拟输入
ADC1->CR1 |= 1<<8; //扫描模式
ADC1->CR2 |= 1<<20; //规则通道外部触发:TIM1_CH1
ADC1->SQR1 |= 1<<20; //规则通道序列长度:2
ADC1->SQR3 |= 9; //第1个转换通道:IN9
ADC1->SQR3 |= 8<<5; //第2个转换通道:IN8
ADC1->CR2 |= 1<<10; //注入通道自动转换
ADC1->CR2 |= 1<<23; //开启温度传感器
ADC1->SMPR1 |= 5<<18; //SMP16[2:0] =5(55.5)
// (55.5+12.5)/4MHz=17s
ADC1->JSQR |= 0x10<<15; //JSRR[4:0]=0x10(通道16)
ADC1->CR2 |= 1; //开启ADC
ADC1->CR2 |= 1<<2; //校准ADC
while(ADC1->CR2 & 1<<2); //等待校准完成
}
- ADC注入通道处理子程序
//ADC1处理子程序
void Adc1_Proc(void)
{
if(ADC1->SR & 2) //EOC=1(转换结束)
{
adc1_dat[adc1_num] = ADC1->DR; //读取转换值
if(++adc1_num == 2)
adc1_num = 0;
}
if(ADC1->SR & 4) //JEOC=1(注入通道转换结束)
{
ADC1->SR &= ~6; //清除JEOC和EOC
adc1_jdat = ADC1->JDR1; //读取转换值
}
}