mirror of
https://github.com/Narukara/std-training-zh-cn.git
synced 2025-08-06 14:52:09 +08:00
i2c & minor
This commit is contained in:
@ -1,11 +1,11 @@
|
||||
这里是 https://github.com/esp-rs/std-training 的简体中文翻译
|
||||
|
||||
目前进度:跟踪 51350f3
|
||||
目前进度:跟踪 e7396d3
|
||||
|
||||
- [x] 引言(1/1)
|
||||
- [x] 准备工作(5/5)
|
||||
- [x] 入门教程(11/11)
|
||||
- [ ] 进阶教程(5/10)
|
||||
- [ ] 进阶教程(6/10)
|
||||
- [ ] 参考资料(0/1)
|
||||
|
||||
---
|
||||
|
@ -10,6 +10,12 @@
|
||||
|
||||
你可以加入 Matrix 上的 [esp-rs 社区](https://matrix.to/#/#esp-rs:matrix.org) 来探讨任何技术问题!社区对所有人开放。
|
||||
|
||||
## 翻译
|
||||
|
||||
这里是本书的简体中文译本。原书(英文版)及其他译本如下:
|
||||
|
||||
- [English](https://esp-rs.github.io/std-training/) ([仓库](https://github.com/esp-rs/std-training/))
|
||||
|
||||
## 开发板
|
||||
|
||||
本书要求使用 [Rust ESP 开发板](https://github.com/esp-rs/esp-rust-board)[^note]——不支持像 QEMU 这样的模拟器。
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
我们将不会编写整个驱动程序,只会做第一步:驱动程序编写的 `hello world`,即读取传感器的设备 ID。这个版本被标记为简单,因为我们解释了代码片段,你只需将它们复制粘贴到正确的位置即可。如果你缺少 Rust 或嵌入式领域的经验,或者如果你觉得困难版本太难,请使用此版本。两个版本使用的是相同的文件。
|
||||
|
||||
`i2c-driver/src/icm42670p.rs` 是一个非常基础的 i2c IMU 传感器驱动的填空版本。任务是补全这个文件,使得运行 `main.rs` 可以记录驱动的设备 ID。
|
||||
`i2c-driver/src/icm42670p.rs` 是一个非常基础的 I²C IMU 传感器驱动的填空版本。任务是补全这个文件,使得运行 `main.rs` 可以记录驱动的设备 ID。
|
||||
|
||||
`i2c-driver/src/icm42670p_solution.rs` 提供本练习的解答。如果要运行它,需要更改 `main.rs` 和 `lib.rs` 中的导入语句。导入语句已经存在,你只需要注释掉当前的导入语句,并取消注释标记为解答的行。
|
||||
`i2c-driver/src/icm42670p_solution.rs` 提供本练习的解答。如果要运行它,需要更改 `main.rs` 和 `lib.rs` 中的导入语句。导入语句已经存在,你只需要注释掉当前的导入语句,并取消注释标记为解答的几行。
|
||||
|
||||
## 驱动
|
||||
|
||||
@ -25,7 +25,7 @@ pub struct ICM42670P<I2C> {
|
||||
// ...
|
||||
```
|
||||
|
||||
我们添加一个 `impl` 块,包含可以在传感器实例上使用的所有方法。它还定义了错误处理。在这个块中,我们还实现了一个实例化方法。(与上面的结构体类似)方法也可以是公有的或私有的。这个方法需要从外部访问,所以它被标记为 `pub`。请注意,以这种方式编写的传感器实例会获取 I²C 总线的所有权。
|
||||
我们添加一个 `impl` 块,包含可以在传感器实例上使用的所有方法。它还定义了错误处理。在这个块中,我们还实现了一个实例化方法。(与结构体类似)方法也可以是公有的或私有的。这个方法需要从外部访问,所以它被标记为 `pub`。请注意,以这种方式编写的传感器实例会获取 I²C 总线的所有权。
|
||||
|
||||
```rust
|
||||
impl<I2C, E>ICM42670P<I2C>
|
||||
@ -71,7 +71,7 @@ impl Register {
|
||||
|
||||
### `read_register()` 和 `write_register()`
|
||||
|
||||
基于 `embedded-hal` crate 提供的方法,我们定义了 _读取_ 和 _写入_ 的方法。它们将作为更具体的方法的基础,并作为一个抽象层,用于适配具有 8 位寄存器的传感器。请注意 `read_register()` 方法是基于 `write_read()` 方法实现的。其原因在于 I²C 协议的特点:我们首先需要在 I²C 总线上写一个命令来指定我们要读取哪个寄存器。 这些辅助方法可以保持私有,因为我们不需要从这个 crate 外访问它们。
|
||||
基于 `embedded-hal` crate 提供的方法,我们定义了 _读取_ 和 _写入_ 的方法。它们将作为更具体的方法的基础,并作为一个抽象层,用于适配具有 8 位寄存器的传感器。请注意 `read_register()` 方法是基于 `write_read()` 方法实现的。其原因在于 I²C 协议的特点:我们首先需要在 I²C 总线上写一个命令来指定我们要读取哪个寄存器。这些辅助方法可以保持私有,因为我们不需要从这个 crate 外访问它们。
|
||||
|
||||
```rust
|
||||
impl<I2C, E>ICM42670P<I2C>
|
||||
@ -94,7 +94,7 @@ where
|
||||
}
|
||||
```
|
||||
|
||||
✅ 实现一个公有方法来读取地址为 `0x0F` 的 `WhoAmI` 寄存器。使用上面的 `read_register()` 方法。
|
||||
✅ 实现一个公有方法来读取地址为 `0x75` 的 `WhoAmI` 寄存器。使用上面的 `read_register()` 方法。
|
||||
|
||||
|
||||
✅ 可选:实现更多方法来向驱动程序添加功能。在[文档](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf)中查阅相应寄存器及其地址。💡 一些点子:
|
||||
|
@ -1,59 +1,59 @@
|
||||
# Writing an I²C Driver - Hard Version
|
||||
# I²C 驱动练习 - 困难版
|
||||
|
||||
We're not going to write an entire driver, merely the first step: the `hello world` of driver writing: reading the device ID of the sensor. This version is labelled hard, because you have to come up with the content of the methods and research information in the [`embedded-hal`](https://docs.rs/embedded-hal/latest/embedded_hal/) and datasheets yourself. You can work in the same file with either version.
|
||||
我们将不会编写整个驱动程序,只会做第一步:驱动程序编写的 `hello world`,即读取传感器的设备 ID。这个版本被标记为困难,因为你需要自己编写方法的内容,并在 [`embedded-hal`](https://docs.rs/embedded-hal/latest/embedded_hal/) 和数据手册里自己查找信息。两个版本使用的是相同的文件。
|
||||
|
||||
`i2c-driver/src/icm42670p.rs` is a gap text of a very basic I²C IMU sensor driver. The task is to complete the file, so that running `main.rs` will log the device ID of the driver.
|
||||
`i2c-driver/src/icm42670p.rs` 是一个非常基础的 I²C IMU 传感器驱动的填空版本。任务是补全这个文件,使得运行 `main.rs` 可以记录驱动的设备 ID。
|
||||
|
||||
`i2c-driver/src/icm42670p_solution.rs` provides the solution to this exercise. If you want to run it, the imports need to be changed in `main.rs` and `lib.rs`. The imports are already there, you only need to comment the current imports out and uncomment the solutions as marked in the line comments.
|
||||
`i2c-driver/src/icm42670p_solution.rs` 提供本练习的解答。如果要运行它,需要更改 `main.rs` 和 `lib.rs` 中的导入语句。导入语句已经存在,你只需要注释掉当前的导入语句,并取消注释标记为解答的几行。
|
||||
|
||||
## Driver API
|
||||
## 驱动 API
|
||||
|
||||
### Instance of the Sensor
|
||||
### 传感器实例
|
||||
|
||||
✅ Create a struct that represents the sensor. It has two fields, one that represents the sensor's device address and one that represents the `I²C` bus itself. This is done using traits defined in the `embedded-hal` crate. The struct is public as it needs to be accessible from outside this crate, but its fields are private.
|
||||
✅ 创建一个结构体来表示传感器。它有两个字段,一个表示传感器的设备地址,另一个表示 `I²C` 总线。这是使用 `embedded-hal` crate 中定义的 trait 来实现的。该结构体是公有的,因为我们需要从这个 crate 外访问它,但它的字段是私有的。
|
||||
|
||||
✅ Implement an instantiating method in the `impl` block. This method needs to be accessible from outside, so it's labelled `pub`. The method takes ownership of the I²C bus and creates an instance of the struct you defined earlier.
|
||||
✅ 在 `impl` 块里实现一个实例化方法。这个方法需要从外部访问,所以它被标记为 `pub`。这个方法获取 I²C 总线的所有权,然后创建前面定义的结构体的实例。
|
||||
|
||||
|
||||
#### Device address
|
||||
#### 设备地址
|
||||
|
||||
✅ This I²C device has two possible addresses, find them in the [datasheet, section 9.3](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf).
|
||||
✅ 这个 I²C 设备有两个可能的地址,在[数据手册的 9.3 节](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf)里找到它们。
|
||||
|
||||
|
||||
🔎 We tell the device which one we want it to use by applying either `0V` or `3.3V` to the `AP_AD0` pin on the device. If we apply `0V`, it listens to address `0x68`. If we apply `3.3V` it listens to address `0x69`. You can therefore think of pin `AD_AD0` as being a one-bit input which sets the least-significant bit of the device address.
|
||||
🔎 我们通过向设备上的 `AP_AD0` 引脚施加 `0V` 或 `3.3V` 来告诉设备我们希望它使用哪一个地址。如果我们施加 `0V`,它会监听地址 `0x68`。如果我们施加 `3.3V`,它会监听地址 `0x69`。因此,可以将引脚 `AD_AD0` 视为一位输入,用于设置设备地址的最低位。
|
||||
|
||||
✅ Create an enum that represents both address variants. The values of the variants need to be in binary representation.
|
||||
✅ 创建一个枚举来表示两种地址。变体的值需要用二进制表示。
|
||||
|
||||
### Representation of Registers
|
||||
### 寄存器的表示
|
||||
|
||||
✅ Create an enum that represents the sensor's registers. Each variant has the register's address as value. For now, you only need the `WhoAmI` register. Find its address in the datasheet.
|
||||
✅ 创建一个枚举来表示传感器的寄存器。每个变体都将寄存器的地址作为它的值。目前,我们只需要 `WhoAmI` 寄存器。到数据手册里查找它的地址。
|
||||
|
||||
✅ Implement a method that exposes the variant's address as `u8`.
|
||||
✅ 实现一个方法,用于将变体的地址以 `u8` 的形式提供出来。
|
||||
|
||||
### `read_register()` and `write_register()`
|
||||
### `read_register()` 和 `write_register()`
|
||||
|
||||
✅ Check out the write and `write_read` function in the `embedded-hal`. Why is it `write_read` and not just `read`?
|
||||
✅ 查看 `embedded-hal` 中的 `write` 和 `write_read` 函数。为什么是 `write_read` 而不是简单的 `read`?
|
||||
|
||||
<Details>
|
||||
<Summary>Answer</Summary>
|
||||
The reason for this lies in the characteristics of the I²C protocol: We first need to write a command over the I²C bus to specify which register we want to read from.
|
||||
<Summary>解答</Summary>
|
||||
原因在于 I²C 协议的特性:我们需要先在 I²C 总线上写一个命令,来指定我们想要读取哪个寄存器。
|
||||
</Details>
|
||||
|
||||
✅ Define a `read_register` and a `write_register` method for the sensor instance. Use methods provided by the `embedded-hal` crate. They serve as helpers for more specific methods and as an abstraction that is adapted to a sensor with 8-bit registers. This means that the data that is written, as well as the data that is read is an unsigned 8-bit integer. Helper methods can remain private as they don't need to be accessible from outside this crate.
|
||||
✅ 给传感器实例定义 `read_register` 和 `write_register` 方法。使用 `embedded-hal` crate 提供的方法。它们将作为更具体的方法的基础,并作为一个抽象层,用于适配具有 8 位寄存器的传感器。这意味着,读取和写入的数据都是无符号8位的整数。这些辅助方法可以保持私有,因为我们不需要从这个 crate 外访问它们。
|
||||
|
||||
✅ Implement a public method that reads the `WhoAmI` register with the address `0x75`. Make use of the above `read_register()` method.
|
||||
✅ 实现一个公有方法来读取地址为 `0x75` 的 `WhoAmI` 寄存器。使用上面的 `read_register()` 方法。
|
||||
|
||||
✅ Optional: Implement further methods that add features to the driver. Check the [documentation](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf) for the respective registers and their addresses. 💡 Some ideas:
|
||||
* Switching the gyroscope sensor or the accelerometer on
|
||||
* Starting measurements
|
||||
* Reading measurements
|
||||
✅ 可选:实现更多方法来向驱动程序添加功能。在[文档](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf)中查阅相应寄存器及其地址。💡 一些点子:
|
||||
* 启用陀螺仪传感器或加速度计
|
||||
* 启动测量
|
||||
* 读取测得数据
|
||||
|
||||
### 🔎 General info about peripheral registers
|
||||
### 🔎 有关外设寄存器的一般信息
|
||||
|
||||
- Registers are small amounts of storage, immediately accessible by the processor. The registers on the sensor are 8 bits.
|
||||
- They can be accessed by their address
|
||||
- You can find [register maps](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf) in the section 14.
|
||||
- Returning a value with MSB and LSB (most significant byte and least significant byte) is done by shifting MSB values, and OR LSB values.
|
||||
- 寄存器事实上就是少量的存储空间,可由处理器直接访问。这个传感器上的寄存器是 8 位的。
|
||||
- 可以通过地址访问这些寄存器
|
||||
- 在数据手册的第 14 节,有[寄存器表](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf)。
|
||||
- 为了得到一个由 MSB(最高有效位)和 LSB(最低有效位)组合而成的 16 位数,可以将 MSB 值移位,然后或上 LSB 值。
|
||||
```rust
|
||||
let GYRO_DATA_X: i16 = ((GYRO_DATA_X1 as i16) << 8) | GYRO_DATA_X0 as i16;
|
||||
```
|
||||
|
1
common/lib/get-uuid/.gitignore
vendored
1
common/lib/get-uuid/.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
/target
|
||||
uuid.toml
|
||||
_uuid.rs
|
||||
Cargo.lock
|
1
common/lib/mqtt-messages/.gitignore
vendored
1
common/lib/mqtt-messages/.gitignore
vendored
@ -1 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
1
common/lib/rgb-led/.gitignore
vendored
1
common/lib/rgb-led/.gitignore
vendored
@ -1 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
1
common/lib/wifi/.gitignore
vendored
1
common/lib/wifi/.gitignore
vendored
@ -1 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
Reference in New Issue
Block a user