二十二、STM32的ADC(二)(ADC单通道)
前言:根据上一章节“二十一、STM32的ADC(一)(ADC介绍)”的介绍我们本章节来实现ADC单通道模式,单次转换非扫描模式的代码。
目录
一、API详解
二、接线图
三、代码实现
切换为连续非扫描
一、API详解
1.void ADC_DeInit(ADC_TypeDef* ADCx);
将指定 ADC 外设寄存器复位到默认复位状态;
2.void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
用 ADC_InitTypeDef 所描述的配置初始化 ADC(设置对齐、扫描模式、触发、连续/单次模式等)。
3.void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct);
把 ADC_InitTypeDef 结构体填充为库提供的默认安全值(方便调用者只修改需要的字段)。
4.void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
使能或失能指定 ADC 的电源/功能(开/关 ADC)。
5.void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
开启或关闭 ADC 的 DMA 请求(把转换完成事件通过 DMA 传输到内存)。
6.void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);
使能/禁用 ADC 的中断源(例如 EOC — 转换结束中断、AWD — 模拟看门狗中断等)。
7.void ADC_ResetCalibration(ADC_TypeDef* ADCx);
开始复位 ADC 校准寄存器(清除上一次校准结果),为后续校准做准备。
8.FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
查询 ADC_ResetCalibration() 的完成状态。
9.void ADC_StartCalibration(ADC_TypeDef* ADCx);
启动 ADC 的校准过程(硬件自动调整偏置以提高精度)。
10.FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);
检测校准过程是否完成。
11.void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
开启或关闭软件触发转换(当你使用软件触发开始常规组转换时调用)。
12.FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);
查询软件启动转换的状态(判断转换是否在进行/已启动)。
13.void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);
在“扫描 + 间断(discontinuous)”模式下配置每次间断所转换的通道数量。
14.void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
使能或禁用离散(间断)模式(Discontinuous Mode)。
15.void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
配置常规序列(regular sequence)中的某一路通道:指定通道号、序号(Rank)、采样时间。
16.void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
使能或禁用外部触发对常规转换组的控制。
17.uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
读取最近一次常规组转换的结果(数据寄存器 DR 的值)。
18.uint32_t ADC_GetDualModeConversionValue(void);
在 双 ADC 联合 (dual mode) 下,返回合并的转换结果(ADC1/ADC2 同步或交叉模式的组合结果)。
19.void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
使能或禁用注入组(injected group)的自动触发转换。
20.void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
使能或禁用注入通道的间断模式。
21.void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv);
配置注入组转换的外部触发源(例如某个定时器事件)。
22.void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
使能或禁用注入组的外部触发。
23.void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
使用软件启动注入组转换(或停止)。
24.FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx);
查询软件启动注入转换命令的状态(是否已启动或完成)。
25.void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
配置注入序列(injected sequence)中的某一路通道:通道号、注入序列中的位置(Rank)、采样时间。
26.void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length);
配置注入序列的长度(注入组中将要采样的通道数)。
27.void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset);
为指定的注入通道设置偏移值(硬件支持注入通道输出减去某个偏移,用于校正/补偿)。
28.uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);
读取指定注入通道最近一次的转换结果。
29.void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);
配置并使能/禁用模拟看门狗(Analog Watchdog),用于监测 ADC 输入是否超出设定阈值。
30.void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold);
设置模拟看门狗的高阈值与低阈值(ADC 值范围内)。
31.void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);
指定某一路通道为模拟看门狗的监测对象(单通道模式)。
32.void ADC_TempSensorVrefintCmd(FunctionalState NewState);
使能或禁用内部温度传感器和内部参考电压(Vrefint)。注意:这个函数在库里通常无 ADCx 参数,
33.FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
查询 ADC 的指定标志位(例如 EOC、JEOC、AWD、STRT 等)。
34.void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
清除 ADC 的某个(或多个)标志位。
35.ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);
查询 ADC 指定中断源的中断挂起/使能状态(中断逻辑是否触发)。
36.void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);
清除 ADC 指定中断的挂起/待处理位(Pending bit),以结束中断。
二、接线图

三、代码实现
1.adc初始化
void AD_Init(void)
{/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //开启ADC1的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟/*设置ADC时钟*/RCC_ADCCLKConfig(RCC_PCLK2_Div6); //选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA0引脚初始化为模拟输入/*规则组通道配置*/ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); //规则组序列1的位置,配置为通道0/*ADC初始化*/ADC_InitTypeDef ADC_InitStructure; //定义结构体变量ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //模式,选择独立模式,即单独使用ADC1ADC_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的数,在非扫描模式下,只能是1ADC_Init(ADC1, &ADC_InitStructure); //将结构体变量交给ADC_Init,配置ADC1/*ADC使能*/ADC_Cmd(ADC1, ENABLE); //使能ADC1,ADC开始运行/*ADC校准*/ADC_ResetCalibration(ADC1); //固定流程,内部有电路会自动执行校准while (ADC_GetResetCalibrationStatus(ADC1) == SET);ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1) == SET);
}
2.获取ad转换值
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转换的结果
}
3.主函数
uint16_t ADValue;
float Voltage; //定义电压变量int main(void)
{OLED_Init(); AD_Init(); OLED_ShowString(1, 1, "ADValue:");OLED_ShowString(2, 1, "Voltage:0.00V");while (1){ADValue = AD_GetValue(); //获取AD转换的值Voltage = (float)ADValue / 4095 * 3.3; //将AD值线性变换到0~3.3的范围,表示电压OLED_ShowNum(1, 9, ADValue, 4); //显示AD值OLED_ShowNum(2, 9, Voltage, 1); //显示电压值的整数部分OLED_ShowNum(2, 11, (uint16_t)(Voltage * 100) % 100, 2); //显示电压值的小数部分Delay_ms(100); //延时100ms,手动增加一些转换的间隔时间}
}
切换为连续非扫描
1.初始化
void AD_Init(void)
{/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //开启ADC1的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟/*设置ADC时钟*/RCC_ADCCLKConfig(RCC_PCLK2_Div6); //选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA0引脚初始化为模拟输入/*规则组通道配置*/ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); //规则组序列1的位置,配置为通道0/*ADC初始化*/ADC_InitTypeDef ADC_InitStructure; //定义结构体变量ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //模式,选择独立模式,即单独使用ADC1ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据对齐,选择右对齐ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部触发,使用软件触发,不需要外部触发ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //连续转换,失能,每转换一次规则组序列后停止ADC_InitStructure.ADC_ScanConvMode = DISABLE; //扫描模式,失能,只转换规则组的序列1这一个位置ADC_InitStructure.ADC_NbrOfChannel = 1; //通道数,为1,仅在扫描模式下,才需要指定大于1的数,在非扫描模式下,只能是1ADC_Init(ADC1, &ADC_InitStructure); //将结构体变量交给ADC_Init,配置ADC1/*ADC使能*/ADC_Cmd(ADC1, ENABLE); //使能ADC1,ADC开始运行/*ADC校准*/ADC_ResetCalibration(ADC1); //固定流程,内部有电路会自动执行校准while (ADC_GetResetCalibrationStatus(ADC1) == SET);ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1) == SET);ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件触发AD转换一次
}
2.获取adc转换值
uint16_t AD_GetValue(void)
{return ADC_GetConversionValue(ADC1); //读数据寄存器,得到AD转换的结果
}
