[rtthread设备]系列文章
【rtthread设备】第零篇:IO设备
【rtthread设备】第一篇:pin设备
【rtthread设备】第二篇:rtc设备
【rtthread设备】第三篇:adc设备
【rtthread设备】第五篇:hwtimer设备
【rtthread设备】第六篇:i2c设备
【rtthread设备】第七篇:spi设备
【rtthread设备】第八篇:看门狗设备
一、i2c设备驱动框架
在i2c通信中,mcu一般作为主机与外围的i2c芯片通信,rttread将i2c主机虚拟成i2c总线设备,通过i2c设备接口与从机通信。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ypoQJS0h-1621013981993)(en-resource://database/1939:1)]
二、i2c驱动api
2.1 常用api
//获得设备句柄
/*
name:i2c总线设备名称
*/
rt_device_t rt_device_find(const char* name);
//传输i2c数据
/*
bus:i2c总线设备
msgs[]:要传输的消息
num:消息的数量
*/
rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus,
struct rt_i2c_msg msgs[],
rt_uint32_t num);
2.2 消息结构体rt_i2c_msg
/*
addr:从机地址,0'7b
flags:传输标志
len:读写字节数
buf:读写数据缓存区
*/
struct rt_i2c_msg
{
rt_uint16_t addr;
rt_uint16_t flags;
rt_uint16_t len;
rt_uint8_t *buf;
};
2.3 传输标志
#define RT_I2C_WR 0x0000 //写标志
#define RT_I2C_RD (1u << 0) //读标志
#define RT_I2C_ADDR_10BIT (1u << 2) /* this is a ten bit chip address */ //10位地址
#define RT_I2C_NO_START (1u << 4) //无起始信号
#define RT_I2C_IGNORE_NACK (1u << 5) //忽略应答
#define RT_I2C_NO_READ_ACK (1u << 6) /* when I2C reading, we do not ACK */ //读的时候不发送ACK
#define RT_I2C_NO_STOP (1u << 7) //无停止信号
三、示例
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-08-15 misonyo first implementation.
*/
/*
* 程序清单:这是一个 I2C 设备使用例程
* 例程导出了 i2c_aht10_sample 命令到控制终端
* 命令调用格式:i2c_aht10_sample i2c1
* 命令解释:命令第二个参数是要使用的I2C总线设备名称,为空则使用默认的I2C总线设备
* 程序功能:通过 I2C 设备读取温湿度传感器 aht10 的温湿度数据并打印
*/
#include <rtthread.h>
#include <rtdevice.h>
#define AHT10_I2C_BUS_NAME "i2c1" /* 传感器连接的I2C总线设备名称 */
#define AHT10_ADDR 0x38 /* 从机地址 */
#define AHT10_CALIBRATION_CMD 0xE1 /* 校准命令 */
#define AHT10_NORMAL_CMD 0xA8 /* 一般命令 */
#define AHT10_GET_DATA 0xAC /* 获取数据命令 */
static struct rt_i2c_bus_device *i2c_bus = RT_NULL; /* I2C总线设备句柄 */
static rt_bool_t initialized = RT_FALSE; /* 传感器初始化状态 */
/* 写传感器寄存器 */
static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t *data)
{
rt_uint8_t buf[3];
struct rt_i2c_msg msgs;
buf[0] = reg; //cmd
buf[1] = data[0];
buf[2] = data[1];
msgs.addr = AHT10_ADDR;
msgs.flags = RT_I2C_WR;
msgs.buf = buf;
msgs.len = 3;
/* 调用I2C设备接口传输数据 */
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
/* 读传感器寄存器数据 */
static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *buf)
{
struct rt_i2c_msg msgs;
msgs.addr = AHT10_ADDR;
msgs.flags = RT_I2C_RD;
msgs.buf = buf;
msgs.len = len;
/* 调用I2C设备接口传输数据 */
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
static void read_temp_humi(float *cur_temp, float *cur_humi)
{
rt_uint8_t temp[6];
write_reg(i2c_bus, AHT10_GET_DATA, 0); /* 发送命令 */
read_regs(i2c_bus, 6, temp); /* 获取传感器数据 */
/* 湿度数据转换 */
*cur_humi = (temp[1] << 12 | temp[2] << 4 | (temp[3] & 0xf0) >> 4) * 100.0 / (1 << 20);
/* 温度数据转换 */
*cur_temp = ((temp[3] & 0xf) << 16 | temp[4] << 8 | temp[5]) * 200.0 / (1 << 20) - 50;
}
static void aht10_init(const char *name)
{
rt_uint8_t temp[2] = {0, 0};
/* 查找I2C总线设备,获取I2C总线设备句柄 */
i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name);
if (i2c_bus == RT_NULL)
{
rt_kprintf("can't find %s device!\n", name);
}
else
{
write_reg(i2c_bus, AHT10_NORMAL_CMD, temp);
rt_thread_mdelay(400);
temp[0] = 0x08;
temp[1] = 0x00;
write_reg(i2c_bus, AHT10_CALIBRATION_CMD, temp);
rt_thread_mdelay(400);
initialized = RT_TRUE;
}
}
static void i2c_aht10_sample(int argc, char *argv[])
{
float humidity, temperature;
char name[RT_NAME_MAX];
humidity = 0.0;
temperature = 0.0;
if (argc == 2)
{
rt_strncpy(name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(name, AHT10_I2C_BUS_NAME, RT_NAME_MAX);
}
if (!initialized)
{
/* 传感器初始化 */
aht10_init(name);
}
if (initialized)
{
/* 读取温湿度数据 */
read_temp_humi(&temperature, &humidity);
rt_kprintf("read aht10 sensor humidity : %d.%d %%\n", (int)humidity, (int)(humidity * 10) % 10);
rt_kprintf("read aht10 sensor temperature: %d.%d \n", (int)temperature, (int)(temperature * 10) % 10);
}
else
{
rt_kprintf("initialize sensor failed!\n");
}
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(i2c_aht10_sample, i2c aht10 sample);