ARM-I2C 驱动优化与 LM75 温度传感器读取实践

1. 引言

本文围绕嵌入式开发中 I2C 驱动的两个典型优化点展开:一是兼容多字节寄存器地址的读写逻辑,二是基于 LM75 温度传感器的数据读取实现。同时补充了 ARM 平台下 FPU 使能的汇编配置,帮助读者在底层驱动开发中快速定位并解决问题。

2. 代码优化:兼容多字节寄存器地址

在 I2C 通信中,部分传感器或外设的寄存器地址不止一个字节。若驱动只按单字节地址处理,会导致高位地址丢失,从而无法正确访问目标寄存器。下面这段代码通过循环逐字节发送寄存器地址,实现多字节地址兼容。

c 复制代码
// 3. 发送要读取的内存地址
int i = reg_len - 1;
for (; i >= 0; i--)
{
    base->I2DR = (reg_addr >> (8 * i)) & 0XFF;
    status = i2c_wait_iif(base);
    if (status != 0) goto stop;
}

上述实现从最高字节开始,依次将寄存器地址的每个字节写入 I2C 数据寄存器,并在每次写入后等待传输完成。这样无论寄存器地址是 8 位、16 位还是 32 位,都能按序完整发送。

3. LM75 温度传感器读取

LM75 是一款常见的 I2C 接口数字温度传感器,温度数据存放在寄存器 0x00 中,共 2 个字节。下面给出基于 I2C 消息结构体的读取实现。

c 复制代码
float get_temp_value(void)
{
    unsigned short t = 0;
    struct I2C_Msg msg = {
        .dev_addr = 0x48,
        .reg_addr = 0x00,
        .reg_len = 1,
        .data = rcv_buffer,
        .len = 2,
        .dir = I2C_read
    };
    i2c_transfer(I2C1, &msg);
    //i2c_read(I2C1, 0x48, 0x00, 1, rcv_buffer, 2);
    t |= (rcv_buffer[0] << 8) | (rcv_buffer[1] << 0);
    t = t >> 7;
    return t * 0.5;
}

读取流程说明:

  • 设备地址为 0x48,寄存器地址为 0x00,读取长度为 2 字节。
  • 通过 i2c_transfer 完成一次完整的读事务。
  • 将两个字节拼成 16 位数据后右移 7 位,得到 9 位有效温度值。
  • 每个 LSB 对应 0.5 摄氏度,因此乘以 0.5 得到实际温度。

4. ARM 平台 FPU 使能配置

在 ARM Cortex-A 系列处理器上,若需要使用浮点运算单元(FPU),必须先完成寄存器配置。下面是一段典型的 FPU 使能汇编代码。

arm 复制代码
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                      // 返回

配置步骤说明:

  • 第一步通过 CPACR 寄存器开放 CP10 和 CP11 协处理器的完全访问权限。
  • 第二步设置 FPEXC 的 EN 位,正式启用 FPU。
  • 第三步清零 FPSCR 标志位,确保浮点运算从干净状态开始。

5. ADC 模拟量采集

ADC(Analog-to-Digital Converter,模拟到数字转换器)是一种电子设备或模块,用于将连续变化的模拟信号转换为离散的数字信号,以便数字系统(如微处理器、微控制器等)能够对其进行处理和分析。这里的模拟信号是狭义的模拟信号,一般指模拟电压信号转换为数字信号。

相关概念说明:

  • 模拟信号:物理世界中连续变换的物理量。
  • 数字信号:一种离散的、不连续的信号。
  • 传感器:能够探测、感知外部环境信息(如温度、光线、压力、运动等),并将这些信息转换成电信号(通常是电压或电流)的装置或器件。

6. 原理图与参考手册分析

IMX6ULL 的 ADC 模块集成于 SoC 内部,参考电压引脚为 ADC_VREFH。在 Mini 底板原理图中,GPIO_1 的 7 号引脚用于 ADC 输入。参考手册中 ADC1 的输入通道与 GPIO 引脚的对应关系如下:

Signal Description Pad Mode Direction
ADC_VREFH Voltage reference high ADC_VREFH - I
ADC1_IN0 Analog channel 1 input 0 GPIO1_IO00 - I
ADC1_IN1 Analog channel 1 input 1 GPIO1_IO01 - I
ADC1_IN2 Analog channel 1 input 2 GPIO1_IO02 - I
ADC1_IN3 Analog channel 1 input 3 GPIO1_IO03 - I
ADC1_IN4 Analog channel 1 input 4 GPIO1_IO04 - I
ADC1_IN5 Analog channel 1 input 5 GPIO1_IO05 - I
ADC1_IN6 Analog channel 1 input 6 GPIO1_IO06 - I
ADC1_IN7 Analog channel 1 input 7 GPIO1_IO07 - I
ADC1_IN8 Analog channel 1 input 8 GPIO1_IO08 - I
ADC1_IN9 Analog channel 1 input 9 GPIO1_IO09 - I

时钟源选择(ADICLK)说明:

  • 00:IPG clock
  • 01:IPG clock divided by 2
  • 10:Reserved
  • 11:Asynchronous clock(ADACK)

ADC 模块还支持自动校准功能,具体原理可阅读参考手册对应章节。

7. ADC 寄存器配置

IMX6ULL 的 ADC 相关寄存器配置要点如下:

寄存器 位域 说明 默认值
ADCx_HC0 AIEN b7 转换完成中断启用/禁用控制 0
ADCx_HC0 ADCH b0-b4 选择 ADC 通道,每次切换通道时会引发一次 ADC 转换 1
ADCx_HS COCO0 b0 判断 ADC 转换是否完成,读 1 表示转换完成,为 0 则未完成 -
ADCx_R0 CDATA b0-b11 ADC 转换完的最终结果,读低十二位 -
ADCx_CFG OVWREN b16 数据覆盖使能 0
ADCx_CFG AVGS b15-b14 硬件平均选择 00
ADCx_CFG ADTRG b13 转换触发选择 0
ADCx_CFG REFSEL b12-b11 电压参考源选择 00
ADCx_CFG ADHSC b10 高速配置 0
ADCx_CFG ADSTS b9-b8 采样时间选择 00
ADCx_CFG ADLPC b7 低功耗配置 0
ADCx_CFG ADIV b6-b5 时钟分频选择 00
ADCx_CFG ADLSMP b4 长采样时间配置 0
ADCx_CFG MODE b3-b2 转换模式选择(分辨率) 10
ADCx_CFG ADICLK b1-b0 输入时钟源选择 11
ADCx_GC CAL b7 校准启动,写 1 启动,读 0 校准完成 -
ADCx_GC ADCO b6 连续转换使能 0
ADCx_GC AVGE b5 硬件平均使能 0
ADCx_GC ACFE b4 比较功能使能 0
ADCx_GC ACFGT b3 比较功能"大于"使能 0
ADCx_GC ACREN b2 比较功能范围使能 0
ADCx_GC DMAEN b1 DMA 使能 0
ADCx_GC ADACKEN b0 异步时钟输出使能 1
ADCx_GS CALF b1 校准失败标志,0 校准成功,1 校准失败,需要写 1 清零 -

8. 光敏传感器与代码编写

光敏传感器的原理图可参考 SmartDraw 图。代码编写主要包含三个步骤:ADC 校准、采样和均值滤波。

在编写代码前,需要理解以下几个核心问题:

  • 什么是 ADC?
  • 什么是 ADC 的基准电压?
  • ADC 的工作原理是什么?
  • 什么是 ADC 的分辨率?常见的分辨率有哪些?
  • 假设采用 12 位分辨率,基准电压为 3.3V,量化结果为 n 时的实际电压应该如何计算?

对于最后一个问题,12 位分辨率下量化结果为 n 时,实际电压的计算公式为:实际电压 = n × 3.3V / 4096。

5. 总结

本文介绍了 I2C 驱动中多字节寄存器地址的兼容写法、LM75 温度传感器的读取流程,以及 ARM 平台 FPU 的使能方法。这些代码片段可直接用于实际驱动开发,也可作为底层调试的参考。建议读者结合具体芯片手册,进一步验证寄存器地址长度和时序配置。

相关推荐
恒锐丰科技林技术员12 小时前
EG2304L 高压半桥驱动芯片:中小功率电力电子方案优选器件
经验分享·嵌入式硬件·硬件工程
OIDCAT14 小时前
CH9433技术解析:一颗芯片搞定CAN总线和9线串口
单片机·嵌入式硬件·工控·调试工具·国产芯片
简单电磁炮14 小时前
关于can的调试
c语言·stm32·单片机
2501_9226395814 小时前
率能半导体 SS6812T双通道H桥驱动芯片:32V/1.0A,覆盖POS打印机、安防相机、办公自动化、游戏机、机器人五大应用场景
单片机·嵌入式硬件·硬件工程
女神下凡14 小时前
芯参谋(77):裸机(无 OS)存储驱动开发指南
arm开发·单片机·嵌入式硬件·设计规范·1024程序员节
weixin_4640780714 小时前
反激原副边之间的Y电容
单片机·嵌入式硬件
花月mmc14 小时前
FPGA数字信号处理与深度学习
嵌入式硬件·深度学习·fpga开发·信号处理
女神下凡15 小时前
芯参谋(76):电源监控复位芯片电路设计指南
arm开发·单片机·嵌入式硬件·fpga开发·设计规范
Tel1992530800415 小时前
旋转变压器型编码器转多种绝对值协议 旋变转SSI/BISS-C/ENDAT2.2 RS422RTU协议+增量 转换器
单片机·自动化·工业自动化·仪器仪表·工控设备
国科安芯15 小时前
LEO卫星里的IO脉冲事件通信,毛刺误触发解析及处理方案
单片机·嵌入式硬件·fpga开发·低轨卫星·商业航天·抗辐射