news 2026/9/28 21:00:02

ARM汇编学习笔记(九):从ADC采集到LCD显示:IMX6ULL外设开发全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ARM汇编学习笔记(九):从ADC采集到LCD显示:IMX6ULL外设开发全解析

前言

在嵌入式开发的学习过程中,外设驱动的编写是核心技能之一。IMX6ULL作为一款广泛应用的ARM Cortex-A7处理器,集成了丰富的片上外设资源。本文将结合IMX6ULL开发板,详细梳理ADC(模数转换)、I2C通信优化以及LCD显示原理三个重要模块,从原理图分析到代码落地,彻底搞懂这些常用外设的工作机制。

一、ADC:模拟世界与数字世界的桥梁

1.1 ADC核心概念

ADC(Analog-to-Digital Converter),即模拟到数字转换器。它是一种将连续变化的模拟信号转换为离散的数字信号的电子设备或模块,以便微处理器(如IMX6ULL)能够处理和分析。

  • 模拟信号:物理世界中连续变化的物理量(如温度、光线、压力)。
  • 数字信号:离散的、不连续的信号。
  • 传感器:将外部环境信息转换成电信号(电压或电流)的装置。

1.2 ADC基本原理与架构对比

IMX6ULL的ADC模块采用逐次比较型(SAR)架构,这是嵌入式传感器采集的首选架构。不同ADC架构的对比如下:

架构类型分辨率范围转换速率范围功耗典型应用场景
逐次比较型(SAR)8~16 位10kSPS~10MSPS低传感器采集、电池检测
Flash 型6~10 位100MSPS~1GSPS极高高速信号采集
Σ-Δ 型16~24 位10SPS~100kSPS中低高精度测量
流水线型10~16 位10MSPS~100MSPS中高雷达、医疗成像

逐次比较型ADC的工作流程:SAR ADC通过逐步逼近的方式确定输入电压对应的数字值。它从最高有效位(MSB)开始,依次设置每一位,并将DAC输出与输入电压比较,最终得到最接近的数字表示。

1.3 基准电压与分辨率

基准电压(VREF)是ADC转换的参考标准,决定了可转换的电压范围。IMX6ULL的ADC参考电压通过ADC_VREFH引脚提供,在开发板上通常为3.3V,VREFL接地为0V。

分辨率决定ADC的最小可分辨电压变化。IMX6ULL的ADC支持8/10/12位分辨率配置,通过ADCx_CFG寄存器的MODE位(bit3:2)选择。

转换公式(以12位分辨率、3.3V基准为例):

[
V_{in} = \frac{n \times V_{REF}}{2^{12}} = \frac{n \times 3.3}{4096}
]

其中 ( n ) 为ADC原始值,范围0~4095。例如,采集值为2048时,实际电压 = 2048 × 3.3 / 4096 =1.65V。

1.4 时钟源选择

IMX6ULL的ADC模块有四种时钟源可选,通过ADICLK[1:0]位配置:

ADICLK时钟源
00IPG clock
01IPG clock divided by 2
10Alternate clock (ALTCLK)
11Asynchronous clock (ADACK)

推荐配置:使用ADACK(异步时钟)作为ADC时钟源。ADACK由ADC模块内部生成,不受系统时钟影响,在低功耗模式下也能工作,有助于提高转换精度。

1.5 校准功能(至关重要)

校准是ADC使用前的必要步骤。由于制造工艺的偏差,ADC内部电容阵列可能存在失配,导致转换误差。IMX6ULL提供了自动校准功能,通过以下步骤完成:

  1. 向ADCx_GC寄存器的CAL位(bit7)写1,启动校准。
  2. 硬件自动执行校准,期间CAL位保持为1。
  3. 校准完成后,CAL位自动清零。
  4. 检查ADCx_GS寄存器的CALF位(bit1)判断校准结果:
    • CALF = 0:校准成功
    • CALF = 1:校准失败,需要写1清零后重试

校准建议在任何复位后以及温度发生显著变化后重新执行。

1.6 IMX6ULL ADC寄存器详解

IMX6ULL的ADC模块通过以下关键寄存器配置:

(1)ADCx_HC0(控制寄存器)
位域名称功能典型配置
b7AIEN转换完成中断使能0(轮询模式)
b4~b0ADCH选择ADC通道1(示例)

每次切换通道时会引发一次ADC转换。

(2)ADCx_HS(状态寄存器)
位域名称功能
b0COCO0转换完成标志,读1表示转换完成

启动转换后需轮询此位,等待其置1。

(3)ADCx_R0(数据结果寄存器)
位域名称功能
b11~b0CDATAADC转换结果(低12位)
(4)ADCx_CFG(配置寄存器)
位域名称功能典型配置
b16OVWREN数据覆盖使能0
b15~14AVGS硬件平均次数00
b13ADTRG转换触发选择0(软件触发)
b12~11REFSEL电压参考源选择00(VREFH/VREFL)
b10ADHSC高速配置0
b9~8ADSTS采样时间选择00
b7ADLPC低功耗配置0
b6~5ADIV时钟分频选择00
b4ADLSMP长采样时间配置0
b3~2MODE转换模式(分辨率)10(12位)
b1~0ADICLK输入时钟源选择11(ADACK)
(5)ADCx_GC(通用控制寄存器)
位域名称功能
b7CAL校准启动(写1,读0完成)
b6ADCO连续转换使能
b5AVGE硬件平均使能
b4ACFE比较功能使能
b3ACFGT比较功能“大于”使能
b2ACREN比较功能范围使能
b1DMAENDMA使能
b0ADACKEN异步时钟输出使能
(6)ADCx_GS(通用状态寄存器)
位域名称功能
b1CALF校准失败标志(0成功,1失败,写1清零)

1.7 代码实现:ADC校准与采样

#include"imx6ull.h"#defineVREF3.3f#defineADC_MAX4095.0f/* ADC初始化与校准 */voidadc_init(ADC_Type*base){/* 1. 配置CFG寄存器:12位分辨率,ADACK时钟源 */base->CFG=(2<<2)|/* MODE=10, 12位 */(3<<0);/* ADICLK=11, ADACK *//* 2. 使能ADACK输出 */base->GC|=(1<<0);/* ADACKEN=1 *//* 3. 启动校准 */base->GC|=(1<<7);/* CAL=1 *//* 4. 等待校准完成 */while(base->GC&(1<<7));/* 5. 检查校准结果 */if(base->GS&(1<<1)){/* 校准失败,写1清零后重试 */base->GS|=(1<<1);/* 可在此添加重试逻辑 */}}/* 单次ADC采样(轮询模式) */uint16_tadc_sample(ADC_Type*base,uint8_tchannel){/* 1. 选择通道,启动转换 */base->HC0=channel&0x1F;/* 2. 等待转换完成 */while(!(base->HS&0x01));/* 3. 读取结果 */returnbase->R0&0x0FFF;}/* 多次采样均值滤波 */uint16_tadc_sample_avg(ADC_Type*base,uint8_tchannel,uint8_ttimes){uint32_tsum=0;uint8_ti;for(i=0;i<times;i++){sum+=adc_sample(base,channel);}return(uint16_t)(sum/times);}/* ADC值转电压 */floatadc_to_voltage(uint16_tadc_val){return(adc_val*VREF)/ADC_MAX;}

代码要点说明:

  • 校准必须在初始化时执行,否则转换精度无法保证。
  • 均值滤波可有效降低随机噪声,推荐采样次数为8~16次。
  • 光敏电阻检测时,将光敏电阻与固定电阻串联分压,ADC采集分压点电压。

二、I2C通信优化:多字节地址兼容与LM75驱动

2.1 I2C总线核心概念

I2C(Inter-Integrated Circuit)是一种串行半双工通信总线,核心特点是两根信号线实现多设备互联:

  • SDA(Serial Data):双向数据线
  • SCL(Serial Clock):双向时钟线,由主设备产生
  • 上拉电阻:SDA和SCL需外接(通常4.7KΩ),空闲时保持高电平
  • 主从架构:同一总线中仅1个主设备,可挂载多个从设备

IMX6ULL的I2C特性:共4路I2C控制器(I2C1~I2C4),支持标准模式(100Kbps)和快速模式(400Kbps)。

2.2 I2C核心时序

基础时序单元:

信号定义
起始信号(S)SCL高电平时,SDA从高拉低
停止信号(P)SCL高电平时,SDA从低拉高
数据传输SCL高电平时SDA稳定(有效);SCL低电平时SDA可切换
应答(ACK)从设备在SCL高电平时拉低SDA
非应答(NACK)主设备保持SDA高电平

从设备读操作时序(以LM75读温度为例):

  1. 主设备发送起始信号(S)
  2. 发送从设备地址 + 写标志(0),等待ACK(目的是“告知读哪个寄存器”)
  3. 发送目标寄存器地址(如LM75的温度寄存器0x00),等待ACK
  4. 发送重复起始信号(Sr)(不发停止信号,避免总线释放)
  5. 发送从设备地址 + 读标志(1),等待ACK
  6. 接收数据:前N-1字节后发送ACK;最后1字节后发送NACK
  7. 发送停止信号(P)

2.3 多字节寄存器地址兼容优化

在实际嵌入式开发中,不同外设的寄存器地址长度可能不同(8位、16位甚至24位)。为了增强代码的可重用性和兼容性,需要实现支持多字节寄存器地址的I2C驱动。

优化后的I2C传输结构体:

structI2C_Msg{uint8_tdev_addr;// 从机地址uint32_treg_addr;// 寄存器地址uint8_treg_len;// 寄存器地址长度(1-4字节)uint8_t*data;// 数据缓冲区uint16_tlen;// 数据长度uint8_tdir;// 传输方向:0-写,1-读};

多字节寄存器地址发送实现:

/* 发送寄存器地址(支持多字节) */inti2c_send_reg_addr(I2C_Type*base,uint32_treg_addr,uint8_treg_len){intstatus=0;inti=reg_len-1;for(;i>=0;i--){base->I2DR=(reg_addr>>(8*i))&0xFF;status=i2c_wait_iif(base);if(status!=0)returnstatus;}return0;}

这段代码通过循环从高字节到低字节依次发送寄存器地址,支持1~4字节的寄存器地址长度。

2.4 LM75温度传感器驱动

LM75温度数据格式:温度值为11位有符号数,高字节和低字节组合后右移7位,再乘以0.5得到实际温度值。

#defineLM75_ADDR0x48#defineLM75_TEMP_REG0x00uint8_trcv_buffer[2];floatget_temp_value(void){unsignedshortt=0;structI2C_Msgmsg={.dev_addr=LM75_ADDR,.reg_addr=LM75_TEMP_REG,.reg_len=1,.data=rcv_buffer,.len=2,.dir=I2C_read};i2c_transfer(I2C1,&msg);/* 组合高低字节,右移7位得到11位温度值 */t=(rcv_buffer[0]<<8)|rcv_buffer[1];t=t>>7;returnt*0.5;}

2.5 FPU使能(浮点运算支持)

在ARM Cortex-A7中,使用浮点运算前必须使能FPU,否则会触发异常:

enable_fpu: /* 1. 设置CPACR寄存器使能FPU访问 */ mrc p15, 0, r0, c1, c0, 2 /* 读取CPACR */ orr r0, r0, #(0xF << 20) /* 设置CP10和CP11为完全访问 */ mcr p15, 0, r0, c1, c0, 2 /* 写回CPACR */ /* 2. 使能FPU */ mov r0, #0x40000000 /* 设置FPEXC的EN位 */ vmsr fpexc, r0 /* 写入FPEXC */ /* 3. 配置FPSCR */ mov r0, #0x00000000 /* 清除所有标志位 */ vmsr fpscr, r0 /* 写入FPSCR */ bx lr /* 返回 */

三、LCD显示原理:从RGB到时序控制

3.1 LCD基础概念

  • 分辨率:如800×480、1920×1080,表示横向和纵向的像素点数量。
  • 色域:RGB888(24位,2²⁴色)或RGB565(16位,2¹⁶色)。
  • 刷新率:60Hz、144Hz、200Hz等,表示每秒刷新画面的次数。

3.2 IMX6ULL的eLCDIF控制器

IMX6ULL的LCD控制器名称为eLCDIF(Enhanced LCD Interface),主要特性包括:

  • 支持MPU模式:8080接口,显示屏自带显存
  • VSYNC模式:针对高速数据传输
  • DOTCLK模式:RGB接口(TFT-RGB),本实验使用此模式
  • 支持ITU-R BT.656接口
  • 8/16/18/24/32 bit bpp数据都支持

硬件架构:软件在内存中划出一块显存(Framebuffer),eLCDIF通过AXI总线从显存读取RGB数据到FIFO,再输出到LCD接口。eLCDIF有两个时钟域:外设总线时钟域(让控制器工作)和LCD像素时钟域(控制电子枪移动)。

3.3 RGB LCD信号线

信号全称功能
数据线DATA[23:0]RGB数据(R:G:B = 8:8:8)
PCLKPixel Clock像素时钟,每个时钟传输一个像素
DEData Enable数据使能,有效期间传输有效像素
HSYNCHorizontal Sync行同步信号
VSYNCVertical Sync场同步信号

3.4 RGB LCD时序分析

以800×480分辨率为例,完整的时序包含以下参数:

水平方向:

  • HFP(Horizontal Front Porch):行同步信号前廊
  • HSYNC宽度:行同步信号有效宽度
  • HBP(Horizontal Back Porch):行同步信号后廊
  • 有效像素:800个像素
  • 水平总周期= HFP + HSYNC宽度 + HBP + 800

垂直方向:

  • VFP(Vertical Front Porch):场同步信号前廊
  • VSYNC宽度:场同步信号有效宽度
  • VBP(Vertical Back Porch):场同步信号后廊
  • 有效行数:480行
  • 垂直总周期= VFP + VSYNC宽度 + VBP + 480

这些时序参数必须与LCD数据手册中的规格一致,否则显示会异常。

3.5 eLCDIF关键寄存器

LCDIF_CTRL寄存器(部分关键位):

位域名称功能配置值
[31]SFTRST软件复位0(正常工作)
[30]CLKGATE时钟开关0(开启时钟)
[29]YCBCR422_INPUTRGB接口时0
[19]BYPASS_COUNTDOTCLK模式需设11
[17]DOTCLK_MODEDOTCLK模式使能1
[9:8]LCD_DATABUS_WIDTHLCD数据总线宽度3(24位)
[7:5]WORD_LENGTH输入数据格式取决于bpp
[0]RUN控制器运行1(启动)

其他关键寄存器:

  • V4_TRANSFER_COUNT:设置水平和垂直像素计数
  • V4_CUR_BUF / V4_NEXT_BUF:当前/下一个显存地址(支持乒乓缓冲)
  • CTRL1:中断使能配置(如CUR_FRAME_DONE_IRQ)

3.6 LCD配置步骤

  1. 复用功能与电气特性配置:将GPIO复用为LCD接口
  2. 配置PCLK时钟频率:目标频率如31MHz
  3. 配置eLCDIF:设置DOTCLK模式、数据线宽度、时序参数
  4. 设置显存地址:将Framebuffer地址写入V4_CUR_BUF
  5. 移植图形库:如LVGL、emWin等

3.7 显存与DMA优化

eLCDIF通过DMA从显存直接读取像素数据,不需要CPU干预。在写入显存后,需要确保数据真正写入DRAM后再启动LCD DMA,否则可能出现显示异常(如底部黑屏或花屏)。

解决方案:在memcpy写入显存后,执行内存屏障指令确保数据可见:

/* 写入显存后执行数据同步屏障 */dsb();/* DSB SY - 确保所有写操作完成 */

四、总结

本文从ADC的模拟-数字转换原理出发,详细分析了:

  • ADC模块:SAR架构、校准流程、12位分辨率配置、ADACK时钟源选择
  • I2C通信优化:多字节寄存器地址兼容、LM75温度传感器驱动、FPU使能
  • LCD显示原理:eLCDIF控制器架构、RGB时序参数、显存与DMA优化

嵌入式开发的核心在于理解硬件原理与熟练配置寄存器。三个模块虽然功能不同,但都遵循相同的开发范式:阅读手册理解寄存器 → 配置时钟和引脚 → 初始化外设 → 编写驱动逻辑。

欢迎在评论区交流讨论!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 20:59:33

Linux 使用入门指南

1. Linux 简介Linux 是一款开源的操作系统内核&#xff0c;广泛应用于服务器、嵌入式设备、超级计算机以及个人桌面环境。它以其稳定性、安全性和灵活性著称&#xff0c;是开发者、运维人员和科研工作者的重要工具。Linux 的发行版众多&#xff0c;常见的有 Ubuntu、CentOS、De…

作者头像 李华
网站建设 2026/9/28 20:59:08

为什么很多企业用了AI,却还是没有实质性变化?

2026年&#xff0c;企业家真正要解决的&#xff0c;已经不是“要不要用AI”&#xff0c;而是“如何把AI真正用进公司”。一项来自【权威机构】的研究显示&#xff0c;尽管许多企业已经开始尝试AI技术&#xff0c;但只有少数能够将其转化为实际的业务成果。这组数据背后&#xf…

作者头像 李华
网站建设 2026/9/28 20:59:08

GaussDB 事务与锁机制:MVCC 可见性、八级表锁与死锁检测

事务与锁是关系型数据库的核心机制&#xff0c;也是理解并发控制的基础。本文整理 GaussDB 中事务管理、MVCC 元组可见性、表级锁分级以及死锁检测相关的知识点。一、事务基础 GaussDB 支持显式事务和隐式事务&#xff1a; 隐式事务&#xff1a;单条语句自动提交&#xff0c;不…

作者头像 李华