RTT应用编程_iic应用编程

1.应用层使用-摘录值RTT官方

访问 I2C 总线设备

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

函数描述
rt_device_find()根据 I2C 总线设备名称查找设备获取设备句柄
rt_i2c_transfer()传输数据

查找 I2C 总线设备

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

rt_device_t rt_device_find(const char* name);
参数描述
nameI2C 总线设备名称
返回——
设备句柄查找到对应设备将返回相应的设备句柄
RT_NULL没有找到相应的设备对象

一般情况下,注册到系统的 I2C 设备名称为 i2c0 ,i2c1等,使用示例如下所示:

#define AHT10_I2C_BUS_NAME      "i2c1"  /* 传感器连接的I2C总线设备名称 */
struct rt_i2c_bus_device *i2c_bus;      /* I2C总线设备句柄 *//* 查找I2C总线设备,获取I2C总线设备句柄 */
i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name);

数据传输

获取到 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);
参数描述
busI2C 总线设备句柄
msgs[]待传输的消息数组指针
num消息数组的元素个数
返回——
消息数组的元素个数成功
错误码失败

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

[!NOTE] 注:此函数会调用 rt_mutex_take(), 不能在中断服务程序里面调用,会导致 assertion 报错。

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

struct rt_i2c_msg
{rt_uint16_t addr;    /* 从机地址 */rt_uint16_t flags;   /* 读、写标志等 */rt_uint16_t len;     /* 读写数据字节数 */rt_uint8_t  *buf;    /* 读写数据缓冲区指针 */
}

从机地址 addr:支持 7 位和 10 位二进制地址,需查看不同设备的数据手册 。

[!NOTE] 注:RT-Thread I2C 设备接口使用的从机地址均不包含读写位,读写位控制需修改标志 flags。

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

#define RT_I2C_WR              0x0000        /* 写标志,不可以和读标志进行“|”操作 */
#define RT_I2C_RD              (1u << 0)     /* 读标志,不可以和写标志进行“|”操作 */
#define RT_I2C_ADDR_10BIT      (1u << 2)     /* 10 位地址模式 */
#define RT_I2C_NO_START        (1u << 4)     /* 无开始条件 */
#define RT_I2C_IGNORE_NACK     (1u << 5)     /* 忽视 NACK */
#define RT_I2C_NO_READ_ACK     (1u << 6)     /* 读的时候不发送 ACK */
#define RT_I2C_NO_STOP         (1u << 7)     /* 不发送结束位 */

使用示例如下所示:

#define AHT10_I2C_BUS_NAME      "i2c1"  /* 传感器连接的I2C总线设备名称 */
#define AHT10_ADDR               0x38   /* 从机地址 */
struct rt_i2c_bus_device *i2c_bus;      /* I2C总线设备句柄 *//* 查找I2C总线设备,获取I2C总线设备句柄 */
i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name);/* 读传感器寄存器数据 */
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;             /* 读写数据字节数 *//* 调用I2C设备接口传输数据 */if (rt_i2c_transfer(bus, &msgs, 1) == 1){return RT_EOK;}else{return -RT_ERROR;}
}

I2C 从设备数据读写API

以下两个读写函数封装自 rt_i2c_transfer() 函数,用于读写I2C从设备的数据,更加简单易用,推荐使用。

向 I2C 从设备发送数据:

rt_size_t rt_i2c_master_send(struct rt_i2c_bus_device *bus,rt_uint16_t               addr,rt_uint16_t               flags,const rt_uint8_t         *buf,rt_uint32_t               count);
参数描述
busI2C 总线设备句柄
addrI2C 从设备地址
flags标志位,可为上文提到的除 RT_I2C_WR RT_I2C_RD之外的其他标志位,可以进行 “\
buf待数据数据缓冲区
count待发送数据大小(单位:字节)
返回——
消息数组的元素个数成功
错误码失败

从 I2C 从设备读取数据,数据会放在缓冲区中:

rt_size_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus,rt_uint16_t               addr,rt_uint16_t               flags,rt_uint8_t               *buf,rt_uint32_t               count);
参数描述
busI2C 总线设备句柄
addrI2C 从设备地址
flags标志位,可为上文提到的除 RT_I2C_WR RT_I2C_RD之外的其他标志位,可以进行 “\
buf数据缓冲区
count缓冲区大小(单位:字节,要大于等于最大接收到的数据长度)
返回——
消息数组的元素个数成功
错误码失败

小技巧

有时,I2C数据需要通过多次函数拼接而成,通过如下方法,可以实现拼接发送一条I2C数据,数据内容为 prefix_buffer + buffer:

rt_i2c_master_send(_i2c_bus_dev, _addr, RT_I2C_NO_STOP, prefix_buffer, prefix_len); /* 只发送起始位,不发送停止位 */
rt_i2c_master_send(_i2c_bus_dev, _addr, RT_I2C_NO_START, buffer, len); /* 不发送起始位,只发送停止位 */

I2C 总线设备使用示例

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

  1. 首先根据 I2C 设备名称查找 I2C 名称,获取设备句柄,然后初始化 aht10 传感器。
  2. 控制传感器的两个函数为写传感器寄存器 write_reg() 和读传感器寄存器 read_regs(),这两个函数分别调用了 rt_i2c_transfer() 传输数据。读取温湿度信息的函数 read_temp_humi() 则是调用这两个函数完成功能。
/** 程序清单:这是一个 I2C 设备使用例程* 例程导出了 i2c_aht10_sample 命令到控制终端* 命令调用格式:i2c_aht10_sample i2c1* 命令解释:命令第二个参数是要使用的I2C总线设备名称,为空则使用默认的I2C总线设备* 程序功能:通过 I2C 设备读取温湿度传感器 aht10 的温湿度数据并打印
*/#include <rtthread.h>
#include <rtdevice.h>#define AHT10_I2C_BUS_NAME          "i2c1"  /* 传感器连接的I2C总线设备名称 */
#define AHT10_ADDR                  0x38    /* 从机地址 */
#define AHT10_CALIBRATION_CMD       0xE1    /* 校准命令 */
#define AHT10_NORMAL_CMD            0xA8    /* 一般命令 */
#define AHT10_GET_DATA              0xAC    /* 获取数据命令 */static struct rt_i2c_bus_device *i2c_bus = RT_NULL;     /* I2C总线设备句柄 */
static rt_bool_t initialized = RT_FALSE;                /* 传感器初始化状态 *//* 写传感器寄存器 */
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;rt_uint32_t buf_size = 1;buf[0] = reg; //cmdif (data != RT_NULL){buf[1] = data[0];buf[2] = data[1];buf_size = 3;}msgs.addr = AHT10_ADDR;msgs.flags = RT_I2C_WR;msgs.buf = buf;msgs.len = buf_size;/* 调用I2C设备接口传输数据 */if (rt_i2c_transfer(bus, &msgs, 1) == 1){return RT_EOK;}else{return -RT_ERROR;}
}/* 读传感器寄存器数据 */
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;/* 调用I2C设备接口传输数据 */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, RT_NULL);      /* 发送命令 */rt_thread_mdelay(400);read_regs(i2c_bus, 6, temp);                /* 获取传感器数据 *//* 湿度数据转换 */*cur_humi = (temp[1] << 12 | temp[2] << 4 | (temp[3] & 0xf0) >> 4) * 100.0 / (1 << 20);/* 温度数据转换 */*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};/* 查找I2C总线设备,获取I2C总线设备句柄 */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){/* 传感器初始化 */aht10_init(name);}if (initialized){/* 读取温湿度数据 */read_temp_humi(&temperature, &humidity);rt_kprintf("read aht10 sensor humidity   : %d.%d %%\n", (int)humidity, (int)(humidity * 10) % 10);if( temperature >= 0 ){rt_kprintf("read aht10 sensor temperature: %d.%d°C\n", (int)temperature, (int)(temperature * 10) % 10);}else{rt_kprintf("read aht10 sensor temperature: %d.%d°C\n", (int)temperature, (int)(-temperature * 10) % 10);}}else{rt_kprintf("initialize sensor failed!\n");}
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(i2c_aht10_sample, i2c aht10 sample);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/19000.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

持续部署CICD

目录 &#xff08;1&#xff09;CICD的开展场景 &#xff08;2&#xff09;项目实际应用 CICD 是持续集成&#xff08;Continuous Integration&#xff09;和持续部署&#xff08;Continuous Deployment&#xff09;简称。指在研发过程中自动执行一系列脚本来降低开发引入 bug…

tomcat8的安装与服务启动脚本的配置并部署jpress应用

目录 一.了解tomcat8 二.下载安装包 三.安装jdk与tomcat 1.安装jdk 2.安装tomcat &#xff08;1&#xff09;解压安装包并创建软链接 &#xff08;2&#xff09;设置启动用户并更改权限 &#xff08;3&#xff09;编写系统服务文件 &#xff08;4&#xff09;重新加载文件…

ChatGPT结合知识图谱构建医疗问答应用 (一) - 构建知识图谱

一、ChatGPT结合知识图谱 在本专栏的前面文章中构建 ChatGPT 本地知识库问答应用&#xff0c;都是基于词向量检索 Embedding 嵌入的方式实现的&#xff0c;在传统的问答领域中&#xff0c;一般知识源采用知识图谱来进行构建&#xff0c;但基于知识图谱的问答对于自然语言的处理…

python Pandas.rank() 排名函数详解

文章目录 Pandas.rank() 函数详解一、参数解析二、案例分享默认排名降序: ascending Falsemethod minmethod maxmethod firstmethod densena_optionbottompct True Pandas.rank() 函数详解 一、参数解析 method&#xff1a;指定排名时的策略。 默认值为 average&#x…

手机python编程软件怎么用,手机python编程软件下载

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;手机python编程软件保存的代码在哪里&#xff0c;手机python编程软件怎么运行&#xff0c;现在让我们一起来看看吧&#xff01; 原标题&#xff1a;盘点几个在手机上可以用来学习编程的软件 前天在悟空问答的时候&#…

前端生成图片验证码怎么做?

##题记&#xff1a;我们实现一个功能首先想一下我们需要做哪些工作&#xff0c;比如我们需要生成一个随机的图片验证码&#xff0c;我们需要一个就是点击事件获取验证码&#xff0c;通过接口我们去获取图片路径进行渲染就行&#xff0c;这里边还要牵扯一件事情就是获取一个随机…

如何使用 PHP 进行数据库索引优化?

首先&#xff0c;我们要明白什么是数据库索引。想象一下&#xff0c;如果你有一堆垃圾邮件&#xff0c;想要找出一封特定的邮件&#xff0c;你会怎么做&#xff1f;对&#xff0c;就是翻阅所有的邮件&#xff0c;直到找到你想要的那封。这就是数据库没有索引的情况。想象一下&a…

HTTP之Session、Cookie 与 Application

目录 简介cookiecookie生命周期 sessionsession生命周期 HTTP cookies示例application 简介 cookie、seesion、application三个都会缓存我们用户状态的数据&#xff0c;使得我们在浏览器访问网站时可以更快速的获取到信息。 主要原因在于HTTP协议是无状态的&#xff0c;我们每…

友好城市(LCS问题)

Palmia国有一条横贯东西的大河&#xff0c;河有笔直的南北两岸&#xff0c;岸上各有位置各不相同的N个城市。 北岸的每个城市有且仅有一个友好城市在南岸&#xff0c;而且不同城市的友好城市不相同。 每对友好城市都向政府申请在河上开辟一条直线航道连接两个城市&#xff0c…

Git笔记--Ubuntu上传本地项目到github

目录 1--基本配置 2--本地上传 1--基本配置 ① 创建ssh-key cd ~/.sshssh-keygen -t rsa -C "邮箱地址"② 查看并关联ssh-key gedit id_rsa.pub 复制内容&#xff0c;在 GitHub 中依次点击 Settings -> SSH and GPG keys -> New SSH key&#xff0c;将 id…

Linux虚拟机中安装MySQL5.6.34

目录 第一章、xshell工具和xftp的使用1.1&#xff09;xshell下载与安装1.2&#xff09;xshell连接1.3&#xff09;xftp下载安装和连接 第二章、安装MySQL5.6.34&#xff08;不同版本安装方式不同)2.1&#xff09;关闭防火墙&#xff0c;传输MySQL压缩包到Linux虚拟机2.2&#x…

Mybatis 知识点

Mybatis 知识点 1.1 Mybatis 简介 1.1.1 什么是 Mybatis Mybatis 是一款优秀的持久层框架支持定制化 SQL、存储过程及高级映射Mybatis 几乎避免了所有的 JDBC 代码和手动设置参数以及获取结果集MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO…

python-pytorch基础之神经网络回归

这里写目录标题 定义数据集定义函数生成数据集 使用Dataloader加载dataset定义神经网络定义实例化查看是否是输出的一个 训练编写trian方法训练并保存模型 测试模型结果构造数据测试结论 定义数据集 import torch import random定义函数 # 生成数据 def get_rancledata():wid…

Spring的@Scheduled

Spring的Scheduled的默认线程池数量为1&#xff0c;也就是说定时任务是单线程执行的。这意味着最多同时只有一个任务在执行。当一个任务还在执行时&#xff0c;其他任务会等待其完成&#xff0c;然后按照其预定的执行策略依次执行。 测试代码&#xff1a; 启动类上加注解Enab…

网络编程 IO多路复用 [epoll版] (TCP网络聊天室)

//head.h 头文件 //TcpGrpSer.c 服务器端 //TcpGrpUsr.c 客户端 通过IO多路复用实现服务器在单进程单线程下可以与多个客户端交互 API epoll函数 #include<sys/epoll.h> int epoll_create(int size); 功能&#xff1a;创建一个epoll句柄//创建红黑树根…

idea如何加快创建Maven项目的速度

一、下载archetype-catalog.xml 下载archetype-catalog.xml的地址 二、配置 以下所说的配置都指全局配置 配置Maven -DarchetypeCataloglocal -Dfile.encodinggbk

线程、进程和管程

一、线程 1.1 定义 线程&#xff1a;线程是进程中的实体&#xff0c;一个进程可以拥有多个线程&#xff0c;一个线程必须有一个父进程。线程有时被称为轻量级进程&#xff0c;是程序执行流的最小单元。 线程的组成部分&#xff1a; 1. 线程ID&#xff1a;线程标识符 2. 当前…

【C++从0到王者】第十五站:list源码分析及手把手教你写一个list

文章目录 一、list源码分析1.分析构造函数2.分析尾插等 二、手把手教你写一个list1.结点声明2.list类的成员变量3.list类的默认构造函数4.list类的尾插5.结点的默认构造函数6.list类的迭代器7.设计const迭代器8.list的insert、erase等接口9.size10.list的clear11.list的析构函数…

SQLserver数据日期数据处理方式(日期查询,日期转换字符串)

获取本月第一天 dateadd(dd,-day(getdate())1,getdate()) 获取下月第一天&#xff08;数据 当前日期减去 日数 在加一个月&#xff09; DATEADD(MM,1,dateadd(dd,-day(getdate())1,getdate())) 获取本月最后一天&#xff08;&#xff09; 将日期转换为字符串的方法两种 1.使用c…

arm neon/fpu/mfloat

neon官网介绍: Arm Neon technology is an advanced Single Instruction Multiple Data (SIMD) architecture extension for the A-profile and R-profile processors. Neon technology is a packed SIMD architecture. Neon registers are considered as vectors of elements …