I²C 驱动练习 - 简单版
我们将不会编写整个驱动程序,只会做第一步:驱动程序编写的 hello world
,即读取传感器的设备 ID。这个版本被标记为简单,因为我们解释了代码片段,你只需将它们复制粘贴到正确的位置即可。如果你缺少 Rust 或嵌入式领域的经验,或者如果你觉得困难版本太难,请使用此版本。两个版本使用的是相同的文件。
i2c-driver/src/icm42670p.rs
是一个非常基础的 I²C IMU 传感器驱动的填空版本。任务是补全这个文件,使得运行 main.rs
可以记录驱动的设备 ID。
i2c-driver/src/icm42670p_solution.rs
提供本练习的解答。如果要运行它,需要更改 main.rs
和 lib.rs
中的导入语句。导入语句已经存在,你只需要注释掉当前的导入语句,并取消注释标记为解答的几行。
驱动
传感器实例
要使用外设传感器,首先要获取它的一个实例。传感器被表示成一个结构体,包含其地址和 I²C 总线对象。这是使用 embedded-hal
crate 中定义的 trait 来实现的。该结构体是公有的,因为我们需要从这个 crate 外访问它,但它的字段是私有的。
我们添加一个 impl
块,包含可以在传感器实例上使用的所有方法。它还定义了错误处理。在这个块中,我们还实现了一个实例化方法。(与结构体类似)方法也可以是公有的或私有的。这个方法需要从外部访问,所以它被标记为 pub
。请注意,以这种方式编写的传感器实例会获取 I²C 总线的所有权。
设备地址
- 设备的地址在代码中可用:
- 这个 I²C 设备有两个可能的地址——
0x68
和0x69
。 我们通过向设备上的AP_AD0
引脚施加0V
或3.3V
来告诉设备我们希望它使用哪一个地址。如果我们施加0V
,它会监听地址0x68
。如果我们施加3.3V
,它会监听地址0x69
。因此,可以将引脚AD_AD0
视为一位输入,用于设置设备地址的最低位。 数据手册的 9.3 节提供了更多信息
寄存器的表示
传感器的寄存器表示为枚举。每个变体都将寄存器的地址作为值。Register
类型实现了一种提供变体地址的方法。
read_register()
和 write_register()
基于 embedded-hal
crate 提供的方法,我们定义了 读取 和 写入 的方法。它们将作为更具体的方法的基础,并作为一个抽象层,用于适配具有 8 位寄存器的传感器。请注意 read_register()
方法是基于 write_read()
方法实现的。其原因在于 I²C 协议的特点:我们首先需要在 I²C 总线上写一个命令来指定我们要读取哪个寄存器。这些辅助方法可以保持私有,因为我们不需要从这个 crate 外访问它们。
✅ 实现一个公有方法来读取地址为 0x75
的 WhoAmI
寄存器。使用上面的 read_register()
方法。
✅ 可选:实现更多方法来向驱动程序添加功能。在文档中查阅相应寄存器及其地址。💡 一些点子:
- 启用陀螺仪传感器或加速度计
- 启动测量
- 读取测得数据
🔎 有关外设寄存器的一般信息
寄存器可以有不同的含义,本质上,它们是一个可以存储值的位置。
在这个特定的上下文中,我们使用的是一个外部设备(因为它是一个传感器,即使与主控芯片在同一块 PCB 上)。它可通过 I2C 寻址,我们在读取和写入其寄存器的地址。每个地址都标识了唯一的一个位置,其中包含了一些信息。在这种情况下,我们想要的是包含当前温度的位置的地址。
如果你想尝试从这个传感器获取其他有趣的数据,可以在第 14 节中找到 ICM-42670 的寄存器表。