一、12位逐次逼近型ADC转换原理
1、ADC原理
ADC中输入的模拟信号是连续的,而输出的数字信号是离散的,所以转换时必须对输入的模拟信号进行采样;然后再把采样值转换成为输出的数字信号;这个过程需要经过采样、保持、量化、编码。
前置滤波器由于采样信号输出的是窄脉冲信号需要抗混叠滤波器来避免高频信号影响基带信号。
采样是将连续的模拟信号转换成时间上离散的采样信号;需要注意的是;根据奈奎斯特采样定理,采样频率必须大于或者等于2陪的采样信号的频率,才可以完整无失真的恢复被采样信号。
AD转换是通过量化这一步骤完成的,
量化器是将参考信号Vref分割成2N个子域,N是数字编码输出的位数。在2^N个子域中分别对应着不同的模拟输入量,量化则要找出不同的模拟量对应的子域,找到之后才可以允许编码器编码输出,这样输入信号某一段就会对应到同一个输出码字,是因为有了最小步长也就是精度,产生了一个码字到另一个码字的转换。因此在转换时间内,被采样的模拟输入信号被转换成等价的数子码输出。
分辨率是ADC可以识别的最小信号变化的能力,有数字和模拟之分。数字分辨是指输出码字的位数,位数越多,分辨率越高。模拟分辨率是指能识别的最小模拟增量。用满刻度表示也就是1bit表示的模拟量,比如:Verf/2^12,取Verf=3.3V,则1bit分辨就是0.8mV。
2、逐次逼近型ADC
逐次比较型A/D转换器,就是将输入模拟信号与不同的参考电压作多次比较,使转换所得的数字量在数值上逐次逼近输入模拟量对应值。
二、STM32F103RCT6 ADC正常工作配置
1、C语言常用位带操作符
(1)清零
若想对一个存储单元清零,即使其全部二进制位为0,只要找一个二进制数,其中各个位符合一下条件:
原来的数中为1的位,新数中相应位为0。然后使二者进行&运算,即可达到清零目的。
a 00101011
b 10010100
c 00000000 //c = a & b
(2)取一个数中某些指定位
若有一个整数a(2byte),想要取其中的低字节,只需要将a与8个1按位与即可。
a 00101100 10101100
b 00000000 11111111
c 00000000 10101100 //c = a & b
(3)保留指定位:
a 01010100
b 00111011
c 00010000 //c = a & b
2、| 按位或
两个相应的二进制位中只要有一个为1,该位的结果值为1。借用逻辑学中或运算的话来说就是,一真为真
应用:将一个数据的某些位定值为1
a 00110000
b 00001111
c 00111111 //c = a | b
3、^ 按位异或
若参加运算的两个二进制位值相同则为0,否则为1
应用:不用临时变量,交换两个值
计算前:
a=3,即011(2);b=4,即100(2)
计算过程:
a=a ^ b; //即111 = 011 ^ 100
b=b ^ a; //即011 = 100 ^ 111
a=a ^ b; //即100 = 111 ^ 011
计算后:
a=100(2)即 4 ;b = 011(2)即 3;
4、~ 取反
~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1变0
5、<< 左移
用来将一个数的各二进制位全部左移N位,右补0
6、>> 右移
将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数,高位补0
2、STM32 ADC模块框图
1) 开启 PA 口时钟,设置 PA1 为模拟输入。
STM32F103RCT6 的 ADC 通道 1 在 PA1 上,所以,我们先要使能 PORTA 的时钟,然后设
置 PA1 为模拟输入。
RCC->APB2ENR|=1<<2; //打开PA1的时钟
GPIOA->CRL&=0XFFFFFF0F; //设置成模拟输入
2) 使能 ADC1 时钟,并设置分频因子。
要使用 ADC1,第一步就是要使能 ADC1 的时钟,在使能完时钟之后,进行一次 ADC1 的
复位。接着我们就可以通过 RCC_CFGR 设置 ADC1 的分频因子。分频因子要确保 ADC1 的时
钟(ADCCLK)不要超过 14Mhz。
RCC->APB2ENR|=1<<9; //ADC1时钟使能
RCC->APB2RSTR|=1<<9; //ADC1复位
RCC->APB2RSTR&=~(1<<9); //ADC复位结束
RCC->CFGR&=~(3<<14); //分频因子设置
RCC->CFGR|=2<<14;
//SYSCLK/DIV2=12M ADC1设置成12M, ADC1不能超过14M!
//否则将导致ADC准确度下降
3) 设置 ADC1 的工作模式。
在设置完分频因子之后,我们就可以开始 ADC1 的模式配置了,设置单次转换模式、触发
方式选择、数据对齐方式等都在这一步实现。
ADC1->CR1&=0XF0FFFF; //工作模式清零
ADC1->CR1|=0<<16; //独立工作模式
ADC1->CR1&=~(1<<8); //非扫描模式
ADC1->CR2&=~(1<<1); //单次转换模式
ADC1->CR2&=~(7<<17);
ADC1->CR2|=7<<17; //软件控制转换
ADC1->CR2|=1<<20; //使用外部触发
ADC1->CR2&=~(1<<11); //右对齐
4) 设置 ADC1 规则序列的相关信息。
接下来我们要设置规则序列的相关信息,我们这里只有一个通道,并且是单次转换的,所
以设置规则序列中通道数为 1(ADC_SQR1[23:20]=0000),然后设置通道 1 的采样周期(通过
ADC_SMPR2[5:3]设置)。
ADC1->SQR1&=~(0XF<<20);
ADC1->SQR1|=0<<20; //只转换在规则序列1
ADC1->SMPR2&=~(7<<3); //通道1采样时间清空
ADC1->SMPR2|=7<<3; //通道1 239.5周期,提高采样时间可以提高采样精确度。
5) 开启 AD 转换器,并校准。
在设置完了以上信息后,我们就开启 AD 转换器,执行复位校准和 AD 校准,注意这两步
是必须的!不校准将导致结果很不准确。
ADC1->CR2|=1<<0; //开启AD转换器
ADC1->CR2|=1<<3; //使能复位校准
while(ADC1->CR2&1<<3); //等待校准结束
//该位由软件复位,硬件自动清除
ADC1->CR2|=1<<2; //开启AD校准
while(ADC1->CR2&1<<2); //等待校准结束
//该位由软件设置,校准结束后并由硬件自动清除
6) 读取 ADC 值。
在上面的校准完成之后, ADC 就算准备好了。接下来我们要做的就是设置规则序列 1 里面
的通道(通过 ADC_SQR3[4:0]设置),然后启动 ADC 转换。在转换结束后,读取 ADC1_DR 里
面的值就是了。
u16 Get_Adc(u8 ch)
{
//设置转换序列
ADC1->SQR3&=0XFFFFFFE0; //规则序列1 通道ch
ADC1->SQR3|=ch;
ADC1->CR2|=1<<22; //启动规则转换通道
while(!(ADC1->SR&1<<1)); //等待转换结束
return ADC1->DR; //返回转换值
}
这里还需要说明一下 ADC 的参考电压, STM32F103RCT6,该芯片没有外部参考电压引脚, ADC 的参考电压直接取自 VDDA,也就是 3.3V。
三、ADC应用举例
1、ADC做触摸按键
2、ADC温度检测,NTC热敏电阻
四、参考文献
https://wenku.baidu.com/view/485726efeff9aef8951e064c.html
STM32 中文参考手册
正点原子 STM32寄存器版
来源:CSDN
作者:qq_38960013
链接:https://blog.csdn.net/qq_38960013/article/details/104608286