STM32外设-ADC¶
一、ADC简介¶
ADC-模拟数字转换器 ADC可以将引脚上连续变化的模拟电压转化为内存中储存的变量 stm32f1系列内部采用逐次逼近型ADC 输入电源0\~3.3V,输出数字量0\~4095 18个输入通道,16个外部通道,2个内部通道,内部划分为规则组和注入组两个转化单元 模拟看门狗可监测输入电压范围并产生中断
tip: STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道
二、逐次逼近型ADC¶

逐次逼近型ADC(SAR ADC)是一种常见的模数转换器,它通过一种“二分搜索”策略逐步确定输入模拟电压对应的数字值。其工作过程始于采样保持电路对输入电压进行捕获,随后内部数模转换器(DAC)从最高有效位(MSB)开始,逐次产生不同的参考电压与输入电压进行比较。每次比较后,根据比较器的输出结果(0或1)来锁定或舍弃当前位,并调整下一次的参考电压,逐步逼近实际输入值。这一过程就像天平称重,通过依次尝试不同砝码(对应二进制位的权重)来精确测量。SAR ADC在速度、精度和功耗之间取得了良好平衡,因此被广泛应用于中速高精度的数据采集系统、传感器接口和工业控制等领域。
三、stm32-ADC结构¶
ADC框图¶

基本结构¶

输入通道¶

四、ADC转换¶
1、单次转化,非扫描模式¶

2、连续转化,非扫描模式¶

3、单次转化,扫描模式¶

4、连续转化,扫描模式¶

5、其他模式见手册11.3部分¶
6、转化时序¶

7、校准¶
•ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差
•建议在每次上电后执行一次校准
•启动校准前, ADC必须处于关电状态超过至少两个ADC时钟周期
五、代码¶
1、单路ADC¶
使能ADC和GPIO时钟¶
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //开启ADC1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
设置ADC时钟¶
ADC时钟来源于APB2总线,最大14Mhz,进行预分配处理时需注意
GPIO初始化¶
GPIO需设置为模拟输入模式,以采集模拟电压值
规则组通道配置¶
ADC初始化¶
通道数仅需在扫描模式下配置
/*ADC初始化*/
ADC_InitTypeDef ADC_InitStructure; //定义结构体变量
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //模式,选择独立模式,即单独使用ADC1
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据对齐,选择右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部触发,使用软件触发,不需要外部触发
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //连续转换,失能,每转换一次规则组序列后停止
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //扫描模式,失能,只转换规则组的序列1这一个位置
ADC_InitStructure.ADC_NbrOfChannel = 1; //通道数,为1,仅在扫描模式下,才需要指定大于1的数,在非扫描模式下,只能是1
ADC_Init(ADC1, &ADC_InitStructure); //将结构体变量交给ADC_Init,配置ADC1
ADC使能并校准¶
/*ADC使能*/
ADC_Cmd(ADC1, ENABLE); //使能ADC1,ADC开始运行
/*ADC校准*/
ADC_ResetCalibration(ADC1); //固定流程,内部有电路会自动执行校准
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
获取转化值¶
通常情况下,不需要、也不应该手动清除EOC标志。它在您读取ADC转换数据寄存器(DR)时会自动由硬件清除。
uint16_t AD_GetValue(void)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件触发AD转换一次
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); //等待EOC标志位,即等待AD转换结束
return ADC_GetConversionValue(ADC1); //读数据寄存器,得到AD转换的结果
}