STM32的ADC模块

模数转换的原理与应用

一般在电子线路中,信号分为两种:模拟信号 + 数字信号,大多数传感器采集的都是模拟信号,比如温度、湿度、压力....... ,采集的模拟信号再转交给计算机进行处理,计算机处理的是数字信号,其中涉及到模拟量和数字量的转换,会使用模数转换器,也被称为ADC。
image

基本概念
image
image

转换原理
image

(1)取样
image
(2)量化
image
(3)编码
image

转换精度
image

image

内部框图
ADC转换器的工作原理

由于ADC转换器需要结合传感器使用,本次的案例结合光敏电阻为例实现,如下:

image

//===================================================================
// 函数名:ADC1_Init
// 功  能:初始化 ADC1 的规则通道(PC0,复用为 ADC123_IN10)
// 配  置:软件触发、单次转换、12 位分辨率、右对齐、单通道
// 转  换:模拟电压 0~3.3 V 对应数字量 0~4095,1 LSB ≈ 0.806 mV
//===================================================================
void ADC1_Init()
{
	//---------------------- 1. 开启外设时钟 ----------------------
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);    // 使能 GPIOC 时钟(GPIOC 挂载在 AHB1 总线)
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);     // 使能 ADC1 时钟(ADC1 挂载在 APB2 总线)

	//---------------------- 2. 配置 PC0 为模拟输入 ----------------------
	GPIO_InitTypeDef GPIO_InitStructure;                     // 定义 GPIO 初始化结构体,用来装载引脚参数

	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;              // 指定要配置的引脚:PC0
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AN;            // 模拟模式:断开数字输入缓冲、施密特触发器和上下拉,只把电压送给 ADC
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;         // 无上下拉电阻(模拟模式下该位硬件已断开,此处仅作语义标注)

	GPIO_Init(GPIOC, &GPIO_InitStructure);                   // 将结构体中的参数写入 GPIOC 对应配置寄存器

	//--------------------- 3. 配置 ADC 公共寄存器(ADC1/2/3 共用,对应 ADC_CCR) ---------------------
	ADC_CommonInitTypeDef ADC_CommonInitStructure;        // 定义公共配置结构体,装载三个 ADC 共享的工作模式、分频系数、DMA 方式、采样延迟参数

	ADC_CommonInitStructure.ADC_Mode              = ADC_Mode_Independent;         // 独立模式:ADC1 单独完成规则/注入转换,不与 ADC2、ADC3 组成双 ADC 或三 ADC 联合转换
	ADC_CommonInitStructure.ADC_Prescaler         = ADC_Prescaler_Div2;           // ADC 公共时钟 = APB2 时钟 ÷ 2;APB2=84MHz 时得 42MHz
	ADC_CommonInitStructure.ADC_DMAAccessMode    = ADC_DMAAccessMode_1;           // 仅双 ADC 模式下才生效,用来选择多路结果打包传输方式;独立模式下硬件忽略该位,规范写法应为 ADC_DMAAccessMode_Disabled
	ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;  // 仅双 ADC 同步模式下生效,设置主、从两路采样之间延迟 5 个周期;独立模式下硬件忽略该参数

	ADC_CommonInit(&ADC_CommonInitStructure);              // 将结构体中的各项参数一次性写入 ADC_CCR 公共控制寄存器,完成上述公共位配置


	//---------------------- 4. 配置 ADC1 自身参数 ----------------------
	ADC_InitTypeDef ADC_InitStructure;                    						     // 定义 ADC 初始化结构体,装载 ADC1 独立的转换参数

	ADC_InitStructure.ADC_Resolution           = ADC_Resolution_12b;                 // 转换分辨率 12 位:输出范围 0~4095
	ADC_InitStructure.ADC_ScanConvMode         = DISABLE;                            // 关闭扫描模式:规则组只按顺序转换已配置的这一路通道
	ADC_InitStructure.ADC_ContinuousConvMode   = DISABLE;                            // 关闭连续模式:软件触发一次只转换一遍,转完自动停止
	ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;      // 不用外部触发源(定时器/外部引脚),改由软件置位 SWSTART 启动
	ADC_InitStructure.ADC_DataAlign            = ADC_DataAlign_Right;              	 // 结果右对齐:12 位有效数据放在数据寄存器低 12 位,高 4 位补 0
	ADC_InitStructure.ADC_NbrOfConversion      = 1;                                  // 规则组参与转换的通道数量为 1,与单通道配置保持一致

	ADC_Init(ADC1, &ADC_InitStructure);                     						 // 将以上参数写入 ADC1 的控制寄存器

	//---------------------- 5. 配置规则组通道、排名与采样时间 ----------------------
	// 参数依次:指定 ADC 外设 → 选择通道号 → 规则组排名(第几个转换)→ 采样保持时间
	ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);

	//---------------------- 6. 使能 ADC1 ----------------------
	ADC_Cmd(ADC1, ENABLE);                                  // 置位 ADON 位,打开 ADC1 总开关;之后即可通过软件命令启动转换
}
int main()
{
	uint16_t val = 0;
	uint8_t buf[128] = {0};
	Usart1_Init(9600);
	ADC1_Init();

	while(1)
	{
		//开启ADC的转换
		ADC_SoftwareStartConv(ADC1);
		
		//等待转换完成之后才可以读取寄存器的值
		while( ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET );
		
		//获取转换结果并转发给电脑
		val = ADC_GetConversionValue(ADC1);
		
		//输出结果  0 ~ 4095
		sprintf((char *)buf,"val = %d\r\n",val);  //格式化转换
		USART1_SendString((char *)buf);
		
		delay_ms(500);
	}
	
}

image

posted @ 2026-10-26 16:50  !城北徐公.!  阅读(4)  评论(0)    收藏  举报