目录
概述
本文主要介绍如何使用Renesa Version Board上的I2C接口在RT -Thread框架下功能的应用。笔者基于SHT-Sensor详细介绍了配置的方法。还介绍了RT -Thread框架下I2C驱动的接口函数。
1 硬件接口介绍
1.1 Version Board上的I2C硬件接口
Renesa Version Board板卡扩展口提供一个标准的I2C接口,其命名如下:
在如下网址能看见该IO所对应的Pin引脚:
https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/hw-board/ra8d1-vision-board/ra8d1-vision-board
1.2 SHT20
1.2.1 SHT20简介
SHT20是由Sensirion公司推出的一款数字温湿度传感器。它采用先进的CMOSens®技术,具有高精度、低功耗和长期稳定性的特点。
SHT20的测量范围涵盖了-40℃至125℃的温度和0%至100%的湿度,精确度分别为±0.3℃和±3%RH。它使用了数字式输出接口,可以通过I2C总线进行数据通信,并支持温度和湿度的实时测量。
SHT20的封装形式小巧,尺寸为3x3x1.1mm,适合各种应用场景。它具有低功耗特性,工作电压范围为2.1V至3.6V,供电电流在典型条件下为1.2mA。此外,SHT20还具有快速响应时间和强大的抗干扰能力。
1.2.2 SHT-20模块电路
1)SHT20硬件接口图
2) sensor模块电路
SHT-20实物图:
2 软件实现
2.1 软件版本信息
软硬件信息 | 版本信息 |
---|---|
Renesas MCU | R7FA8D1BH |
RT-Thread Studio | 2.2.7 |
FSP 版本 | 5.1.0 |
调试工具:DAP-link | ART-Link CMSIS-DAP: V2.0.0 |
2.2 RT-Thread Studio创建项目
打开RT-Thread Studio,File->RT-Thread Project,打开之后看见如下页面,输入项目名称,创建项目。
2.3 FSP配置I2C接口
1)选择SCI3接口,配置为I2C模式,该接口对应的IO口为P408和P409
2)在Stacks面板上配置驱动的相关信息
完成以上两个步骤之后,就可以重新生成项目代码。
3) RT-Thread Studio打开驱动接口,配置完成后,使用Ctrl+S保存文件。
2.4 使能Sensor驱动
打开RT-Thread Setting,搜索sht2,找到该驱动后使能该驱动。
在项目目录中,packages中已经加载该驱动程序。
3 RT-Thread驱动架构
3.1 接口函数
一般来说,MCU的I2C设备作为主从设备进行通信。在RT-Thread中,I2C主机被虚拟化为I2C总线设备。I2C从站通过I2C设备接口与I2C总线通信。相关接口如下:
Function | Description |
---|---|
rt_device_find() | Find device handles based on I2C bus device name |
rt_i2c_transfer() | transfer data |
3.1.1 查找设备函数
在使用I2C总线设备之前,需要根据I2C总线设备名称获取设备句柄,以便对I2C总线设备进行操作。设备功能如下:
rt_device_t rt_device_find(const char* name);
Parameter | Description |
---|---|
name | I2C bus device name |
Return Value | —— |
device handle | Finding the corresponding device will return the corresponding device handle |
RT_NULL | No corresponding device object found |
举个例子:
注册到系统的I2C设备名称为i2co2、i2c1等。使用示例如下:
#define AHT10_I2C_BUS_NAME "i2c1" /* Sensor connected I2C bus device name */
struct rt_i2c_bus_device *i2c_bus; /* I2C bus device handle */
/* Find the I2C bus device and get the I2C bus device handle */
i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name);
3.1.2 数据传输函数
可以通过获取I2C总线设备句柄来使用' rt_i2c_transfer() '进行数据传输。函数原型如下:
rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus,
struct rt_i2c_msg msgs[],
rt_uint32_t num);
Parameter | Description |
---|---|
bus | I2C bus device handle |
msgs[] | Message array pointer to be transmitted |
num | The number of elements in the message array |
Return Value | —— |
the number of elements in the message array | succeeded |
error code | failed |
一个应用实例:
Message结构体定义
struct rt_i2c_msg
{
rt_uint16_t addr; /* Slave address */
rt_uint16_t flags; /* Reading, writing signs, etc. */
rt_uint16_t len; /* Read and write data bytes */
rt_uint8_t *buf; /* Read and write data buffer pointer */
}
读数据函数实现
/* Read sensor register data */
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; /* Slave address */
msgs.flags = RT_I2C_RD; /* Read flag */
msgs.buf = buf; /* Read and write data buffer pointer */
msgs.len = len; /* Read and write data bytes */
/* Call the I2C device interface to transfer data */
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
3.3 驱动Demo
RT-Thread提供了一个Demo,其详细代码如下:
/*
* Program listing: This is an I2C device usage routine
* The routine exports the i2c_aht10_sample command to the control terminal
* Command call format: i2c_aht10_sample i2c1
* Command explanation: The second parameter of the command is the name of the I2C bus device to be used. If it is empty, the default I2C bus device is used.
* Program function: read the temperature and humidity data of the aht10 sensor and print.
*/
#include <rtthread.h>
#include <rtdevice.h>
#define AHT10_I2C_BUS_NAME "i2c1" /* Sensor connected I2C bus device name */
#define AHT10_ADDR 0x38 /* Slave address */
#define AHT10_CALIBRATION_CMD 0xE1 /* Calibration command */
#define AHT10_NORMAL_CMD 0xA8 /* General command */
#define AHT10_GET_DATA 0xAC /* Get data command */
static struct rt_i2c_bus_device *i2c_bus = RT_NULL; /* I2C bus device handle */
static rt_bool_t initialized = RT_FALSE; /* Sensor initialization status */
/* Write sensor register */
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;
/* Call the I2C device interface to transfer data */
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
/* Read sensor register data */
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;
/* Call the I2C device interface to transfer data */
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); /* send command */
rt_thread_mdelay(400);
read_regs(i2c_bus, 6, temp); /* obtian sensor data */
/* Humidity data conversion */
*cur_humi = (temp[1] << 12 | temp[2] << 4 | (temp[3] & 0xf0) >> 4) * 100.0 / (1 << 20);
/* Temperature data conversion */
*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};
/* Find the I2C bus device and get the I2C bus device handle */
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)
{
/* Sensor initialization */
aht10_init(name);
}
if (initialized)
{
/* Read temperature and humidity data */
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");
}
}
/* Export to the msh command list */
MSH_CMD_EXPORT(i2c_aht10_sample, i2c aht10 sample);
4 系统测试
4.1 硬件环境
将SHT20的电源和通信接口与Version Board连接起来,其连接图如下:
硬件实物图如下:
4.2 软件测试方法介绍
RT-Thread已经提供了SHT20相关的测试命令,其具体测试方法如下:
4.2.1 探测传感器
sht2x 软件包提供了丰富的测试命令,项目只要在 RT-Thread 上开启 Finsh/MSH 功能即可。在做一些基于 sht2x
的应用开发、调试时,这些命令会非常实用,它可以准确的读取指传感器测量的温度与湿度。具体功能可以输入 sht20
,可以查看完整的命令列表:
msh /> sht20
Usage:
sht20 probe <dev_name> - probe sensor by given name
sht20 read - read sensor sht20 data
msh />
具体方法如下:
msh />sht20 probe i2c1 #探测成功,没有错误日志
msh />
msh />sht20 probe i2c88 #探测失败,提示对应的 I2C 设备找不到
[E/sht20] can't find sht20 device on 'i2c88'
msh />
4.2.2 读取数据
探测成功之后,输入 sht20 read
即可获取温度与湿度,包括提示信息,日志如下:
msh />sht20 read
read sht20 sensor humidity : 54.7 %
read sht20 sensor temperature: 27.3
msh />
4.3 板卡级测试
4.3.1 准备测试环境
1)使用Ctrl+B组合键,编译项目代码,如下编译成功,可以看见如下log:
2)下载代码到板卡中
3)打开串口终端工具,如果代码能正常工作,可以看见如下log:
4.3.2 测试
1)查询I2C驱动接口信息,使用如下命令:
list device
2)检测SHT20在线状态
探测失败状态:
sht20 probe sci3i
探测成功状态:
sht20 probe sci3i
改变环境温度,观察传感器温湿度的变化情况: