二十二、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;		//模式,选择独立模式,即单独使用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_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;		//模式,选择独立模式,即单独使用ADC1
	ADC_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的数,在非扫描模式下,只能是1
	ADC_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转换的结果
}
相关推荐
飞睿科技2 小时前
超越蓝牙与Wi-Fi,UWB技术如何解锁手机下一波创新浪潮?
嵌入式硬件·物联网·智能手机·uwb
点灯小铭2 小时前
基于单片机的交流功率测量仪设计与实现
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
星辰pid4 小时前
STM32基于OLED的多级菜单(控制步进/无刷电机/舵机,含FLASH存储数据掉电不丢失)
stm32·单片机·嵌入式硬件
飞睿科技5 小时前
乐鑫ESP32-C2小尺寸高性价比,物联网应用的理想无线连接方案
嵌入式硬件·物联网·智能路由器
RFID舜识物联网5 小时前
NFC与RFID防伪标签:构筑产品信任的科技防线
大数据·人工智能·科技·嵌入式硬件·物联网·安全
FanXing_zl5 小时前
在整数MCU上实现快速除法计算:原理、方法与优化
单片机·嵌入式硬件·mcu·算法·定点运算
Dunkle.T7 小时前
单片机中NRST引脚复用为GPIO
单片机·嵌入式硬件·复用·py32f002bl15s7·nrst
逆小舟7 小时前
【STM32】中断
stm32·单片机·嵌入式硬件
我先去打把游戏先7 小时前
ESP32C3开发指南(基于IDF):console控制台命令行交互功能
笔记·嵌入式硬件·mcu·物联网·学习·esp32·交互