官方的文档写的是读取传感器的温湿度并打印出来,作为萌新学rtt,这个过程稍微有点看不懂,所以我简化了实现过程。
用GPIO口模拟IIC,实现往向设备写入数据,并向从设备读取数据,这个简单的套路理解了,后面完成复杂的功能也会有思路。
工作原理参考链接: IIC基本原理
想要先完成数据的读写以实现明显代码效果,可以只用看时序图那一部分。这个文章说了一个重要的点,我把重点的放进来:
这是写操作:
这是读操作:进行读操作之前需要进行一次伪写操作
接下来进入代码片:
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 <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"
#define EEP_I2C_BUS_NAME "i2c1" /* 连接I2C总线设备名称 */
#define EEP_ADDR 0x50 /* 从机地址 */
#define WP GET_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);
总结:这是简单的实现,考虑到的底层很少,相当于黑盒学习,这种办法不益于学习,但是最主要的目的是通过代码效果来告诉你,你的方向是没错的,完成效果后,还需对底层实现进一步的了解!