RT-Thread IIC总线官方实例实现

官方的文档写的是读取传感器的温湿度并打印出来,作为萌新学rtt,这个过程稍微有点看不懂,所以我简化了实现过程。
用GPIO口模拟IIC,实现往向设备写入数据,并向从设备读取数据,这个简单的套路理解了,后面完成复杂的功能也会有思路。

工作原理

工作原理参考链接: IIC基本原理
想要先完成数据的读写以实现明显代码效果,可以只用看时序图那一部分。这个文章说了一个重要的点,我把重点的放进来:

这是写操作:

  • 起始信号->从设备地址->写操作->应答信号->从设备数据的地址->应答信号->存数据的buffer->停止信号。
    写入的时候需要明确这个数据需要放在哪。
    RT-Thread IIC总线官方实例实现_第1张图片

这是读操作:进行读操作之前需要进行一次伪写操作

  • 起始信号->从设备地址->写操作->应答信号->从设备数据的地址->应答信号->停止信号。
  • 起始信号->从设备数据的地址->应答信号->取数据的buffer->应答信号->停止信号。

RT-Thread IIC总线官方实例实现_第2张图片
这样就完成了数据的写入和读取。

代码解析

接下来进入代码片:

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);

实现效果

RT-Thread IIC总线官方实例实现_第3张图片
总结:这是简单的实现,考虑到的底层很少,相当于黑盒学习,这种办法不益于学习,但是最主要的目的是通过代码效果来告诉你,你的方向是没错的,完成效果后,还需对底层实现进一步的了解!

你可能感兴趣的:(RT-Thread和STM32,stm32,rtt,嵌入式)