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

基本概念


转换原理

(1)取样

(2)量化

(3)编码

转换精度


内部框图

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

//===================================================================
// 函数名: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);
}
}

作者:bbzhu04@gmail.com ,多有不妥之处,望批评指正
本文原创,欢迎转载;转载请在文章显著位置标明原文链接: href="https://www.cnblogs.com/zhubb/p/23442789"
保留所有权限,未经许可禁止篡改、商用发布。

浙公网安备 33010602011771号