官方的文档写的是读取传感器的温湿度并打印出来,作为萌新学rtt,这个过程稍微有点看不懂,所以我简化了实现过程。
用GPIO口模拟IIC,实现往向设备写入数据,并向从设备读取数据,这个简单的套路理解了,后面完成复杂的功能也会有思路。
工作原理
工作原理参考链接: IIC基本原理
想要先完成数据的读写以实现明显代码效果,可以只用看时序图那一部分。这个文章说了一个重要的点,我把重点的放进来:
这是写操作:
- 起始信号->从设备地址->写操作->应答信号->从设备数据的地址->应答信号->存数据的buffer->停止信号。
写入的时候需要明确这个数据需要放在哪。
文章图片
- 起始信号->从设备地址->写操作->应答信号->从设备数据的地址->应答信号->停止信号。
- 起始信号->从设备数据的地址->应答信号->取数据的buffer->应答信号->停止信号。
文章图片
这样就完成了数据的写入和读取。
代码解析
接下来进入代码片:
static void i2c_eep_sample(int argc, char *argv[])
{
//定义写入数据的buffer,第一个是数据地址位,第二、三个数据是今天的日期,
//uint8为unsigned char型,定义成 6, 18应该不影响
//从设备的地址设为全局变量,这里没有写
rt_uint8_t buf_wr[3] = {0x51, 6,18};
i2c_bus = rt_i2c_bus_device_find(EEP_I2C_BUS_NAME);
//查找设备
if(i2c_bus == RT_NULL)
{
rt_kprintf("can't find %s", EEP_I2C_BUS_NAME);
}
// WP位拉低,进行写操作
//这是用的EEPROM的控制引脚,使用写数据需要将RE位拉低
//没有就不需要加进去
rt_pin_mode(WP, PIN_MODE_OUTPUT);
rt_pin_write(WP, PIN_LOW);
epp_wr(i2c_bus, buf_wr, 3);
//写数据,数据地址位和两个数据位
rt_thread_mdelay(400);
//读数据前需要把读取数据的地址写入,
//这里的{0x51,0}下面用两次,一次写入地址,一次读取之前设定好的两个数据
rt_uint8_t buf_rd[2] = {0x51, 0};
//写数据,这里只需要写入一个参数就行
epp_wr(i2c_bus, buf_rd, 1);
//读数据,将读到的两位放入buf_rd中
epp_rd(i2c_bus, buf_rd, 2);
if (ret == RT_EOK)
{rt_kprintf("today is %d.%d\n", buf_rd[0], buf_rd[1]);
}}
写入数据实现块:
/* 写传EEPROM寄存器 */
static rt_err_t epp_wr(struct rt_i2c_bus_device *bus,
rt_uint8_t *data,
rt_uint8_t add)
{
//创建消息数据结构
struct rt_i2c_msg msgs;
msgs.addr = EEP_ADDR;
//从设备地址
msgs.flags = RT_I2C_WR;
//写
msgs.buf = data;
//写入数据,包括从设备数据地址以及两个时间数据
msgs.len = add;
//写入数据个数,包括从设备地址/* 调用I2C设备接口传输数据 */
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{
rt_kprintf("write ok!\n");
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
读取数据实现块:
/* 读传EEPROM寄存器数据 */
static rt_err_t epp_rd(struct rt_i2c_bus_device *bus, rt_uint8_t *data, rt_uint8_t add)
{
//消息数据结构
struct rt_i2c_msg msgs;
msgs.addr = EEP_ADDR;
//从设备地址
msgs.flags = RT_I2C_RD;
//读
msgs.buf = data;
//存储数据的buffer
msgs.len = add;
//读取个数/* 调用I2C设备接口传输数据 */
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{//msgs.buf[1] += 1;
rt_kprintf("read ok!\n");
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
完整代码
#include
#include
#include "drv_common.h"#define EEP_I2C_BUS_NAME"i2c1"/* 连接I2C总线设备名称 */
#define EEP_ADDR0x50/* 从机地址 */
#define WPGET_PIN(B, 5)static struct rt_i2c_bus_device *i2c_bus = RT_NULL;
/* I2C总线设备句柄 *//* 写传EEPROM寄存器 */
static rt_err_t epp_wr(struct rt_i2c_bus_device *bus, rt_uint8_t *data, rt_uint8_t add)
{struct rt_i2c_msg msgs;
msgs.addr = EEP_ADDR;
msgs.flags = RT_I2C_WR;
msgs.buf = data;
msgs.len = add;
/* 调用I2C设备接口传输数据 */
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{
rt_kprintf("write ok!\n");
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}/* 读传EEPROM寄存器数据 */
static rt_err_t epp_rd(struct rt_i2c_bus_device *bus, rt_uint8_t *data, rt_uint8_t add)
{
struct rt_i2c_msg msgs;
msgs.addr = EEP_ADDR;
msgs.flags = RT_I2C_RD;
msgs.buf = data;
msgs.len = add;
/* 调用I2C设备接口传输数据 */
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{//msgs.buf[1] += 1;
rt_kprintf("read ok!\n");
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}static void i2c_eep_sample(int argc, char *argv[])
{
rt_err_t ret = RT_NULL;
rt_uint8_t buf_wr[3] = {0x51, 6,18};
i2c_bus = rt_i2c_bus_device_find(EEP_I2C_BUS_NAME);
//查找设备
if(i2c_bus == RT_NULL)
{
rt_kprintf("can't find %s", EEP_I2C_BUS_NAME);
}
/* WP位拉低,进行写操作 */
rt_pin_mode(WP, PIN_MODE_OUTPUT);
rt_pin_write(WP, PIN_LOW);
epp_wr(i2c_bus, buf_wr, 3);
//写地址
rt_thread_mdelay(400);
rt_uint8_t buf_rd[2] = {0x51, 0};
epp_wr(i2c_bus, buf_rd, 1);
//读数据
epp_rd(i2c_bus, buf_rd, 2);
if (ret == RT_EOK)
{rt_kprintf("today is %d.%d\n", buf_rd[0], buf_rd[1]);
}}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(i2c_eep_sample, i2c aht10 sample);
实现效果
【RT-Thread和STM32|RT-Thread IIC总线官方实例实现】
文章图片
总结:这是简单的实现,考虑到的底层很少,相当于黑盒学习,这种办法不益于学习,但是最主要的目的是通过代码效果来告诉你,你的方向是没错的,完成效果后,还需对底层实现进一步的了解!
推荐阅读
- RT-Thread|RT-Thread记录(十七、AT组件 — ESP8266使用 at_device 软件包联网)
- RT-Thread|RT-Thread记录(十四、I/O 设备模型之ADC设备)
- RT-Thread|RT-Thread记录(十六、SFUD组件 — SPI Flash的读写)
- RT-Thread|RT-Thread 应用篇 — 在STM32L051上使用 RT-Thread (一、无线温湿度传感器 之 新建项目)
- RT-Thread|RT-Thread记录(九、RT-Thread 中断处理与阶段小结)
- 嵌入式|嵌入式操作系统FreeRTOS(低功耗 Tickless 模式)
- 嵌入式|嵌入式学习笔记(综合提高篇 第二章) -- FreeRTOS的移植和应用
- 单片机|一步一阶梯的学习嵌入式
- 单片机|为什么学了很久的STM32,独立做项目还是一脸茫然