Linux应用编程 - i2c-dev操作I2C

        嵌入式Linux操作I2C设备,我们一般会在内核态编写I2C驱动程序。另外还能在用户空间编写I2C程序,下面介绍相关代码的实现。

        i2c-dev框架在内核中封装了I2C通信所需要的所有通信细节,I2C适配器会在/dev目录下创建字符设备,例如:/dev/i2c-0,通过系统调用操作/dev/i2c-0就可以实现与I2C设备通信。

    

一、I2C适配器操作函数

        下面介绍如何在用户空间打开I2C适配器,并使用I2C适配器读写I2C设备。

1、打开I2C适配器

         调用open系统调用打开/dev/i2c-n文件

/* 打开字符设备 */
s32 hal_i2c_open(u32 u32I2cIdx, s32 *ps32Fd)
{s32 s32Fd          = 0;s8    s8Fname[128]  = {0,};sprintf((char *)s8Fname, "/dev/i2c-%u", u32I2cIdx);s32Fd = open((char *)s8Fname, 0);if (0 >= s32Fd){LOG_WARN("i2c open %s s32Fd=%d,retry it\n",s8Fname,s32Fd);s32Fd = open((char *)s8Fname, 0);if (0 >= s32Fd){LOG_ERR("Open %s error, s32Fd %d,u32I2cIdx:0x%X!\n",s8Fname, s32Fd,u32I2cIdx);return -1;}}*ps32Fd  = s32Fd;return 0;
}/* 关闭字符设备 */
s32 hal_i2c_close(s32 s32Fd)
{if(0 >= s32Fd){LOG_ERR("failed !\n");return -1;}close(s32Fd);return 0;
}

2、I2C适配器读写

        通过ioctl去读写I2C适配器从而与I2C设备通信

/*
*****************************************************************************************
*	函 数 名: hal_i2c_read
*	功能说明: I2C读
*	形    参: s32Fd       : I2C节点
*           u16DevAddr  : 设备地址
*           u16RegAddr  : 寄存器地址
*           u16RegLen   : 寄存器长度
*           pu8Buf      : 读取数据buf
*           u16DataLen  : 需要读取数据长度
*	返 回 值: 返回0:OK
*            其他: ERROR
*****************************************************************************************
*/
s32 hal_i2c_read(s32 s32Fd, u16 u16DevAddr, u16 u16RegAddr,u16 u16RegLen, u8 *pu8Buf, u16 u16DataLen)
{u8  u8Buf[2]  = {0,};struct i2c_rdwr_ioctl_data rdwr = {0};struct i2c_msg msg[2] = {0};if(I2C_DEVICE_REG_LEN_2BIT == u16RegLen){  u8Buf[0] = (u16RegAddr >> 8) & 0xff;u8Buf[1] = u16RegAddr & 0xff;}else{                       //8位寄存器u8Buf[0] = u16RegAddr & 0xff;}msg[0].addr  = u16DevAddr; //设备地址msg[0].flags = 0;msg[0].len   = u16RegLen;msg[0].buf   = u8Buf;  //存放寄存器的地址msg[1].addr = u16DevAddr;msg[1].flags = 0;msg[1].flags |= I2C_M_RD;msg[1].len = u16DataLen;  //需要读取的数据长度msg[1].buf = pu8Buf;//存放返回数据的地址rdwr.msgs = &msg[0];rdwr.nmsgs = 2;if(ioctl(s32Fd, I2C_RDWR, &rdwr) != 2){LOG_ERR("CMD_I2C_READ error! \n");goto Error;}return 0;Error:return -1;
}/*
*****************************************************************************************
*	函 数 名: hal_i2c_write
*	功能说明: I2C写
*	形    参: s32Fd       : I2C节点
*           u16DevAddr  : 设备地址
*           u16RegAddr  : 寄存器地址
*           u16RegLen   : 寄存器长度
*           pu8Buf      : 写入数据buf
*           len         : 需要写入数据长度
*	返 回 值: 返回0:OK
*            其他: ERROR
*****************************************************************************************
*/
s32 hal_i2c_write(s32 s32Fd, u16 u16DevAddr, u16 u16RegAddr,u16 u16RegLen, u8 *pu8Buf, u16 len)
{u8 *pu8SendBuff = NULL;struct i2c_rdwr_ioctl_data rdwr = {0,};struct i2c_msg messages = {0,};if(I2C_DEVICE_REG_LEN_2BIT == u16RegLen){pu8SendBuff = (u8 *)malloc(len + I2C_DEVICE_REG_LEN_2BIT);  //需要传递的buffer中,头2个字节是寄存器地址pu8SendBuff[0] = (u16RegAddr >> 8) & 0xff;   //保存寄存器地址值pu8SendBuff[1] = u16RegAddr & 0xff;}else{pu8SendBuff = (u8 *)malloc(len + I2C_DEVICE_REG_LEN_1BIT);pu8SendBuff[0] = u16RegAddr & 0xff;   //保存寄存器地址值}if (NULL == pu8SendBuff){LOG_ERR("malloc failed!\n");return -1;}if (NULL != pu8Buf){if(I2C_DEVICE_REG_LEN_2BIT == u16RegLen)memcpy(&pu8SendBuff[I2C_DEVICE_REG_LEN_2BIT], pu8Buf, len);    //寄存器地址长度为2,需要从pu8SendBuff[2]开始存放需要写的buffer数据elsememcpy(&pu8SendBuff[I2C_DEVICE_REG_LEN_1BIT], pu8Buf, len);}messages.addr = u16DevAddr;  //设备地址messages.flags = 0;messages.buf = pu8SendBuff; if(I2C_DEVICE_REG_LEN_2BIT == u16RegLen)messages.len = len + I2C_DEVICE_REG_LEN_2BIT;elsemessages.len = len + I2C_DEVICE_REG_LEN_1BIT;rdwr.msgs = &messages;rdwr.nmsgs = 1;if(0 >= ioctl(s32Fd, I2C_RDWR, (unsigned long)&rdwr)){perror("error:");LOG_ERR("I2C send failed!\n");goto Error;}free(pu8SendBuff);return 0;Error:free(pu8SendBuff);return -1;
}

二、实例

        ap3216C是一款三合一环境传感器,它内部集成了:数字环境光传感器(Ambilent Light Aensors,ALS)、距离传感器(Proximity Sense,PS)和一个红外LED(Infrared Radiation LED,IR LED),该芯片通过IIC接口连接ARM板,设备地址为0x1E

下图为主要的几个寄存器:

首先,我们可以用i2cdetect工具去探测I2C1上的ap3216c芯片,看硬件通路是否正常

$ i2cdetect -r -y 0

1、读ap3216c芯片的数据

代码下载链接:https://download.csdn.net/download/hinewcc/89438732

从I2C适配器接口操作ap3216c的代码如下:

/* 打开/dev/i2c-0 */
static s32 ap3216c_i2c_open(u32 _u32I2cIdx, s32 *_ps32Fd)
{hal_i2c_open(_u32I2cIdx, _ps32Fd);return 0;
}/* I2C写单个寄存器 */
static s32 ap3216c_write_reg(s32 _s32Fd, u8 _u8Reg, u8 _u8Data)
{HAL_DEV_I2C_INFO_S stData = {0};stData.u16DevAddr   = AP3216C_ADDR; 	//设备地址stData.u16RegAddr   = _u8Reg;        	//寄存器地址stData.u16RegLen    = AP3216C_REG_W; 	//寄存器地址长度return hal_i2c_write(_s32Fd, stData.u16DevAddr, stData.u16RegAddr, stData.u16RegLen, &_u8Data, 1);
}/* I2C读单个寄存器 */
static s32 ap3216c_read_reg(s32 _s32Fd, u8 _u8Reg, u8 *_pData)
{HAL_DEV_I2C_INFO_S stData = {0};u8 data = 0;stData.u16DevAddr   = AP3216C_ADDR; //设备地址stData.u16RegAddr   = _u8Reg;        //寄存器地址stData.u16RegLen    = AP3216C_REG_W; //寄存器地址长度return hal_i2c_read(_s32Fd, stData.u16DevAddr, stData.u16RegAddr, stData.u16RegLen, _pData, 1);
}/* 关闭i2c */
static s32 ap3216c_i2c_close(s32 _s32Fd)
{hal_i2c_close(_s32Fd);return 0;
}

最终,ap3216c适配层会提供如下接口给应用层调用

/*
*********************************************************************************************************
*	函 数 名: ap3216c_init
*	功能说明: 初始化
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
int ap3216c_init(void)
{ap3216c_i2c_open(I2C_INDEX, &g_stAp3216c.s32Fd);/* 初始化AP3216C */ap3216c_write_reg(g_stAp3216c.s32Fd, AP3216C_SYSTEMCONG, 0x04);	/* 复位AP3216C */usleep(100000);													/* AP3216C复位最少10ms */ap3216c_write_reg(g_stAp3216c.s32Fd, AP3216C_SYSTEMCONG, 0X03);	/* 开启ALS、PS+IR */return 0;
}/*
*********************************************************************************************************
*	函 数 名: ap3216c_deinit
*	功能说明: 初始化
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
int ap3216c_deinit(void)
{if (g_stAp3216c.s32Fd != NULL) {ap3216c_i2c_close(g_stAp3216c.s32Fd);g_stAp3216c.s32Fd = NULL;}return 0;
}/*
*********************************************************************************************************
*	函 数 名: ap3216c_getdata
*	功能说明: 读数据
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
int ap3216c_getdata(HAL_AP3216C_DATA_T *_pstData)
{u8 u8Buf[6] = {0};int i;unsigned short ir, als, ps;if (g_stAp3216c.s32Fd == NULL) {return -1;}for(i = 0; i < 6; i++) {ap3216c_read_reg(g_stAp3216c.s32Fd, AP3216C_REG_IR_L + i, &u8Buf[i]);	//读单个寄存器}if(u8Buf[0] & 0X80) 	/* IR_OF位为1,则数据无效 */ir = 0;					else 				/* 读取IR传感器的数据 */ir = ((unsigned short)u8Buf[1] << 2) | (u8Buf[0] & 0X03); 			als = ((unsigned short)u8Buf[3] << 8) | u8Buf[2];	/* 读取ALS传感器的数据 */  if(u8Buf[4] & 0x40)	/* IR_OF位为1,则数据无效 */ps = 0;    													else 				/* 读取PS传感器的数据 */ps = ((unsigned short)(u8Buf[5] & 0X3F) << 4) | (u8Buf[4] & 0X0F); _pstData->usIr = ir;_pstData->usAls = als;_pstData->usPs = ps;return 0;
}

main函数while循环中读取ap3216c的数据

int main(int argc, char* argv[])
{HAL_AP3216C_DATA_T stAp3216c;ap3216c_init();							//初始化while(1){ap3216c_getdata(&stAp3216c);		//读数据printf("ir = %d, als = %d, ps = %d\r\n", stAp3216c.usIr, stAp3216c.usAls, stAp3216c.usPs);usleep(200000); /* 200ms */}return 0;
}

2、测试结果

/ # ./test_app
Ap3216c: ir = 0, als = 12, ps = 0
Ap3216c: ir = 3, als = 15, ps = 0
Ap3216c: ir = 4, als = 11, ps = 0
Ap3216c: ir = 3, als = 12, ps = 0

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

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

相关文章

kettle从入门到精通 第七十课 ETL之kettle kettle数据校验,脏数据清洗轻松拿捏

场景&#xff1a;输入在指定的错误(错误应涵盖数据类型不匹配的情况)行数内&#xff0c;trans不报错&#xff0c;但通过错误处理步骤捕捉&#xff0c;并记入文件&#xff0c;整个数据管线正常完成直至处理完最后一个输入行。 解决方案&#xff1a;使用步骤【数据检验】进行处理…

本周MoonBit新增Wasm1引用计数支持、语法即将添加错误恢复机制

MoonBit更新 【Wasm MVP】Wasm1 后端添加基于 Perceus 算法的引用计数支持 【语法】throw raise try catch 均被保留为关键字 为了即将添加的错误处理机制 【Core】List与sorted_map被移动至core/immut下 List被移动至core/immut/list包中&#xff0c;并被移除内置类型支持 …

哈希表、递归在二叉树中的应用-1372. 二叉树中的最长交错路径

题目链接及描述 1372. 二叉树中的最长交错路径 - 力扣&#xff08;LeetCode&#xff09; 题目分析 题目所述&#xff0c;计算在二叉树中交替遍历的最大深度【左->右->左】【右->左->右】&#xff0c;例如对于从当前根节点root出发&#xff0c;则此时遍历方向有两个…

今日成果2024-6-7 TrustZone TEE安全SDK开发指南

Rockchip Vendor Storage Application Note.pdf OK 开机下&#xff0c;可以实现Vendor Storage的读写。 0ms时同步RTC时间 OK Rockchip_Developer_Guide_TEE_SDK_CN.pdf 什么是TrustZone 此系统方法意味着可以保护安全内存、加密块、键盘和屏幕等外设&#xff0c;从而可确…

视频剪辑可以赚钱吗 快速学会视频剪辑的方法

由于视频剪辑的需求不断增长&#xff0c;学会视频剪辑成为一项自媒体必备的技能&#xff0c;这个技能可以为个人带来收入和职业发展带来机会。无论是作为自由职业者还是在公司工作&#xff0c;掌握视频剪辑技能都可以为你提供更多的工作机会和竞争优势。这篇文章将讲解视频剪辑…

2.深度学习-线性回归

文章目录 环境配置&#xff08;必看&#xff09;线性回归代码工程运行结果1.对比图2.运行结果 环境配置&#xff08;必看&#xff09; Anaconda-创建虚拟环境的手把手教程相关环境配置看此篇文章&#xff0c;本专栏深度学习相关的版本和配置&#xff0c;均按照此篇文章进行安装…

Carsim高级开发:VS Connect通讯开发指南

文章目录 前言一、VS Connect 概念引入二、VS Connect 通讯框架三、Carsim 工程配置1、车辆模型配置2、procedure配置3、Run Control配置4、受控车辆名称配置 四、VS Connect Server代码1、打开Sln工程2、代码修改 五、VS Connect Client代码1、函数的调用关系2、carsim_variab…

5G消息 x 文旅 | 一站式智慧文旅解决方案

5G消息 x 文旅 | 一站式智慧文旅解决方案 文旅 x 5G 消息将进一步强化资源整合&#xff0c;满足游客服务需求、企业营销需求、政府管理需求&#xff0c;推进文化旅游项目的智慧化、数字化&#xff0c;增强传播力、竞争力和可持续性。5G 消息的“原生入口”、“超强呈现”、“智…

帕金森病的食疗建议

帕金森病&#xff08;PD&#xff09;是一种慢性、进展性的神经退行性疾病&#xff0c;主要影响中老年人。虽然目前尚无法根治&#xff0c;但及早规范治疗可显著改善症状&#xff0c;提高患者的生活质量。饮食调理作为帕金森病综合治疗的重要组成部分&#xff0c;对于维持患者较…

接口测试详解

接口测试详解 本文主要讲软件接口 一、什么是接口&#xff1f;硬件接口&#xff1a;硬件接口指的是硬件提供给外界的一种实体。主要作用是内部数据分离出外 部的沟通方法 目的是&#xff1a;沟通外部来改变内部的数据。如&#xff1a;USB接口&#xff0c;投影仪接口 软件接口…

【CDN】逆天 CDN !BootCDN 向 JS 文件中植入恶意代码

今天在调试代码&#xff0c;突然控制台出现了非常多报错。 这非常可疑&#xff0c;报错指向的域名也证实了这一点。 因为我的 HTML 中只有一个外部开源库&#xff08;qrcode.min.js&#xff09;&#xff0c;因此只有可能是它出现了问题。 我翻看了请求记录&#xff0c;发现这…

【无线感知】【P3】无线感知手势识别-Ubicomp2022论文分享

前言&#xff1a; 本篇主要关于手势识别的方向的,主要参考 北京大学-《无线感知手势识别-Ubicomp2022论文分享》 目录&#xff1a; 技术背景 主要问题&#xff08;异质性问题&#xff09; 感知模型 EDP DPSense 实现效果 一 技术背景 基于WIFI的手势识别在智能家具,以…

ShardingSphere-proxy添加自定义分片规则(踩坑日记)

文章目录 一、新建spring boot项目二、编写代码(1) 新建一个类(2) doSharding方法详解(3) 实际例子 三、增加spi文件&#xff08;很关键&#xff09;四、打包五、把生成的文件放到ext-lib中六、yaml配置&#xff08;怎么用&#xff09;七、测试 版本环境 mysql 5.7.40 sharding…

湘潭大学信息与网络安全复习笔记2(总览)

前面的实验和作业反正已经结束了&#xff0c;现在就是集中火力把剩下的内容复习一遍&#xff0c;这一篇博客的内容主要是参考教学大纲和教学日历 文章目录 教学日历教学大纲 教学日历 总共 12 次课&#xff0c;第一次课是概述&#xff0c;第二次和第三次课是密码学基础&#x…

[渗透测试学习] Runner-HackTheBox

Runner-HackTheBox 信息搜集 nmap扫描端口 nmap -sV -v 10.10.11.13扫描结果如下 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0) 80/tcp open http nginx 1.18.0 (Ubuntu) 8000…

中小制造业工厂要不要上MES系统

MES系统的主要功能包括制造数据管理、计划排产管理、生产调度管理、库存管理、质量管理、人力资源管理、工作中心/设备管理、工具工装管理、采购管理、成本管理、项目看板管理、生产过程控制、底层数据集成分析、上层数据集成分解等。通过这些模块&#xff0c;MES为企业打造一个…

基于springboot实现农产品直卖平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现农产品直卖平台系统的设计演示 摘要 计算机网络发展到现在已经好几十年了&#xff0c;在理论上面已经有了很丰富的基础&#xff0c;并且在现实生活中也到处都在使用&#xff0c;可以说&#xff0c;经过几十年的发展&#xff0c;互联网技术已经把地域信息的隔…

快速构建本地RAG聊天机器人:使用LangFlow和Ollama实现无代码开发

基于LangChain的快速RAG应用原型制作方法 还记得构建智能聊天机器人需要数月编码的日子吗&#xff1f; LangChain这样的框架确实简化了开发流程&#xff0c;但对非程序员来说&#xff0c;数百行代码仍然是一道门槛。 有没有更简单的方法呢&#xff1f; 图片由 Ravi Palwe 在…

适用于 macOS 的最佳免费数据恢复软件

升级到 macOS 后&#xff0c;它可以帮助您从 HDD、SSD、存储卡、USB 闪存驱动器、数码相机或其他存储介质设备中完全恢复已删除、格式化或无法访问的数据。 当 macOS Monterey 用户寻找数据恢复解决方案时&#xff0c;免费数据恢复软件始终是一个不错的选择。实际上&#xff0…

Linux基础命令[29]-chown

文章目录 1. chown 命令说明2. chown 命令语法3. chown 命令示例3.1 修改属主3.2 修改属组3.3 修改属主和属组3.4 修改文件夹所属 4. 总结 1. chown 命令说明 chown&#xff1a;更改文件的用户或用户组&#xff0c;需要 root 用户或 sudo 权限的用户执行该命令。基本信息如下&…