Github

整个RTT学习过程中对工程的完善和开发都记录在Github上的一个项目中,项目还会随着学习的深入进行更新
项目URL:https://github.com/HITLIVING/-RT-Thread-.git
读者可以通过Pull下来整个项目进一步了解
对I2C驱动的实现需要格外关注
drv_mpu6050.c
drv_mpu6050.h
两个文件

外设配置

STM32F1RCT6芯片
MPU6050模块

Cube

由于使用的是模拟I2C,不需要使用独特的板上资源,仅需两个通用IO口即可,因此这里不需要对Cube有额外操作

Kconfig

  1. menuconfig BSP_USING_I2C1
  2. bool "Enable I2C1 BUS (software simulation)"
  3. default n
  4. select RT_USING_I2C
  5. select RT_USING_I2C_BITOPS
  6. select RT_USING_PIN
  7. if BSP_USING_I2C1
  8. comment "Notice: PA2 --> 2; PA3 --> 3"
  9. config BSP_I2C1_SCL_PIN
  10. int "I2C1 scl pin number"
  11. range 1 50
  12. default 2
  13. config BSP_I2C1_SDA_PIN
  14. int "I2C1 sda pin number"
  15. range 1 50
  16. default 3
  17. endif

这样配置后,即可以通过Env将I2C的SCL和SDA与特定的引脚(pin设备引脚号)对应
这里使用的是PA2和PA3,可以通过文件 drv_gpio.c 查到对应的设备号为2和3

Env

image.png
image.png
image.png
image.png

Kconfig完成配置后,即可在Env中看到关于I2C的设备驱动选项,使能设备,并填入对应的pin设备号后,保存退出
使用 scons 指令生成MDK5工程

MDK

image.png

即可以看到工程树下完成了对I2C驱动文件的添加
同时通过查看 rtconfig.h 文件
image.pngimage.png

添加了我们在Kconfig中写好的定义

从中也可以认识到Env工具的实质:

  • 用Kconfig文件配置Env菜单界面和一些配置选项
  • Env中打开或关闭选项,并根据选项添加相关设备的宏定义
  • 根据宏定义的内容在工程树下添加外设驱动的文件

到这里对模拟I2C外设的驱动完成

接口函数

查找 I2C 总线设备

在使用 I2C 总线设备前需要根据 I2C 总线设备名称获取设备句柄,进而才可以操作 I2C 总线设备,查找设备函数如下所示,

  1. rt_device_t rt_device_find(const char* name);
参数 描述
name I2C 总线设备名称
返回 ——
设备句柄 查找到对应设备将返回相应的设备句柄
RT_NULL 没有找到相应的设备对象

一般情况下,注册到系统的 I2C 设备名称为 i2c0 ,i2c1等,按照之前配置这里使用的是”i2c1”总线

数据传输

获取到 I2C 总线设备句柄就可以使用 rt_i2c_transfer() 进行数据传输。函数原型如下所示

  1. rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus,
  2. struct rt_i2c_msg msgs[],
  3. rt_uint32_t num);
参数 描述
bus I2C 总线设备句柄
msgs[] 待传输的消息数组指针
num 消息数组的元素个数
返回 ——
消息数组的元素个数 成功
错误码 失败

I2C 总线的自定义传输接口传输的数据也是以一个消息为单位。参数 msgs[] 指向待传输的消息数组,用户可以自定义每条消息的内容,实现 I2C 总线所支持的 2 种不同的数据传输模式。如果主设备需要发送重复开始条件,则需要发送 2 个消息。

注:此函数会调用 rt_mutex_take(), 不能在中断服务程序里面调用,会导致 assertion 报错。

I2C 消息数据结构原型如下:

  1. struct rt_i2c_msg
  2. {
  3. rt_uint16_t addr; /* 从机地址 */
  4. rt_uint16_t flags; /* 读、写标志等 */
  5. rt_uint16_t len; /* 读写数据字节数 */
  6. rt_uint8_t *buf; /* 读写数据缓冲区指针 */
  7. }

从机地址 addr:支持 7 位和 10 位二进制地址,需查看不同设备的数据手册 。

RT-Thread I2C 设备接口使用的从机地址均不包含读写位,读写位控制需修改标志 flags。

标志 flags 可取值为以下宏定义,根据需要可以与其他宏使用位运算 “|” 组合起来使用。

  1. #define RT_I2C_WR 0x0000 /* 写标志 */
  2. #define RT_I2C_RD (1u << 0) /* 读标志 */
  3. #define RT_I2C_ADDR_10BIT (1u << 2) /* 10 位地址模式 */
  4. #define RT_I2C_NO_START (1u << 4) /* 无开始条件 */
  5. #define RT_I2C_IGNORE_NACK (1u << 5) /* 忽视 NACK */
  6. #define RT_I2C_NO_READ_ACK (1u << 6) /* 读的时候不发送 ACK */

发送数据

此函数其实是对传输函数进行了一层封装,函数原型如下:

  1. rt_size_t rt_i2c_master_send(struct rt_i2c_bus_device *bus,
  2. rt_uint16_t addr,
  3. rt_uint16_t flags,
  4. const rt_uint8_t *buf,
  5. rt_uint32_t count)
参数 描述
bus I2C总线设备句柄
addr 从机地址,不包含读写位
flags 标志,(写0即可,会通过封装自动配置为写)只支持10位地址选择RT_I2C_ADDR_10BIT
buf 指向发送数据的指针
count 发送数据字节数
返回 成功发送的数据字节数

接收函数

此函数其实也是对传输函数进行了一层封装,函数原型如下:

  1. rt_size_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus,
  2. rt_uint16_t addr,
  3. rt_uint16_t flags,
  4. const rt_uint8_t *buf,
  5. rt_uint32_t count)
参数 描述
bus I2C总线设备句柄
addr 从机地址,不包含读写位
flags 标志,(写0即可,会通过封装自动配置为读)只支持10位地址选择RT_I2C_ADDR_10BIT
buf 指向发送数据的指针
count 发送数据字节数
返回 成功接收的数据字节数

上机实验

见文件工程下的对MPU6050的驱动文件
drv_mpu6050.c
drv_mpu6050.h