当前位置: 首页 > news >正文

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,重复采样}
}

关键知识点总结

  1. ADC 校准:通过adc1_Calibration函数消除硬件偏移误差,是高精度采样的必要步骤。
  2. 引脚配置:通过IOMUXC_SetPinMuxIOMUXC_SetPinConfig将 GPIO 复用为 ADC 输入,并配置电气属性(如禁用上拉、使能拉电路)。
  3. 寄存器操作
    • GS:状态寄存器,用于判断校准状态
    • GC:全局控制寄存器,用于使能 ADC 和启动校准
    • HC[0]:通道 0 控制寄存器,用于启动转换和配置中断
    • HS:转换状态寄存器,用于判断转换是否完成
    • R[0]:通道 0 数据寄存器,存储转换结果
  4. 数据转换:12 位 ADC 的采样值(0~4095)通过比例计算转换为实际电压(0~3.3V)。

四、实验现象

检测到光照强度

http://www.dtcms.com/a/389334.html

相关文章:

  • 网格生成引擎:设计原则、关键组件
  • 【开发AI】Spring AI Alibaba:集成AI应用的Java项目实战
  • Spark专题-第二部分:Spark SQL 入门(2)-算子介绍-Scan/Filter/Project
  • Selenium 自动化爬虫:处理动态电商页面
  • 无需Selenium:巧用Python捕获携程机票Ajax请求并解析JSON数据
  • Python版Kafka基础班 - 学习笔记
  • IDEA 查看 Maven 依赖树与解决 Jar 包冲突
  • 【LVS入门宝典】LVS与Nginx、HAProxy的对比:四层(LVS) vs 七层(Nginx)的适用场景
  • 系统安全配置与加固
  • 【AI-Agent】AI游戏库
  • 病毒库更新原理
  • 服务器内存爆炸,日志无报错,通过分析 Dump 文件查找问题原因
  • 【Redis学习】服务端高并发分布式结构演变之路
  • 【JavaScript 性能优化实战】第三篇:内存泄漏排查与根治方案
  • 关于JavaScript性能优化实战的技术
  • 分布式流处理与消息传递——Paxos Stream 算法详解
  • ​​瑞芯微RK3576多路AHD摄像头实测演示,触觉智能配套AHD硬件方案
  • mysql删除数据库命令,如何安全彻底地删除MySQL数据库?
  • vscode中创建项目、虚拟环境,安装项目并添加到工作空间完整步骤来了
  • 如何快速传输TB级数据?公司大数据传输的终极解决方案
  • Linux的进程调度及内核实现
  • 使用BeanUtils返回前端为空值?
  • Windows Server数据库服务器安全加固
  • Linux TCP/IP调优实战,性能提升200%
  • Amazon ElastiCache:提升应用性能的云端缓存解决方案
  • 查找并替换 Excel 中的数据:Java 指南
  • 多线服务器具体是指什么?
  • Golang语言基础篇001_常量变量与数据类型
  • pytest文档1-环境准备与入门
  • MySQL 专题(四):MVCC(多版本并发控制)原理深度解析