ARM嵌入式 --- ADC
一、ADC 基础概念核心重点ADC 本质连续的模拟信号→离散的数字信号的转换是嵌入式系统采集外部传感器温度、电压、电流的核心接口。两大核心特性量程ADC 能采集的电压范围如 IMX6ULL 是 0~3.3V。分辨率数字量的精度如 12 位 2^12 4096 级最小分辨电压 3.3V/4095 ≈ 0.8mV。常见类型逐次逼近型IMX6ULL 采用、Σ-Δ 型高精度测量、流水线型高速采集。二、逐次逼近型 ADC核心原理逐次逼近型 ADC 核心是 “二分查找”ADC 内部有 DAC数模转换器和比较器。从最高位MSB到最低位LSB依次试探若 DAC 输出 输入电压 → 保留该位。若 DAC 输出 输入电压 → 清零该位。经过 n 次试探n 为分辨率得到最终数字量。关键流程初始化 → 校准 → 启动转换 → 等待完成 → 读取结果。关键概念解析2.1 量程定义ADC 输入电压的有效范围IMX6ULL ADC 单极性输入为0~3.3V。注意输入电压不能超过量程否则会导致数据饱和全为 0xFFF或损坏芯片。2.2 分辨率定义ADC 能分辨的最小电压变化公式最小分辨电压满量程数字值量程212−13.3V≈0.806mVIMX6ULL 支持8/10/12 位分辨率12 位为最高精度博客重点讲解 12 位配置。2.3 精度区别精度 ≠ 分辨率精度包含误差偏移误差、增益误差、噪声误差。校准作用IMX6ULL 的 ADC 内置自校准功能能消除偏移 / 增益误差提升精度博客代码核心实现校准。2.4 实际应用选择指南应用场景分辨率选择关键要求普通电压采集电池电压12 位满足精度配置简单高精度传感器温湿度12 位 校准需多次采样取平均高速数据采集10/8 位降低转换时间提升采样率三、IMX6ULL 中的 ADC 模块3.1 硬件配置1引脚复用IMX6ULL 的 ADC 引脚需配置为ADC 功能而非 GPIO以 ADC1_IN1 为例引脚GPIO1_IO01→ 复用为ADC1_IN1ALT1 功能。配置函数IOMUXC_SetPinMux/IOMUXC_SetPinConfig与你现有 I2C 代码风格一致。2时钟配置IMX6ULL ADC 时钟源来自peripheral clock默认 66MHz。时钟分频通过CFG寄存器配置推荐分频系数 8时钟 8.25MHz符合 ADC 时钟要求。3.2 关键寄存器配置核心寄存器名称位定义功能实战配置控制寄存器ADCx_HC0AIENbit7转换完成中断使能0 禁用中断查询模式ADCHbit[4:0]采样通道选择0b00001 选择 ADC1_IN1 通道状态寄存器ADCx_HSCOCO0bit0通道 0 转换完成标志等待该位为 1确认转换结束数据寄存器ADCx_R0CDATAbit[11:0]12 位 ADC 转换结果存储仅读取低 12 位屏蔽高位无效数据配置寄存器ADCx_CFGMODEbit[4:2]ADC 分辨率选择0b010 12 位分辨率ADICLKbit[6:5]ADC 时钟源选择0b11 异步时钟源CLK_DIVbit[1:0]输入时钟分频系数0b11 8 分频适配 ADC 时钟要求通用控制寄存器ADCx_GCCALbit7ADC 自校准启动1 启动内部自校准流程ASYNC_CLK_ENbit6异步时钟使能1 使能 ADC 异步时钟SW_STARTbit0软件触发转换1 软件启动 ADC 转换通用状态寄存器ADCx_GSCALFbit1自校准失败标志0 校准成功失败时写 1 清零标志四、ADC驱动代码实现4.1 ADC 初始化函数adc_init功能引脚配置 → 寄存器配置 → ADC 自校准int adc_init(ADC_Type * base) { // 1. 配置引脚为 ADC 功能 IOMUXC_SetPinMux(IOMUXC_GPIO1_IO01_GPIO1_IO01, 1); IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01, 0x10b0); // 2. 关闭通道0防止配置时误触发转换 base-HC[0] ~(1 0); // 3. 配置分辨率时钟分频12位 8分频 base-CFG (0x2 2) | (0x3 0); // 4. 选择软件触发转换 base-GC (0x01 0); // 5. 清除校准失败标志 base-GS | (0x01 1); // 6. 启动自校准 base-GC | (0x01 7); // 7. 等待校准完成 while(base-GC (1 7)); // 8. 判断校准是否成功 if(base-GS (1 1)) return -1; return 0; }引脚配置GPIO1_IO01配置为ALT1→ 复用为ADC1_IN1通道0x10b0为 ADC 输入推荐电气配置HC [0] 关闭通道先清空通道使能位保证配置安全。CFG 寄存器配置bit4~bit2 0x2→12 位分辨率bit1~bit0 0x3→8 分频时钟GC 寄存器配置bit0 1→软件触发转换bit7 1→启动 ADC 自校准GS 状态寄存器bit1为校准失败标志校准后若为 1 → 初始化失败4.2 ADC 读取函数adc_read功能启动转换 → 等待完成 → 读取 12 位结果unsigned short adc_read(ADC_Type * base) { unsigned short adc_value 0; // 1. 选择ADC通道0x1f为内部通道可改为外部通道 base-HC[0] | (0x1f 0); // 2. 启动转换 base-HC[0] (0x1 0); // 3. 等待转换完成标志 while(!(base-HS (1 0))); // 4. 读取低12位有效数据 adc_value base-R[0] 0xfff; return adc_value; }HC [0] 通道选择0x1f内部温度传感器通道若使用外部ADC1_IN1改为0x01启动转换向HC[0]的 bit0 写 1 → 软件启动转换HS 状态寄存器bit0 1表示转换完成循环等待直到该位置 1R [0] 结果寄存器只取低 12 位有效数据 →0xfff屏蔽高位结果范围0 ~ 40954.3 main.c函数int main(void) { // 定义变量存储ADC原始数据 unsigned short data 0; // 1. 系统基础资源初始化 system_irq_init(); // 初始化中断控制器 clk_init(); // 初始化系统时钟 led_init(); // LED初始化可选用于状态指示 beep_init(); // 蜂鸣器初始化可选 key_irq_init(gpio1_io18_handler); // 按键中断初始化 gpt1_init(); // 定时器初始化 uart_init(UART1); // 串口初始化用于打印结果 i2c_init(I2C1); // I2C初始化根据需求可选 // 2. ADC初始化 int flag adc_init(ADC1); // 3. 循环采样、打印电压 while(1) { // 若ADC初始化成功才执行采样 if(!flag) { // 读取ADC原始数据0~4095 data adc_read(ADC1); // 计算公式实际电压 原始数据 * 330 / 4095 // 330 3.3V * 100用于保留两位小数 unsigned int adc_value data * 330 / (4096 - 1); // 串口打印原始数据 实际电压保留两位小数 printf(data 0x%x value %d.%02d\r\n, data, adc_value / 100, adc_value % 100); // 每隔3秒采样一次 delay_ms(3000); } } return 0; }运行结果程序下载到开发板后串口助手会输出传感器的实时电压约为 3.3V五、学习总结ADC 配置完整思路流程引脚配置将 GPIO1_IO01 复用为 ADC 功能并配置电气属性。关闭通道清空 HC [0] 启动位防止配置时误触发转换。核心参数配置通过 CFG 寄存器设置 12 位分辨率 8 分频时钟。触发模式配置通过 GC 寄存器配置为软件触发转换。校准准备清空 GS 寄存器的校准失败标志位。启动自校准置位 GC 寄存器校准位启动 ADC 内部校准。等待校准完成循环等待校准位硬件自动清零。校准结果判断检查校准失败标志判断初始化是否成功。通道选择读取时配置 HC [0] 选择 ADC 采集通道。启动转换软件置位启动位开始 AD 转换。等待完成查询 HS 寄存器状态等待转换结束。读取结果从 R [0] 寄存器读取低 12 位有效采样数据。ADC 配置先引脚、再时钟分辨率、必须校准采集时选通道、软启动、等完成、读数据核心就是寄存器的正确配置与状态判断。ADC 学习重点总结核心原理ADC 完成模拟电压到数字量的转换i.MX6ULL 采用 12 位逐次逼近型结构。关键步骤引脚复用 → 寄存器配置 → 自动校准 → 软件触发 → 结果读取。寄存器核心CFG分辨率 / 时钟、GC触发 / 校准、HC [0]通道 / 启动、HS完成标志、R [0]数据。必备操作ADC 必须执行自校准才能保证采集精度。采集流程选择通道 → 启动转换 → 等待完成 → 读取有效数据。实战要点12 位 ADC 结果范围 0~4095对应 0~3.3V 电压可通过公式换算实际电压。