0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RT-Thread设备框架使用指南——I2C总线设备简介

RTThread物联网操作系统 来源:lq 2019-01-22 11:50 次阅读

I2C 简介

I2C(Inter Integrated Circuit)总线是 PHILIPS 公司开发的一种半双工、双向二线制同步串行总线。I2C 总线传输数据时只需两根信号线,一根是双向数据线 SDA(serial data),另一根是双向时钟线 SCL(serial clock)。SPI 总线有两根线分别用于主从设备之间接收数据和发送数据,而 I2C 总线只使用一根线进行数据收发。

I2C 和 SPI 一样以主从的方式工作,不同于 SPI 一主多从的结构,它允许同时有多个主设备存在,每个连接到总线上的器件都有唯一的地址,主设备启动数据传输并产生时钟信号,从设备被主设备寻址,同一时刻只允许有一个主设备。如下图所示:

I2C 总线主从设备连接方式

如下图所示为 I2C 总线主要的数据传输格式:

I2C 总线数据传输格式

当总线空闲时,SDA 和 SCL 都处于高电平状态,当主机要和某个从机通讯时,会先发送一个开始信号,然后发送从机地址和读写控制位,接下来传输数据(主机发送或者接收数据),数据传输结束时主机会发送结束信号。传输的每个字节为8位,高位在前,低位在后。数据传输过程中的不同名词详解如下所示:

开始条件:SCL 为高电平时,主机将 SDA 拉低,表示数据传输即将开始。

从机地址:主机发送的第一个字节为从机地址,高 7 位为地址,最低位为 R/W 读写控制位,1 表示读操作,0 表示写操作。一般从机地址有 7 位地址模式和 10 位地址模式两种,如果是 10 位地址模式,第一个字节的头 7 位 是 11110XX 的组合,其中最后两位(XX)是 10 位地址的两个最高位,第二个字节为 10 位从机地址的剩下8位,如下图所示:

7 位地址和 10 位地址格式

应答信号:每传输完成一个字节的数据,接收方就需要回复一个 ACK(acknowledge)。写数据时由从机发送 ACK,读数据时由主机发送 ACK。当主机读到最后一个字节数据时,可发送 NACK(Negative Acknowledgement)然后跟停止条件。

数据:地址帧发送完后可能会发送一些指令,依从机而定,然后开始传输数据,由主机或者从机发送,每个数据为 8 位,数据的字节数没有限制。

重复开始条件:在一次通信过程中,主机可能需要和不同的从机传输数据或者需要切换读写操作时,主机可以再发送一个开始条件。

停止条件:在 SDA 为低电平时,主机将 SCL 拉高并保持高电平,然后在将 SDA 拉高,表示传输结束。

访问 I2C 总线设备

一般情况下 MCU 的 I2C 器件都是作为主机和从机通讯,在 RT-Thread 中将 I2C 主机虚拟为 I2C总线设备,I2C 从机通过 I2C 设备接口和 I2C 总线通讯,相关接口如下所示:

查找 I2C 总线设备

在使用 I2C 总线设备前需要根据 I2C 总线设备名称获取设备句柄,进而才可以操作 I2C 总线设备,查找设备函数如下所示,

1rt_device_trt_device_find(constchar*name);


1#defineAHT10_I2C_BUS_NAME"i2c1"/*传感器连接的I2C总线设备名称*/2structrt_i2c_bus_device*i2c_bus;/*I2C总线设备句柄*/34/*查找I2C总线设备,获取I2C总线设备句柄*/5i2c_bus=(structrt_i2c_bus_device*)rt_device_find(name);一般情况下,注册到系统的 I2C 设备名称为 i2c0 ,i2c1等,使用示例如下所示:

数据传输

获取到 I2C 总线设备句柄就可以使用 rt_i2c_transfer() 进行数据传输。函数原型如下所示:

1rt_size_trt_i2c_transfer(structrt_i2c_bus_device*bus,2structrt_i2c_msgmsgs[],3rt_uint32_tnum);

和 SPI 总线的自定义传输接口一样,I2C 总线的自定义传输接口传输的数据也是以一个消息为单位。参数 msgs[] 指向待传输的消息数组,用户可以自定义每条消息的内容,实现 I2C 总线所支持的 2 种不同的数据传输模式。如果主设备需要发送重复开始信号,则需要发送 2 个消息。

I2C 消息数据结构原型如下:

1structrt_i2c_msg2{3rt_uint16_taddr;/*从机地址*/4rt_uint16_tflags;/*读、写标志等*/5rt_uint16_tlen;/*读写数据字节数*/6rt_uint8_t*buf;/*读写数据缓冲区指针*/7}

从机地址 addr:支持 7 位和 10 位二进制地址,需查看不同设备的数据手册 。RT-Thread I2C 设备接口使用的从机地址均为不包含读写位的地址,读写位控制需修改标志 flags。

标志 flags 可取值为以下宏定义,根据需要可以与其他宏使用位运算 “|” 组合起来使用。

1#defineRT_I2C_WR0x0000/*写标志*/2#defineRT_I2C_RD(1u<< 0)      /* 读标志 */3#define RT_I2C_ADDR_10BIT      (1u << 2)      /* 10 位地址模式 */4#define RT_I2C_NO_START        (1u << 4)      /* 无开始条件 */5#define RT_I2C_IGNORE_NACK     (1u << 5)      /* 忽视 NACK */6#define RT_I2C_NO_READ_ACK     (1u << 6)     /* 读的时候不发送 ACK */

使用示例如下所示:

1#defineAHT10_I2C_BUS_NAME"i2c1"/*传感器连接的I2C总线设备名称*/ 2#defineAHT10_ADDR0x38/*从机地址*/ 3structrt_i2c_bus_device*i2c_bus;/*I2C总线设备句柄*/ 4 5/*查找I2C总线设备,获取I2C总线设备句柄*/ 6i2c_bus=(structrt_i2c_bus_device*)rt_device_find(name); 7 8/*读传感器寄存器数据*/ 9staticrt_err_tread_regs(structrt_i2c_bus_device*bus,rt_uint8_tlen,rt_uint8_t*buf)10{11structrt_i2c_msgmsgs;1213msgs.addr=AHT10_ADDR;/*从机地址*/14msgs.flags=RT_I2C_RD;/*读标志*/15msgs.buf=buf;/*读写数据缓冲区指针*/16msgs.len=len;/*读写数据字节数*/1718/*调用I2C设备接口传输数据*/19if(rt_i2c_transfer(bus,&msgs,1)==1)20{21returnRT_EOK;22}23else24{25return-RT_ERROR;26}27}

I2C 总线设备使用示例

I2C 设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下:

首先根据 I2C 设备名称查找 I2C 名称,获取设备句柄,然后初始化 aht10 传感器。

控制传感器的 2 的函数为写传感器寄存器 write_reg() 和读传感器寄存器 read_regs(),这两个函数分别调用了 rt_i2c_transfer() 传输数据。读取温湿度信息的函数 read_temp_humi() 则是调用这两个函数完成功能。

1/* 2*程序清单:这是一个I2C设备使用例程 3*例程导出了i2c_aht10_sample命令到控制终端 4*命令调用格式:i2c_aht10_samplei2c1 5*命令解释:命令第二个参数是要使用的I2C总线设备名称,为空则使用默认的I2C总线设备 6*程序功能:通过I2C设备读取温湿度传感器aht10的温湿度数据并打印 7*/ 8 9#include 10#include 11 12#defineAHT10_I2C_BUS_NAME"i2c1"/*传感器连接的I2C总线设备名称*/ 13#defineAHT10_ADDR0x38/*从机地址*/ 14#defineAHT10_CALIBRATION_CMD0xE1/*校准命令*/ 15#defineAHT10_NORMAL_CMD0xA8/*一般命令*/ 16#defineAHT10_GET_DATA0xAC/*获取数据命令*/ 17 18staticstructrt_i2c_bus_device*i2c_bus=RT_NULL;/*I2C总线设备句柄*/ 19staticrt_bool_tinitialized=RT_FALSE;/*传感器初始化状态*/ 20 21/*写传感器寄存器*/ 22staticrt_err_twrite_reg(structrt_i2c_bus_device*bus,rt_uint8_treg,rt_uint8_t*data) 23{ 24rt_uint8_tbuf[3]; 25structrt_i2c_msgmsgs; 26 27buf[0]=reg;//cmd 28buf[1]=data[0]; 29buf[2]=data[1]; 30 31msgs.addr=AHT10_ADDR; 32msgs.flags=RT_I2C_WR; 33msgs.buf=buf; 34msgs.len=3; 35 36/*调用I2C设备接口传输数据*/ 37if(rt_i2c_transfer(bus,&msgs,1)==1) 38{ 39returnRT_EOK; 40} 41else 42{ 43return-RT_ERROR; 44} 45} 46 47/*读传感器寄存器数据*/ 48staticrt_err_tread_regs(structrt_i2c_bus_device*bus,rt_uint8_tlen,rt_uint8_t*buf) 49{ 50structrt_i2c_msgmsgs; 51 52msgs.addr=AHT10_ADDR; 53msgs.flags=RT_I2C_RD; 54msgs.buf=buf; 55msgs.len=len; 56 57/*调用I2C设备接口传输数据*/ 58if(rt_i2c_transfer(bus,&msgs,1)==1) 59{ 60returnRT_EOK; 61} 62else 63{ 64return-RT_ERROR; 65} 66} 67 68staticvoidread_temp_humi(float*cur_temp,float*cur_humi) 69{ 70rt_uint8_ttemp[6]; 71 72write_reg(i2c_bus,AHT10_GET_DATA,0);/*发送命令*/ 73read_regs(i2c_bus,6,temp);/*获取传感器数据*/ 74 75/*湿度数据转换*/ 76*cur_humi=(temp[1]<< 12 | temp[2] << 4 | (temp[3] & 0xf0) >>4)*100.0/(1<< 20); 77    /* 温度数据转换 */ 78    *cur_temp = ((temp[3] & 0xf) << 16 | temp[4] << 8 | temp[5]) * 200.0 / (1 << 20) - 50; 79} 80 81static void aht10_init(const char *name) 82{ 83    rt_uint8_t temp[2] = {0, 0}; 84 85    /* 查找I2C总线设备,获取I2C总线设备句柄 */ 86    i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); 87 88    if (i2c_bus == RT_NULL) 89    { 90        rt_kprintf("can't find %s device!\n", name); 91    } 92    else 93    { 94        write_reg(i2c_bus, AHT10_NORMAL_CMD, temp); 95        rt_thread_mdelay(400); 96 97        temp[0] = 0x08; 98        temp[1] = 0x00; 99        write_reg(i2c_bus, AHT10_CALIBRATION_CMD, temp);100        rt_thread_mdelay(400);101        initialized = RT_TRUE;102    }103}104105static void i2c_aht10_sample(int argc, char *argv[])106{107    float humidity, temperature;108    char name[RT_NAME_MAX];109110    humidity = 0.0;111    temperature = 0.0;112113    if (argc == 2)114    {115        rt_strncpy(name, argv[1], RT_NAME_MAX);116    }117    else118    {119        rt_strncpy(name, AHT10_I2C_BUS_NAME, RT_NAME_MAX);120    }121122    if (!initialized)123    {124        /* 传感器初始化 */125        aht10_init(name);126    }127    if (initialized)128    {129        /* 读取温湿度数据 */130        read_temp_humi(&temperature, &humidity);131132        rt_kprintf("read aht10 sensor humidity   : %d.%d %%\n", (int)humidity, (int)(humidity * 10) % 10);133        rt_kprintf("read aht10 sensor temperature: %d.%d \n", (int)temperature, (int)(temperature * 10) % 10);134    }135    else136    {137        rt_kprintf("initialize sensor failed!\n");138    }139}140/* 导出到 msh 命令列表中 */141MSH_CMD_EXPORT(i2c_aht10_sample, i2c aht10 sample);

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • SPI
    SPI
    +关注

    关注

    17

    文章

    1612

    浏览量

    89584
  • 总线
    +关注

    关注

    10

    文章

    2702

    浏览量

    87198
  • I2C
    I2C
    +关注

    关注

    28

    文章

    1346

    浏览量

    120791

原文标题:RT-Thread设备框架使用指南——I2C 总线设备

文章出处:【微信号:RTThread,微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    【先楫HPM5361EVK开发板试用体验】RT-Thread I2C使用

    RT-ThreadI2C简介 I2C(Inter Integrated Circuit)总线是 PHILIPS 公司开发的一种半双工、
    发表于 12-25 23:57

    分析rt-threadI2C设备驱动框架

    简要上一篇分析了RTT的PIN驱动,得到了很多网友的认可,很开心。很多人跟我反映写一些u***,wlan等框架,这个一步一步来,从浅到深。这一篇文章我们来分析rt-threadI2C设备
    发表于 01-12 06:23

    【资料】RT-Thread设备框架使用指南

    是合并进行的,如采样和保持,量化和编码在转换过程中是同时实现的。3、RT-Thread设备框架使用指南——I2C
    发表于 03-22 16:07

    基于RT-Thread设备框架实现的tca9534软件包

    游戏机)工业自动化gpio有限的处理器产品3 支持情况4 使用说明4.1 依赖RT-Thread 3.0.0+I2C 驱动,tca9534设备使用 I2C 进行数据通讯,需要系统
    发表于 05-16 16:21

    RT-ThreadI2C设备的驱动框架对接如何实现

    RT-Thread中引入了I2C设备设备驱动框架,该驱动框架提供了基于芯片GPIO进行模拟的
    发表于 05-19 17:11

    基于STM32L431RCT6讲解如何使用I2C设备接口及相关软件包

    中。由于 RT-Thread Nano 没有设备驱动框架,所以我们要把 i2c.h 中有关完整版的内容去掉。整理完之后的 i2c.h 文件如
    发表于 07-18 11:24

    如何使用I2C设备驱动接口开发应用程序

    2 个 GPIO 自行编写程序模拟 I2C 总线协议实现同样的功能。RT-Thread 提供了一套 I/O
    发表于 08-18 10:54

    基于RT-Thread测试NK-980 IoT开发板的I2C外设性能简析

    1、RT-Thread I2C应用实践  硬件环境  ● 开发板:Nuvoton NK-980 IoT  ● USB线:Micro-USB 连接线2根  ● I2C外设资源:
    发表于 10-12 15:56

    如何使用RT-Thread的串口设备

    即可。引入了带设备管理框架的实时操作系统 RT-Thread 后,串口的使用则与裸机或者其它 RTOS 有很大的不同之处。RT-Thread 中自带
    发表于 10-25 11:05

    详解RT-Thread I2C设备驱动框架及相关函数

    2 个 GPIO 自行编写程序模拟 I2C 总线协议实现同样的功能。RT-Thread 提供了一套 I/O
    发表于 10-25 12:02

    详细讲解RT-Thread I2C设备驱动框架及相关函数

    本应用笔记以驱动I2C接口的6轴传感器MPU6050为例,说明了如何使用I2C设备驱动接口开发应用程序,并详细讲解了RT-Thread I2C
    的头像 发表于 03-29 10:52 2w次阅读
    详细讲解<b class='flag-5'>RT-Thread</b> <b class='flag-5'>I2C</b><b class='flag-5'>设备</b>驱动<b class='flag-5'>框架</b>及相关函数

    RT-Thread设备模型框架及创建注册设备的实现

    RT-Thread设备模型框架及创建注册设备的实现方式介绍如下:
    的头像 发表于 05-28 10:38 1807次阅读
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>设备</b>模型<b class='flag-5'>框架</b>及创建注册<b class='flag-5'>设备</b>的实现

    RT-Thread文档_RT-Thread 简介

    RT-Thread文档_RT-Thread 简介
    发表于 02-22 18:22 5次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> <b class='flag-5'>简介</b>

    RT-Thread文档_I2C 总线设备

    RT-Thread文档_I2C 总线设备
    发表于 02-22 18:35 0次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>I2C</b> <b class='flag-5'>总线</b><b class='flag-5'>设备</b>

    浅析RT-Thread设备驱动框架

    RT-Thread 设备框架属于组件和服务层,是基于 RT-Thread 内核之上的上层软件。设备框架
    的头像 发表于 08-07 15:39 1265次阅读