rtt标准版的软件i2c使用

软件i2c配置

在rtt配备的env环境中,通过menuconfig进入项目配置界面,依次选择Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable I2C1 BUS (software simulation)

在使能软件i2c后,会进入i2c的scl和sda的io配置,在rtt中stm32的多类gpio(如PA、PB)被降维编码为一维id,如

  • PC0: $2*16 + 0 = 32$
  • PF1: $5*16 + 1 = 81$

通过UI界面配置的结果,如SCL和SDA对应的io pin口,可以在rtconfig.h中看到对应的宏定义接口。

i2c设备的封装

rtt中的i2c设备是对rt_device类型设备的再封装,对应i2c总线设备的类(结构体)的父类即为rt_device。

i2c总线设备结构体如下所示

1
2
3
4
5
6
7
8
9
10
11
/*for i2c bus driver*/
struct rt_i2c_bus_device
{
struct rt_device parent;
const struct rt_i2c_bus_device_ops *ops;
rt_uint16_t flags;
struct rt_mutex lock;
rt_uint32_t timeout;
rt_uint32_t retries;
void *priv;
};

device封装格式与linux类似,ops指的是针对当前字符设备操作的一组函数指针,如open、close、read以及write等。

i2c总线设备的使用

  1. 声明i2c设备
1
2
#define I2C_BUS_NAME          "i2c1"                    /* 传感器连接的I2C总线设备名称 */
static struct rt_i2c_bus_device *i2c_bus = RT_NULL; /* I2C总线设备句柄 */
  1. 通过rt_device类的find方法连接总线设备句柄
1
2
3
4
5
i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(I2C_BUS_NAME);
if (i2c_bus == RT_NULL) {
rt_kprintf("can't find %s device!\n", I2C_BUS_NAME);
return -RT_ERROR;
}
  1. rt_device类的open方法尝试开启设备,并检查函数返回(引用设备,每次open使设备ref++)
1
2
3
4
if (rt_device_open(&i2c_bus->parent, RT_NULL) != RT_EOK) {
rt_kprintf("open %s device failed!\n", I2C_BUS_NAME);
return -RT_ERROR;
}
  1. 读写数据-transfer方法
  • RT_I2C_WR:写标志
  • RT_I2C_RD:读标志
  • RT_I2C_ADDR_10BIT:10bit地址模式
  • RT_I2C_NO_START:无起始位,与无结束位实现拼接
  • RT_I2C_NO_STOP:同上
  • RT_I2C_IGNORE_NACK:发送时无视来自接收方的NACK
  • RT_I2C_NO_READ_ACK:读取时不产生ACK
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*?
* I2C bus transfer
*
* @param bus the I2C bus device
* @param msgs the I2C message array
* @param num the number of I2C message
*
* @return the number of messages sent
*/
rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus,
struct rt_i2c_msg msgs[],
rt_uint32_t num);

struct rt_i2c_msg msgs; /* i2c消息结构体 */
msgs.addr = addr; /* i2c从机地址 */
msgs.buf = buf; /* 数据缓冲区 */
msgs.len = len; /* 数据长度 */
msgs.flags = RT_I2C_WR; /* 写标志 */

if (rt_i2c_transfer(i2c_bus, &msgs, 1) != 1){
return -RT_ERROR;
}
  1. 读写数据-master封装方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*?
* I2C master send data
*
* @param[in] *bus the I2C bus device
* @param[in] addr the I2C slave address
* @param[in] flags the I2C message flags
* @param[in] *buf the data buffer
* @param[in] count the data buffer length
*
* @return the number of bytes sent
*/
rt_size_t rt_i2c_master_send(struct rt_i2c_bus_device *bus,
rt_uint16_t addr,
rt_uint16_t flags,
const rt_uint8_t *buf,
rt_uint32_t count);
/*?
* I2C master receive data
*
* @param[in] *bus the I2C bus device
* @param[in] addr the I2C slave address
* @param[in] flags the I2C message flags
* @param[out] *buf the data buffer
* @param[out] count the received data length
*
* @return the number of bytes receive
*/
rt_size_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus,
rt_uint16_t addr,
rt_uint16_t flags,
rt_uint8_t *buf,
rt_uint32_t count);
  1. 关闭设备(取消引用,ref–)
1
2
3
4
if (rt_device_close(&i2c_bus->parent) != RT_EOK) {
rt_kprintf("close %s device failed!\n", I2C_BUS_NAME);
return -RT_ERROR;
}