ARM架构——ADC 模数转换器

📅 发布时间:2026/7/10 1:34:20 👁️ 浏览次数:
ARM架构——ADC 模数转换器
目录一、ADC 基础概念二、逐次逼近型 ADC三、关键概念解析2.1 量程2.2 分辨率2.3 精度2.4 实际应用选择指南四、IMX6ULL 中的 ADC 模块4.1 硬件配置4.2 关键寄存器配置五、驱动代码实现5.1 自动校准函数5.2 初始化函数5.3 采样与电压转换函数5.4 主函数集成测试六、滤波算法选型与实现6.1 滤波算法对比与选型6.2 均值滤波优化实现七、总结一、ADC 基础概念ADC (Analog-to-Digital Converter)模拟到数字转换器。它是一种电子设备或模块用于将连续变化的模拟信号转换为离散的数字信号以便数字系统如微处理器、微控制器等能够对其进行处理和分析。模拟信号物理世界中连续变化的物理量如温度、光线、压力等数字信号离散的、不连续的信号计算机处理的0和1传感器一种能够探测、感知外部环境信息如温度、光线、压力、运动等并将这些信息转换成电信号通常是电压或电流的装置或器件。ADC 工作流程现实世界物理量 → 传感器 → 模拟电压 → ADC → 数字信号 → 数字系统二、逐次逼近型 ADCADC有多种实现方式其中逐次逼近型ADC在速度和精度间取得了良好平衡速度比双积分型 ADC 快得多精度比 Flash 型 ADC 高得多逐次逼近型 ADC 的核心是一个比较器Comparator和一套 “逐次逼近寄存器SAR” 逻辑。它的转换过程像一个 “猜数字游戏”通过不断折半参考电压逐步确定输入电压对应的二进制每一位MSB到LSB。下图以8位ADC为例展示了将3.8V模拟电压参考电压5V转换为数字信号的过程模数转换过程示例初始化将 8 位数字量的最高位设为 1其余为 0对应电压为 5V/2 2.5V与输入模拟电压如 3.8V比较逐步逼近2.5V 3.8V → 保留最高位 1次高位设为 1对应电压2.5V 1.25V 3.75V3.75V 3.8V → 保留次高位 1第三位设为 1对应电压3.75V 0.625V 4.375V4.375V 3.8V → 第三位设为 0第四位设为 1对应电压3.75V 0.3125V 4.0625V重复此过程直到 8 位全部判定完毕输出结果最终 8 位数字量为11000100十六进制 0xC2十进制 194换算为实际电压实际电压 (采样值 / 2^ADC位数) × 参考电压代入得194 / 256 × 5V 3.7890625V与输入 3.8V 高度逼近。三、关键概念解析2.1 量程定义ADC能够测量的输入电压范围决定因素参考电压注意事项输入电压超过量程会导致失真削顶或损坏器件2.2 分辨率定义指ADC的位数常见位数8位ADC(256级)、10位ADC(1024级)、12位ADC(4096级)、16位ADC(65536级)计算12位ADC的分辨率 3.3V / 4096 ≈ 0.8mV2.3 精度定义与测量结果的绝对准确性相关关键指标偏移误差、增益误差、INL(积分非线性)、DNL(微分非线性)重要提示高精度ADC价格更高需根据实际需求选择2.4 实际应用选择指南量程选择确保信号电压范围在ADC量程内信号太小 → 需先用运放放大信号太大 → 需用电阻分压分辨率选择根据需要的测量精度选择位数例锂电池电压(3.0V-4.2V)12位ADC(4096级)足以满足需求精度考量对绝对准确性要求高的场合需研究数据手册中的精度指标四、IMX6ULL 中的 ADC 模块4.1 硬件配置特性参数分辨率12位0~4095通道数10路ADC1_IN0 ~ ADC1_IN9参考电压外部引脚ADC_VREFH通常接3.3V时钟源支持IPG时钟、异步时钟ADACK附加功能硬件平均、自动校准、比较器、DMA支持4.2 关键寄存器配置寄存器名称核心功能实战配置12 位、通道 1控制寄存器ADCx_HC0中断使能、采样通道选择AIEN0禁用中断、ADCH1选择 ADC1_IN1状态寄存器ADCx_HS转换完成标志位COCO0等待 COCO01表示转换完成数据寄存器ADCx_R0存储采样结果读取低 12 位CDATA [0~11]屏蔽高位无效数据配置寄存器ADCx_CFG分辨率、时钟源、采样时间配置MODE1012 位、ADICLK11异步时钟通用控制寄存器ADCx_GC校准启动、时钟使能CAL1启动校准、ASYNC_CLK_EN1时钟使能通用状态寄存器ADCx_GS校准失败标志CALFCALF0校准成功失败需写1清零五、驱动代码实现5.1 自动校准函数校准是消除器件固有误差、提升采样精度的关键步骤必须在初始化时执行int adc1_calibration(void) { ADC1-GS | (1 1); // 清零CALF校准失败标志写1清零 ADC1-GC | (1 7); // 置位CAL位启动校准 while ((ADC1-GC (1 7)) ! 0); // 等待校准完成CAL位自动清零 if ((ADC1-GS (1 1)) ! 0) { return -1; // 校准失败 } else { return 0; // 校准成功 } }关键逻辑校准过程中需等待 CAL 位清零校准失败后需重新初始化避免带误差采样。5.2 初始化函数初始化流程包含引脚配置→寄存器配置→校准三大核心步骤void adc1_init(void) { // 1. 引脚配置GPIO1_IO01复用为ADC1_IN1禁用上拉 IOMUXC_SetPinMux(IOMUXC_GPIO1_IO01_GPIO1_IO01, 1); // 复用为ADC模式 IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01, IOMUXC_SW_PAD_CTL_PAD_PKE(1) | // 使能引脚保持器 IOMUXC_SW_PAD_CTL_PAD_PUE(0)); // 禁用上拉ADC推荐配置 // 2. 寄存器配置12位分辨率、异步时钟 ADC1-HC[0] ~(1 7); // 禁用转换完成中断 ADC1-CFG 0; // 清空配置寄存器 ADC1-CFG | (2 2); // MODE10 → 12位分辨率 ADC1-CFG | (3 0); // ADICLK11 → 异步时钟ADACK ADC1-GC 0; // 清空通用控制寄存器 ADC1-GC | (1 0); // 使能异步时钟输出 // 3. 启动校准并打印结果 printf(adc1_calibration() 0 ? Calibration OK\n : Calibration Failed\n); }5.3 采样与电压转换函数get_adc_value触发采样并读取 12 位数字量get_adc_volt根据核心公式将数字量转换为实际电压。// 读取ADC采样值12位0~4095 unsigned short get_adc_value(void) { ADC1-HC[0] 0; // 清空通道选择 ADC1-HC[0] | (1 0); // 选择通道1触发单次采样 while ((ADC1-HS (1 0)) 0); // 等待转换完成COCO01 return ADC1-R[0] 0xFFF; // 读取低12位有效数据 } // 转换为实际电压参考电压3.3V float get_adc_volt(void) { return get_adc_value() * 3.3 / 4096; // 核心公式 }5.4 主函数集成测试main.c 中初始化系统资源后循环采样并打印电压值直观验证 ADC 功能int main(void) { system_interrupt_init(); // 系统中断初始化 clock_init(); // 时钟初始化 beep_init(); led_init(); // 其他外设初始化 adc1_init(); // ADC初始化 float adc_volt 0; while (1) { adc_volt get_adc_volt(); // 读取电压 // 格式化打印保留3位小数 int m (int)(adc_volt * 1000) / 1000; int n (int)(adc_volt * 1000) % 1000; printf(ADC Voltage: %d.%03dV\n, m, n); delay_ms(10); // 10ms采样间隔 } return 0; }运行结果串口将持续输出类似 ADC Voltage: 1.234V 的信息反映传感器的实时电压变化。六、滤波算法选型与实现实际应用中采样信号易受电源纹波、电磁干扰影响导致数据波动。文档与图片中提到多种滤波算法以下结合场景选型并实现优化。6.1 滤波算法对比与选型滤波算法核心原理适用场景优点缺点均值滤波多次采样取平均值静态信号如温度、光线实现简单、抑制随机噪声响应慢、不适合动态信号卡尔曼滤波基于概率模型动态修正误差动态信号如运动物体速度、电流响应快、精度高公式复杂、参数难调低通滤波过滤高频噪声、保留低频信号电源纹波干扰严重的场景平滑效果好高频信号失真高通滤波过滤低频噪声、保留高频信号缓慢漂移的信号如压力传感器抑制漂移静态信号误差大6.2 均值滤波优化实现在 get_adc_value 基础上扩展采样 10 次取平均值抑制随机噪声// 均值滤波10次采样取平均 unsigned short get_adc_value_avg(void) { unsigned int sum 0; for (int i 0; i 10; i) { ADC1-HC[0] 0; ADC1-HC[0] | (1 0); while ((ADC1-HS (1 0)) 0); sum ADC1-R[0] 0xFFF; } return sum / 10; // 返回平均值降低波动 }七、总结ADC 是嵌入式系统中连接模拟世界和数字世界的关键组件。在 ARM 架构的 IMX6ULL 处理器中ADC 模块通过寄存器配置和驱动代码实现可以方便地与各种传感器配合使用。掌握 ADC 的使用对于开发基于 ARM 架构的嵌入式系统至关重要。在物联网、工业控制、智能家居等应用中ADC 都能发挥重要作用帮助我们获取和处理各种物理世界的信息。