ARM(12) - ADC 检测光照强度
一、ADC 基本概念
ADC(Analog-to-Digital Converter,模拟数字转换器)的核心功能是将连续的模拟电压信号转换为离散的数字值。常见 ADC 类型及特点:
- 逐次比较型 ADC:精度优于 Flash 型 ADC,速度优于双积分型 ADC,是精度与速度的 “平衡之选”(I.MX6ULL 采用线性逐次逼近算法的 ADC)。
- 双积分型 ADC:精度高、抗干扰能力强,但转换速度慢,适合低速高精度场景(如数字电表)。
- Flash 型 ADC:转换速度极快,但精度较低、硬件复杂度高(需大量比较器),适合高速低精度场景(如视频信号采集)。
ADC 关键参数:
- 量程:ADC 能转换的模拟电压范围,由参考电压决定(待测电压不能超过参考电压)。
- 分辨率:以 “位数” 衡量(如 8 位、10 位、12 位)。12 位 ADC 的数字值范围为
0~4095
(\(2^{12}-1 = 4095\)),位数越多,对电压的 “细分能力” 越强,精度越高。
逐次逼近 二分法
adc:量程:指的是adc能转换的模拟电压的范围,由参考电压决定。
待测·电压不能大于参考电压
分辨率:adc的位数。
12bit
10bit
8bit
二、I.MX6ULL ADC 模块特性
结合芯片手册与代码,I.MX6ULL 的 ADC 模块具有以下特点:
- 采用线性逐次逼近算法,分辨率最高可达 12 位(数字值范围
0~4095
)。 - 采样率最高可达 1MS/s(1 兆次 / 秒),满足多数中速采样场景。
- 支持多外部模拟输入通道(代码中使用
GPIO1_IO01
作为模拟输入示例)。 - 配置灵活:
- 可配置采样时间、转换速度 / 功耗;
- 输入时钟可从多个源选择,还支持低噪声异步时钟源(降低转换噪声);
- 支持转换完成中断、硬件平均等功能;
- 可配置 “自动比较”(与阈值比较,触发中断或标志)。
- 支持校准功能:上电或高精度要求时,需执行校准以提升转换精度。(自校准功能)
Feature 特点/特性
模数转换器框图
两个引脚的差值(稳定)作为------》参考电压
ADC外部信号
时钟选择和分频
三、寄存器和引脚配置(查手册)
引脚
电气特性 用带参宏配置
寄存器
ADLSMP
长采样 -》 时钟周期长 --越短越好
GC寄存器
HC【0】 寄存器
三、ADC 驱动代码分析(裸机实现)
以下是 ADC1 模块驱动代码,包含
ADC 校准
初始化
获取采样值
转换为电压值的功能。
1. 引脚配置(模拟输入使能)
ADC 需要将 GPIO 引脚配置为模拟输入模式,并设置合适的电气属性(如上下拉、驱动能力等)。
代码示例(以 GPIO1_IO01
为例):
// 1. 配置GPIO1_IO01引脚为ADC功能(引脚复用)// 第二个参数"1"表示将引脚复用为ADC功能(具体值由芯片手册定义)IOMUXC_SetPinMux(IOMUXC_GPIO1_IO01_GPIO1_IO01, 1);// 2. 配置引脚电气属性:关闭上拉(PUE=0)IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01, IOMUXC_SW_PAD_CTL_PAD_PUE(0));// 3. 配置引脚电气属性:使能拉电路(PKE=1),确保引脚在未输入时电平稳定IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01, IOMUXC_SW_PAD_CTL_PAD_PKE(1));
2. ADC 校准(提升精度)
校准是为了消除 ADC 内部的偏移误差,确保转换精度。代码中 adc1_Calibration
函数实现校准逻辑:
int adc1_Calibration(void)
{ADC1->GS |= (1 << 1); // 置位GS寄存器bit1,启动校准ADC1->GC |= (1 << 7); // 置位GC寄存器bit7,开始校准while((ADC1->GC & (1 << 7)) != 0); // 等待校准完成(GC bit7清零)return ((ADC1->GS) & (1 << 1)) == 0; // 校准成功时,GS bit1会清零,返回校准结果
}
3. ADC 初始化(模块使能与参数配置)
adc1_init
函数完成 ADC 模块的基础配置:
void adc1_init(void)
{// 1. 配置GPIO1_IO01引脚为ADC功能(引脚复用)// 第二个参数"1"表示将引脚复用为ADC功能(具体值由芯片手册定义)IOMUXC_SetPinMux(IOMUXC_GPIO1_IO01_GPIO1_IO01, 1);// 2. 配置引脚电气属性:关闭上拉(PUE=0)IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01, IOMUXC_SW_PAD_CTL_PAD_PUE(0));// 3. 配置引脚电气属性:使能拉电路(PKE=1),确保引脚在未输入时电平稳定IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01, IOMUXC_SW_PAD_CTL_PAD_PKE(1));// 2. 失能中断(避免初始化时触发中断)ADC1->HC[0] &= ~(1 << 7); // 清除HC[0]的bit7(中断使能位)// 3. 配置CFG寄存器(ADC工作参数,如采样时间、分辨率等)ADC1->CFG = 0;ADC1->CFG |= (2 << 2) | (3 << 0); // 具体位配置需参考芯片手册,此处为示例// 4. 配置GC寄存器,使能ADC模块ADC1->GC = 0;ADC1->GC |= (1 << 0); // 置位bit0,使能ADC// 5. 执行校准并打印结果printf(adc1_Calibration() ? " Calibration completed normally.\n" : "Calibration failed. \n");
}
4. 采样与数字值获取(get_adc_value
)
通过配置 “通道控制寄存器” 启动转换,轮询 “状态寄存器” 等待完成,最后从 “数据寄存器” 读取结果:
unsigned short get_adc_value(void)
{// 1. 配置HC[0](通道0控制寄存器),启动通道0转换ADC1->HC[0] = 0; // 先清零ADC1->HC[0] |= (1 << 0); // 置位bit0(启动转换位),启动通道0的AD转换// 2. 等待转换完成:轮询HS寄存器(状态寄存器)的bit0(通道0转换完成标志)while((ADC1->HS & (1 << 0)) == 0);// 3. 读取转换结果:R[0]为通道0数据寄存器,低12位为有效数据(12位分辨率)return ADC1->R[0] & 0XFFF; // 只保留低12位
}
5. 电压转换(get_adc_volt
)
根据 ADC 分辨率和参考电压,将数字值转换为实际电压(I.MX6ULL 参考电压为 3.3V):
/*** @brief 将ADC采样值转换为实际电压值* @return 电压值(单位:V,范围:0~3.3V)*/
float get_adc_volt(void)
{unsigned short adc_val;adc_val = get_adc_value(); // 获取12位采样值// 电压计算公式:参考电压为3.3V,12位ADC的最大值为4095(对应3.3V)// 采样值与电压成正比:电压 = 3.3V * 采样值 / 4096return 3.3 * adc_val / 4096;
}
6. 主函数(业务逻辑与测试)
主函数初始化系统各模块后,循环采集 ADC 电压并打印:
int main(void)
{// 初始化系统基础模块(时钟、中断、LED、蜂鸣器、按键等)clock_init();system_interrupt_init();led_init();beep_init();key_init();epit1_init();gpt1_init();uart1_init();i2c1_init();adc1_init(); // 初始化ADCfloat voltage = 0;int int_part = 0, dec_part = 0; // 电压整数、小数部分(保留三位小数)while (1){voltage = get_adc_volt(); // 获取电压(单位:V)voltage *= 1000; // 放大1000倍,便于提取三位小数int_part = voltage / 1000; // 整数部分dec_part = (int)voltage % 1000; // 小数部分(三位)printf("ADC Voltage: %d.%03d V\n", int_part, dec_part);delay_ms(100); // 延迟100ms,重复采样}
}
关键知识点总结
- ADC 校准:通过
adc1_Calibration
函数消除硬件偏移误差,是高精度采样的必要步骤。- 引脚配置:通过
IOMUXC_SetPinMux
和IOMUXC_SetPinConfig
将 GPIO 复用为 ADC 输入,并配置电气属性(如禁用上拉、使能拉电路)。- 寄存器操作:
GS
:状态寄存器,用于判断校准状态GC
:全局控制寄存器,用于使能 ADC 和启动校准HC[0]
:通道 0 控制寄存器,用于启动转换和配置中断HS
:转换状态寄存器,用于判断转换是否完成R[0]
:通道 0 数据寄存器,存储转换结果- 数据转换:12 位 ADC 的采样值(0~4095)通过比例计算转换为实际电压(0~3.3V)。
四、实验现象
检测到光照强度