6.3物联网RK3399项目开发实录-驱动开发之I2C 使用(wulianjishu666)

news/2024/6/20 19:20:42/文章来源:https://blog.csdn.net/vx349014857/article/details/137163555

物联网开发源码案例集:

链接:https://pan.baidu.com/s/1kfPDpYZpm_G0GBLAup3KTQ?pwd=vgvv

=============================================================

I2C 使用

简介

AIO-3399J 开发板上有 9 个片上 I2C 控制器,各个 I2C 的使用情况如下表:

_images/i2c_list.jpg

本文主要描述如何在该开发板上配置 I2C。

配置 I2C 可分为两大步骤:

  • 定义和注册 I2C 设备

  • 定义和注册 I2C 驱动

下面以配置 GSL3680 为例。

定义和注册 I2C 设备

在注册 I2C 设备时,需要结构体 i2c_client 来描述 I2C 设备。然而在标准 Linux 中,用户只需要提供相应的 I2C 设备信息,Linux 就会根据所提供的信息构造 i2c_client 结构体。

用户所提供的 I2C 设备信息以节点的形式写到 DTS 文件中,如下所示:

kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-edp.dts
&i2c4 {status = "okay";gsl3680: gsl3680@41 {compatible = "gslX680";reg = <0x41>;screen_max_x = <1536>;screen_max_y = <2048>;touch-gpio = <&gpio1 20 IRQ_TYPE_LEVEL_LOW>;reset-gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;};
};

定义和注册 I2C 驱动

定义 I2C 驱动

在定义 I2C 驱动之前,用户首先要定义变量 of_device_id 和 i2c_device_id

of_device_id 用于在驱动中调用 DTS 文件中定义的设备信息,其定义如下所示:

 static struct of_device_id gsl_ts_ids[] = {{.compatible = "gslX680"},{}};

定义变量 i2c_device_id

 static const struct i2c_device_id gsl_ts_id[] = {{GSLX680_I2C_NAME, 0},{}};MODULE_DEVICE_TABLE(i2c, gsl_ts_id);

i2c_driver 如下所示:

 static struct i2c_driver gsl_ts_driver = {.driver = { .name = GSLX680_I2C_NAME,.owner = THIS_MODULE,.of_match_table = of_match_ptr(gsl_ts_ids),},#ifndef CONFIG_HAS_EARLYSUSPEND//.suspend  = gsl_ts_suspend,//.resume   = gsl_ts_resume,#endif.probe      = gsl_ts_probe,.remove     = gsl_ts_remove,.id_table   = gsl_ts_id,};

注:变量 id_table 指示该驱动所支持的设备。

注册 I2C 驱动

使用 i2c_add_driver 函数注册 I2C 驱动。

i2c_add_driver(&gsl_ts_driver);

在调用 i2c_add_driver 注册 I2C 驱动时,会遍历 I2C 设备,如果该驱动支持所遍历到的设备,则会调用该驱动的 probe 函数。

通过 I2C 收发数据

在注册好 I2C 驱动后,即可进行 I2C 通讯。

  • 向从机发送信息:

 int i2c_master_send(const struct i2c_client *client, const char *buf, int count){int ret;struct i2c_adapter *adap = client->adapter;struct i2c_msg msg;msg.addr = client->addr;msg.flags = client->flags & I2C_M_TEN;msg.len = count;msg.buf = (char *)buf;ret = i2c_transfer(adap, &msg, 1);/** If everything went ok (i.e. 1 msg transmitted), return #bytes* transmitted, else error code.*/return (ret == 1) ? count : ret;}
  • 向从机读取信息:

 int i2c_master_recv(const struct i2c_client *client, char *buf, int count){struct i2c_adapter *adap = client->adapter;struct i2c_msg msg;int ret;msg.addr = client->addr;msg.flags = client->flags & I2C_M_TEN;msg.flags |= I2C_M_RD;msg.len = count;msg.buf = buf;ret = i2c_transfer(adap, &msg, 1);/** If everything went ok (i.e. 1 msg received), return #bytes received,* else error code.*/return (ret == 1) ? count : ret;}EXPORT_SYMBOL(i2c_master_recv);

FAQs

Q1: 通信失败,出现这种 log: “timeout, ipd: 0x00, state: 1” 该如何调试?

A1: 请检查硬件上拉是否给电。

Q2: 调用 i2c_transfer 返回值为 -6?

A2: 返回值为 -6 表示为 NACK 错误,即对方设备无应答响应,这种情况一般为外设的问题,常见的有以下几种情况:

  • I2C 地址错误,解决方法是测量 I2C 波形,确认是否 I2C 设备地址错误;

  • I2C slave 设备不处于正常工作状态,比如未给电,错误的上电时序等;

  • 时序不符合 I2C slave 设备所要求也会产生 Nack 信号。

Q3: 当外设对于读时序要求中间是 stop 信号不是 repeat start 信号的时候,该如何处理?

A3: 这时需要调用两次 i2c_transfer, I2C read 拆分成两次,修改如下:

static int i2c_read_bytes(struct i2c_client *client, u8 cmd, u8 *data, u8 data_len) {struct i2c_msg msgs[2];int ret;u8 *buffer;buffer = kzalloc(data_len, GFP_KERNEL);if (!buffer)return -ENOMEM;;msgs[0].addr = client->addr;msgs[0].flags = client->flags;msgs[0].len = 1;msgs[0].buf = &cmd;ret = i2c_transfer(client->adapter, msgs, 1);if (ret < 0) {dev_err(&client->adapter->dev, "i2c read failed\n");kfree(buffer);return ret;}msgs[1].addr = client->addr;msgs[1].flags = client->flags | I2C_M_RD;msgs[1].len = data_len;msgs[1].buf = buffer;ret = i2c_transfer(client->adapter, &msgs[1], 1);if (ret < 0)dev_err(&client->adapter->dev, "i2c read failed\n");elsememcpy(data, buffer, data_len);kfree(buffer);return ret;
}

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

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

相关文章

WebCopilot:一款功能强大的子域名枚举和安全漏洞扫描工具

关于WebCopilot WebCopilot是一款功能强大的子域名枚举和安全漏洞扫描工具&#xff0c;该工具能够枚举目标域名下的子域名&#xff0c;并使用不同的开源工具检测目标存在的安全漏洞。 工具运行机制 WebCopilot首先会使用assetsfinder、submaster、subfinder、accumt、finddom…

大数据学习第十二天(hadoop概念)

1、服务器之间数据文件传递 1&#xff09;服务器之间传递数据&#xff0c;依赖ssh协议 2&#xff09;http协议是web网站之间的通讯协议&#xff0c;用户可已通过http网址访问到对应网站数据 3&#xff09;ssh协议是服务器之间&#xff0c;或windos和服务器之间传递的数据的协议…

C语言第三十九弹---预处理(上)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 预处理 1、预定义符号 2、#define定义常量 3、#define定义宏 4、带有副作用的宏参数 5、宏替换的规则 6、宏和函数的对比 总结 在C语言中&#xff0c;预处…

阿里云2核4G云服务器支持多少人同时在线?并发数计算?

阿里云2核4G服务器多少钱一年&#xff1f;2核4G配置1个月多少钱&#xff1f;2核4G服务器30元3个月、轻量应用服务器2核4G4M带宽165元一年、企业用户2核4G5M带宽199元一年。可以在阿里云CLUB中心查看 aliyun.club 当前最新2核4G服务器精准报价、优惠券和活动信息。 阿里云官方2…

蓝奏云直链获取在线解析网站源码

源码简介 蓝奏云直链获取在线解析网站源码 蓝奏云链接解析 本地API接口 支持有无密码和短期直链和永久直链&#xff0c;同时还可以显示文件名和大小。 这个解析器无需数据库即可搭建&#xff0c;API接口已经本地化&#xff0c;非常简单易用。 安装环境 php5.6 搭建教程 …

在编程中使用中文到底该不该??

看到知乎上有个热门问题&#xff0c;为什么很多人反对中文在编程中的使用&#xff1f; 这个问题有几百万的浏览热度&#xff0c;其中排名第一的回答非常简洁&#xff0c;我深以为然&#xff1a; 在国内做开发&#xff0c;用中文写注释、写文档&#xff0c;是非常好的习惯&…

前端工程师————HTML5学习

HTML5基础 开发工具很多&#xff0c;其中Hbulider较好用&#xff0c;下载网址如下&#xff1a; DCloud - HBuilder、HBuilderX、uni-app、uniapp、5、5plus、mui、wap2app、流应用、HTML5、小程序开发、跨平台App、多端框架 html表示整个页面 head表示搜素框 body表示内容 ti…

Java练习

这个练习我用到了继承&#xff0c;多态和封装。 1.继承&#xff1a; Animal 类是一个抽象类&#xff0c;它有两个子类 Dog 和 Cat。 Dog 和 Cat 分别继承自 Animal 类&#xff0c;因此它们可以使用 Animal 类中定义的属性和方法&#xff0c;同时也可以有自己特有的属性和方法。…

【Java代码审计】SSTI模板注入篇

【Java代码审计】SSTI模板注入篇 1.概述2.Velocity 模板引擎3.Thymeleaf 模板注入复现普通url作为视图 4.SSTI 漏洞修复白名单控制跳转模版设置response参数 1.概述 模板引擎支持使用静态模板文件&#xff0c;在运行时用 HTML 页面中的实际值替换变量/占位符&#xff0c;从而让…

C++要学到什么程度才能找到实习?

在考虑 C 学习到何种程度可以找到实习时&#xff0c;以下是一些具体的方向和建议。我这里有一套编程入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习编程&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私信22&#xff0c;我…

java学习之路-数组定义与使用

目录 ​编辑 1.什么是数组 2.数组的创建及其初始化 2.1数组的创建 2.2数组的初始化 3.数组的使用 3.1数组元素访问 3.2遍历数组 4.数组是引用类型 4.1jvm的内存分布 4.2基本类型变量与引用类型变量的区别 4.3引用变量详解 4.4 null 5.数组的使用场景 5.1存储数据 5…

使用Vue实现CSS过渡和动画

01-初识动画和过渡 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>使用vue实现css过渡和动画&l…

数据结构——遍历二叉树和线索二叉树,树和森林

目录 1.遍历的算法实现 1.先序遍历 代码示例&#xff1a; 2.中序遍历 代码示例&#xff1a; 3.后序遍历 代码示例&#xff1a; 4.遍历算法的分析 2.遍历二叉树的非递归算法 1.中序遍历非递归算法 代码示例&#xff1a; 3.二叉树的层次遍历 代码示例&#xff1a; 4.二…

c#仿ppt案例

画曲线 namespace ppt2024 {public partial class Form1 : Form{public Form1(){InitializeComponent();}//存放所有点的位置信息List<Point> lstPosition new List<Point>();//控制开始画的时机bool isDrawing false;//鼠标点击开始画private void Form1_MouseD…

网络原理 - HTTP / HTTPS(2)——http请求

目录 一、认识 “方法”&#xff08;method&#xff09; 1、GET方法 2、POST方法 &#xff08;1&#xff09;登录 &#xff08;2&#xff09;上传 &#xff08;3&#xff09;GET和POST使用习惯 3、GET方法和POST方法的区别 正确滴 关于一些网上的说法&#xff0c;错误滴…

电商技术揭秘四:电商平台的物流管理系统

文章目录 引言一、物流管理系统的功能与架构1.1 物流管理系统在电商平台中的作用概述保障订单的及时配送优化库存管理控制运营成本提升客户服务水平支持数据驱动的决策应对市场变化 1.2 订单处理功能分析自动化处理流程订单分配与履行错误检测与处理机制实时订单状态更新订单数…

新能源汽车充电桩常见类型及充电桩站场的智能监管方案

随着新能源汽车市场的迅猛发展&#xff0c;充电桩作为支持其运行的基础设施&#xff0c;也呈现出多样化的类型。这些充电桩不仅在外形和功能上存在差异&#xff0c;更在充电速度、充电方式以及使用场景等方面展现出独特的优势。 一、充电桩类型及区别 1、慢充桩&#xff08;交…

5.vector容器的使用

文章目录 vector容器1.构造函数代码工程运行结果 2.赋值代码工程运行结果 3.容量和大小代码工程运行结果 4.插入和删除代码工程运行结果 5.数据存取工程代码运行结果 6.互换容器代码工程运行结果 7.预留空间代码工程运行结果 vector容器 1.构造函数 /*1.默认构造-无参构造*/ …

苹果开发者账号注册后生成开发证书和发布证书的流程解析

转载&#xff1a;注册苹果开发者账号的方法 在2020年以前&#xff0c;注册苹果开发者账号后&#xff0c;就可以生成证书。 但2020年后&#xff0c;因为注册苹果开发者账号需要使用Apple Developer app注册开发者账号&#xff0c;所以需要缴费才能创建ios证书了。 所以新政策出…

Redis的5大常见数据类型的用法

上一篇文章我们讲了Redis的10大应用场景&#xff0c;这一篇文章就针对Redis的常用数据结构进行一个说明&#xff0c;通过示例的形式演示每一种数据结构如何使用。 当涉及Redis的数据操作时&#xff0c;不同数据类型对应的不同数据结构&#xff0c;如下就对5大常用的数据类型进行…