Linux学习笔记7-IIC的应用

接下来进入其他两种串行通信方式:SPII2C的学习,因为以后的项目中会用到这些通信方式,而且正点原子的开发板里面也有用I2C和SPI通信的传感器来做实例,分别是一个距离传感器和六轴陀螺仪,这样就可以很好的通过实例来学习了。这两个通信方式最大的区别就是速度,I2C的最高通信速度是400KHz,而SPI最高可以到几百MHz,所以在低速应用时I2C即可,到了高速的场合就必须用SPI了。
先学习I2C的应用,这里还是和以前一样,重点放在应用上,然后研究距离传感器的datasheet来尝试编写传感芯片的驱动!
I.MX6UL有4路I2C,正点原子写的I2C驱动包含了一系列的函数,这些函数其实就是对I2C相关的寄存器做一些置1或者0的操作,所以我们可以学习下常用的对寄存器按位逻辑操作的方法:

  1. 使某一位置0,其他位不变
base->I2CR &= ~(1 << 7);  //第7位置0,使用按位与
base->I2CR &= ~((1 << 5) | (1 << 4) | (1 << 3));   //[5:3]位同时清零
  1. 使某一位置1,其他位不变
base->I2CR |= ( 1 << 7);  //第7位置1,按位或
base->I2CR |=  (1 << 4) | (1 << 2);  //同时把第4位和第1位置1
  1. 检测某一位是否为0或者1
if(base->I2SR & (1 << 5)) == 1  //即I2SR的第五位是否为1,如果为1则逻辑与的结果是1
if((base->I2CR) & (1 << 5)) == 0)  即I2SR的第五位是否为0

这里不会深入研究正点原子的I2C驱动,只需要知道如何调用函数进行I2C数据的读写即可,把重点放在开发板上的传感器芯片AP3216C上。研究它的datasheet先。

The AP3216C is an integrated ALS & PS module that includes a digital ambient light sensor [ALS], a proximity sensor [PS], and an IR LED in a single package.
所以它包含了3个模块,光传感器ALS、距离传感器PS和红外线LEDIR,最常用在手机和平板上用来检测耳朵是否接触听筒,或者光传感器来检测光照强度调节屏幕亮度。

在datasheet里查到这个芯片的地址是0x1E,再研究datasheet第12页的表格,传感器的设置、数据读取和写入都是从不同的寄存器地址,所以我们先用一些宏来把寄存器地址在头文件中定义好,方便后面调用。宏的名字一定要一眼就看出意思来

#define AP3216C_ADDR    	0X1E	/* AP3216C器件地址 */#define AP3216C_SYSTEMCONG	0x00	/* 配置寄存器 			*/
#define AP3216C_INTSTATUS	0X01	/* 中断状态寄存器 		*/
#define AP3216C_INTCLEAR	0X02	/* 中断清除寄存器 		*/
#define AP3216C_IRDATALOW	0x0A	/* IR数据低字节 */
#define AP3216C_IRDATAHIGH	0x0B	/* IR数据高字节 		*/
#define AP3216C_ALSDATALOW	0x0C	/* ALS数据低字节 		*/
#define AP3216C_ALSDATAHIGH	0X0D	/* ALS数据高字节			*/
#define AP3216C_PSDATALOW	0X0E	/* PS数据低字节 			*/
#define AP3216C_PSDATAHIGH	0X0F	/* PS数据高字节 			*/

先编写读写数据的函数ap3216c_write(...),其实就是配置i2c_transfer结构体的各个参数,这个函数的参数是设备地址、要写入的寄存器、写入的数据,返回值可以扩展,可以是0-4,对应未写入(0),I2C14写入(返回值14)

unsigned char ap3216c_write(unsigned char addr, unsigned char reg, unsigned char data)  
{unsigned char status = 0;   unsigned char writedata = data;struct i2c_transfer masterXfer;  			/* 定义masterXfer结构体并配置 */masterXfer.slaveAddress = addr; 			/* 设备地址 */masterXfer.direction = kI2C_Write;			/* 方向为写入 */masterXfer.subaddress = reg;				/* 要写入的寄存器地址 */masterXfer.subaddressSize = 1;				/* 地址长度一个字节  */masterXfer.data = &writedata;				/* 要写入的数据 */masterXfer.dataSize = 1;  					/* 写入数据长度1个字节 */if(i2c_master_transfer(I2C1, &masterXfer))status=1;return status;}

同样的可以编写读函数ap3216c_read(...),参数是设备地址、要读的寄存器、返回值就是读取的数据。

unsigned char ap3216c_read(unsigned char addr,unsigned char reg)
{unsigned char val=0;struct i2c_transfer masterXfer;	masterXfer.slaveAddress = addr;				/* 设备地址 */masterXfer.direction = kI2C_Read;			/* 读取数据 */masterXfer.subaddress = reg;				/* 要读取的寄存器地址 */masterXfer.subaddressSize = 1;				/* 地址长度一个字节	*/masterXfer.data = &val;						/* 接收数据缓冲区 */masterXfer.dataSize = 1;					/* 读取数据长度1个字节 */i2c_master_transfer(I2C1, &masterXfer);return val;
}

根据读写的基础函数,我们可以编写读写IRPSALS几个模块数据的函数ap3216c_readdata(...)

void ap3216c_readdata(unsigned short *ir, unsigned short *ps, unsigned short *als)
{unsigned char buf[6];unsigned char i;/* 循环读取所有传感器数据 */for(i = 0; i < 6; i++)	{buf[i] = ap3216c_read(AP3216C_ADDR, AP3216C_IRDATALOW + i);	 /* 从0X0A到0X0F */}if(buf[0] & 0X80) 	/* IR_OF位为1,则数据无效 */*ir = 0;					else 				/* 读取IR传感器的数据  */*ir = ((unsigned short)buf[1] << 2) | (buf[0] & 0X03); 	/* 只保留buf[0]即IR低字节,并把高字节左移两位,获取IR完整数据 */		*als = ((unsigned short)buf[3] << 8) | buf[2];	/* 读取ALS传感器的数据 	*/  if(buf[4] & 0x40)	/* IR_OF位为1,则数据无效 */*ps = 0;    													else 				/* 读取PS传感器的数据  */*ps = ((unsigned short)(buf[5] & 0X3F) << 4) | (buf[4] & 0X0F); 	
}

至此AP3216C这个芯片的驱动就基本完成了。开发板的硬件上是通过I.MX6UL的I2C1通道和传感器连接,所以一开始需要初始化I2C1,这里就不赘述。
在main.c里的while(1)循环中读取这3个模块的数据并通过串口打印出来:

while(1)
{ap3216c_readdata(&ir, &ps, &als);printf("\r\n Data of IR, PS, ALS is: %d, %d, %d\r\n\r\n", ir, ps, als);delayms(200);
}

Makefile后烧写,在测试时用手去靠近开发板上的芯片,观察输出结果,也可以用光照,看看输出结果是否和预想一致。
在这里插入图片描述

I2C的学习到此结束,接下去进入SPI外设的学习。
未完待续

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

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

相关文章

Java中异常处理顺序和全局异常处理器

异常处理顺序 我们直接通过代码看下Java中异常的处理顺序。 数组越界异常属于运行时异常&#xff0c;被捕捉后就停止了&#xff0c;打印结果为数组越界了。 Test public void test2(){int[] arr new int[4];try{System.out.println(arr[5]);}catch (ArrayIndexOutOfBoundsE…

Python练习题(四)

本文主要是【Python】——Python练习题的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一句&#xff1a;狠狠沉淀&a…

解密Prompt系列20. LLM Agent之再谈RAG的召回多样性优化

几个月前我们就聊过RAG的经典方案解密Prompt系列14. LLM Agent之搜索应用设计。前几天刚看完openAI在DevDay闭门会议上介绍的RAG相关的经验&#xff0c;有些新的感悟&#xff0c;借此机会再梳理下RAG相关的优化方案。推荐直接看原视频&#xff08;外网&#xff09;A Survey of …

Django 模板引擎 (四)

一、Django模板引擎 一个强大的工具&#xff0c;用于在HTML页面中嵌入动态内容。它使用一种被称为Django模板语言&#xff08;Django Template Language&#xff09;的简单而强大的语法来处理模板。该模板语言使用”{% %}”进行标记&#xff0c;用于执行各种操作。 二、Django…

Linux驱动开发学习笔记3《新字符设备驱动实验》

目录 一、新字符设备驱动原理 1.分配和释放设备号 2.新的字符设备注册方法 &#xff08;1&#xff09; 字符设备结构 &#xff08;2&#xff09;cdev_init函数 &#xff08;3&#xff09; cdev_add函数 &#xff08;4&#xff09;cdev_del 函数 二、自动创建设备节点 …

4382系列数字荧光示波器

4382系列数字荧光示波器 简述&#xff1a; 4382系列手持式数字荧光示波器具有8个产品型号&#xff0c;带宽200MHz、350MHz、500MHz、1GHz&#xff0c;最高采样率5GSa/s&#xff0c;最大存储深度60kpts/CH&#xff0c;最快波形捕获率10万个波形/秒&#xff0c;独创的Any Acquire…

【每日OJ —— 101. 对称二叉树】

每日OJ —— 101. 对称二叉树 1.题目&#xff1a;101. 对称二叉树2.解法2.1.算法讲解2.2.代码实现2.3.提交通过展示 1.题目&#xff1a;101. 对称二叉树 2.解法 2.1.算法讲解 1.该题是判断二叉树是否对称&#xff0c;关键在于&#xff0c;左子树等于右子树&#xff0c;而所给的…

YOLOv8独家原创改进:创新自研CPMS注意力,多尺度通道注意力具+多尺度深度可分离卷积空间注意力,全面升级CBAM

💡💡💡本文自研创新改进:自研CPMS, 多尺度通道注意力具+多尺度深度可分离卷积空间注意力,全面升级CBAM 1)作为注意力CPMS使用; 推荐指数:五星 CPMS | 亲测在多个数据集能够实现涨点,对标CBAM。 收录 YOLOv8原创自研 https://blog.csdn.net/m0_63774211/ca…

代码随想录第二十三天(一刷C语言)|组合总数组合总数II分割回文串

创作目的&#xff1a;为了方便自己后续复习重点&#xff0c;以及养成写博客的习惯。 一、组合总数 思路&#xff1a;参考carl文档 定义两个全局变量&#xff0c;二维数组result存放结果集&#xff0c;数组path存放符合条件的结果。&#xff08;这两个变量可以作为函数参数传入…

观海微电子---AF、AG、AR 的差别和作用

一、名称解释及原理 1.AF ---- Anti-fingerprint&#xff0c;中文为抗指纹。一般 SiO2AF 材料&#xff08;DON&#xff0c;M4、道康宁 AF 材料&#xff09;&#xff0c;一般采用真空蒸发镀膜法。 原理&#xff1a;AF 防污防指纹玻璃是根据荷叶原理&#xff0c;在玻璃外表面涂制…

无需公网IP!Apache服务器本地部署与内网穿透实现公网访问

Apache服务安装配置与结合内网穿透实现公网访问 文章目录 Apache服务安装配置与结合内网穿透实现公网访问前言1.Apache服务安装配置1.1 进入官网下载安装包1.2 Apache服务配置 2.安装cpolar内网穿透2.1 注册cpolar账号2.2 下载cpolar客户端 3. 获取远程桌面公网地址3.1 登录cpo…

理解 Python 的 for 循环

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 在本篇博客中&#xff0c;我们将讨论 Python 中 for 循环的原理。 我们将从一组基本例子和它的语法开始&#xff0c;还将讨论与 for 循环关联的 else 代码块的用…