从设备地址到寄存器地址:I²C驱动完整流程详解

从设备地址到寄存器地址:I²C驱动完整流程详解

摘要:

在嵌入式开发中,I²C是最常用的外设通信协议之一。很多初学者容易混淆两个概念:

  • I²C设备地址(Device Address)
  • 寄存器地址(Register Address)

实际驱动开发中,我们经常看到类似:

c 复制代码
i2c_write(0x48,0x01,0x80);

那么:

  • 0x48是什么?
  • 0x01是什么?
  • 0x80又是什么?

本文将从通信底层原理开始,完整解析一次I²C读写过程。


一、I²C通信基本结构

1.1 什么是I²C?

I²C(Inter-Integrated Circuit)是一种由 Philips(现 NXP)提出的串行通信协议。

它最大的特点:

  • 两根线完成通信
  • 支持多个设备挂载
  • 每个设备拥有唯一地址

I²C总线包含两根信号线:

信号 作用
SCL 时钟线
SDA 数据线

结构如下:

复制代码
                 MCU
              Master
                 |
        ------------------
        SCL            SDA
        |              |
        |              |

   ----------------------------
   I²C Bus

       |             |
       |             |

  Temperature     EEPROM
     0x48           0x50

其中:

MCU:

  • 负责产生时钟
  • 主动发起通信

称为:

复制代码
Master(主机)

传感器:

  • 被动响应
  • 根据地址接收数据

称为:

复制代码
Slave(从机)

二、I²C设备地址是什么?

2.1 为什么需要设备地址?

假设:

一条I²C总线上连接:

复制代码
MCU

 |
 |
 +----温度传感器
 |
 +----EEPROM
 |
 +----RTC

那么MCU发送数据时:

到底给谁?

所以每个芯片都有一个地址:

例如:

设备 地址
温度传感器 0x48
EEPROM 0x50
RTC 0x68

通信开始:

MCU首先发送:

复制代码
我要找地址0x48的设备

只有地址匹配的芯片响应。


三、I²C地址格式

常见I²C地址:

7bit地址

例如:

复制代码
温度传感器:

0x48

二进制:

复制代码
0100 1000

但是实际传输时:

需要加入读写位。

格式:

复制代码
+------------+-----+
| 地址7bit   |R/W |
+------------+-----+

例如:

写:

复制代码
0x48 <<1 |0

=

0x90

读:

复制代码
0x48 <<1 |1

=

0x91

所以:

复制代码
0x48

不是实际发送的数据

而是设备逻辑地址

四、设备地址 ≠ 寄存器地址

这是I²C驱动最容易理解错误的地方。

例如:

一个温度传感器:

设备地址:

复制代码
0x48

内部:

复制代码
Sensor

地址0x48


内部寄存器:

0x00 温度寄存器

0x01 配置寄存器

0x02 状态寄存器

0x03 ID寄存器

关系:

复制代码
        I²C地址

          |
          |

     找到芯片


          |

          |

     寄存器地址


          |

          |

      找功能


          |

          |

       数据

举个生活例子:

复制代码
城市
 |
小区
 |
楼栋
 |
房间

对应:

复制代码
设备地址
 |
寄存器地址
 |
寄存器数据

五、I²C写寄存器流程

假设:

修改传感器配置寄存器:

复制代码
寄存器:

0x01


写入:

0x80

通信过程:

复制代码
START

↓

设备地址

0x48 + W


↓

寄存器地址

0x01


↓

数据

0x80


↓

STOP

对应时序:

复制代码
SCL

_|‾|_|‾|_|‾|_|‾|_|‾|


SDA

START

0x48

ACK

0x01

ACK

0x80

STOP

最终:

芯片内部:

复制代码
REG[0x01]=0x80

六、I²C读寄存器流程

读取温度:

目标:

复制代码
读取:

0x00寄存器

很多芯片读取需要两步。

第一步:告诉芯片我要哪个寄存器

发送:

复制代码
START

↓

0x48 + W

↓

0x00

↓

STOP

第二步:读取数据

重新开始:

复制代码
START

↓

0x48 + R

↓

DATA

↓

STOP

完整过程:

复制代码
MCU


发送:

设备地址

0x48


↓

寄存器

0x00


↓

重新START


↓

读取数据


↓

25℃

七、STM32 HAL库中的I²C驱动

实际代码:

写寄存器

c 复制代码
uint8_t reg = 0x01;

uint8_t data = 0x80;


HAL_I2C_Master_Transmit(
    &hi2c1,
    0x48<<1,
    &reg,
    1,
    100
);


HAL_I2C_Master_Transmit(
    &hi2c1,
    0x48<<1,
    &data,
    1,
    100
);

对应:

代码 含义
0x48 设备地址
0x01 寄存器地址
0x80 数据

八、Linux I²C驱动流程

Linux中:

应用程序不会直接操作SDA/SCL。

完整链路:

复制代码
应用程序

   |

 read/write/ioctl

   |

 /dev/i2c-x

   |

 I2C Adapter

   |

 I2C Driver

   |

硬件控制器

   |

SDA/SCL

   |

Sensor

九、Linux驱动中的关键结构

Linux:

c 复制代码
struct i2c_client
{
    unsigned short addr;
};

里面保存:

复制代码
设备地址

0x48

读取寄存器:

常见接口:

c 复制代码
i2c_smbus_read_byte_data(
        client,
        0x00
);

这里:

client:

代表:

复制代码
哪个设备

0x00:

代表:

复制代码
哪个寄存器

十、一次完整的数据读取过程

例如:

读取温度。

最终路径:

复制代码
应用程序

read_temperature()


↓

Linux驱动


↓

I2C消息


↓

设备地址

0x48


↓

找到温度芯片


↓

寄存器地址

0x00


↓

读取数据


↓

0x19


↓

转换


↓

25℃

十一、驱动调试常见问题

1. 地址错误

现象:

复制代码
I2C ACK失败

检查:

  • 原理图
  • 芯片手册
  • ADDR引脚

例如:

芯片默认:

复制代码
0x48

但是硬件:

ADDR拉高:

可能变成:

复制代码
0x49

2. 忘记左移

错误:

c 复制代码
i2c_write(0x48)

某些HAL库需要:

正确:

c 复制代码
i2c_write(0x48<<1)

原因:

HAL使用8bit地址。


3. 寄存器地址长度错误

有些芯片:

8bit寄存器:

复制代码
0x00

有些:

16bit寄存器:

复制代码
0x1234

需要根据Datasheet确定。


十二、总结

理解I²C最重要的三个概念:

1. 设备地址

决定:

我要和哪个芯片通信

例如:

复制代码
0x48

2. 寄存器地址

决定:

我要访问芯片里面哪个功能

例如:

复制代码
0x00 温度
0x01 配置

3. 数据

决定:

我要写入什么或者读取什么

例如:

复制代码
0x80

最终关系:

复制代码
I²C通信


设备地址

↓

找到芯片


↓

寄存器地址

↓

找到功能


↓

数据

↓

完成读写

一句话总结:

I²C设备地址负责"找芯片",寄存器地址负责"找芯片内部功能",数据负责"读写具体内容"。理解这三个层级,就掌握了90%的I²C驱动开发基础。


相关推荐
Qt程序员5 小时前
做嵌入式必备|12 个 RTOS 核心机制,建议收藏
嵌入式·嵌入式开发·rtos
susplus1 天前
【51单片机通信协议】串口
51单片机·串口·嵌入式·通信协议
星源~1 天前
zephyr-Linux环境下搭建步骤
linux·mcu·嵌入式开发·zephyr
牛奶yu茶2 天前
数据链路层的MTU
网络·网络通信·通信·通信协议·通信网络
129Lab3 天前
BMS算法快速原型开发:AI辅助实现扩展卡尔曼滤波(EKF)SOC估算从理论到代码落地
python·嵌入式开发·bms·卡尔曼滤波·电池管理系统·soc估算
ocean21035 天前
2025-2026年嵌入式开发大厂面试高频问题
面试·秋招·嵌入式开发·rtos·面经·嵌入式面试
Oflycomm5 天前
物联网终端的“不可能三角”:小尺寸、低功耗、高稳定性如何兼得?
物联网·低功耗·嵌入式开发·无线模组
合天网安实验室5 天前
Modbus协议及其取证的学习笔记
ctf·modbus·通信协议·取证
俊基科技6 天前
AU-60全功能AI语音处理模组:重塑音频边界,定义清晰通话新标准
安全·嵌入式开发·硬件开发·ai降噪·语音模块·回音消除·矿场通讯