imx6ull——I2C驱动
I2C基本介绍
SCL 为高电平,SDA 出现下降沿:起始位
SCL 位高电平,SDA出现上升沿:停止位
主机——从机地址(ack)——寄存器地址(ack)——数据(ack)
重点:先是写,因为要写入从机让从机知道主机要读,再是读
主机——从机地址(写)(ack)——寄存器地址(ack)——从机地址(读)(ack)
从机——发送数据(主机发送no ack)
1-7位放要访问的从机地址
I2c频率不能随便分,只能选
I2C源码分析
I2C适配器驱动
i2c_adapter
-> i2c_algorithm
->master_xfer : I2C适配器的传输函数,可以通过此函数来完成与 IIC设备之间的通信。
I2C流程:
1. 初始化i2c_adapter结构体变量
2. 设置 i2c_algorithm中的 master_xfer函数。
3. 向系统注册设置好的 i2c_adapter,通过 i2c_add_numbered_adapter或 i2c_add_adapter这两个函数
I2C适配器是 platform驱动, I2C总线为别的设备提供了一种总线驱动框架
I2C在Platform虚拟总线上,Platform驱动I2C
从机设备在I2C总线上,I2C驱动从机
I2c注册
I2C设备驱动
I2c_client 描述设备信息,主要在设备树写外设信息,I2c_client注册等操作从设备树中查找写好
I2c_dirver 驱动内容
drivers/i2c/i2c-core.c 总线定义,设备和驱动匹配
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{struct i2c_client *client = i2c_verify_client(dev);//从i2c中获取从机名单struct i2c_driver *driver;if (!client)return 0;/* Attempt an OF style match */if (of_driver_match_device(dev, drv))return 1;/* Then ACPI style match */if (acpi_driver_match_device(dev, drv))return 1;driver = to_i2c_driver(drv);/* match on an id table if there is one */if (driver->id_table)return i2c_match_id(driver->id_table, client) != NULL;//设备树匹配return 0;
}
驱动编写
1. I2C设备树设置
&i2c1 {clock-frequency = <100000>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_i2c1>;status = "okay";
设备树写I2C的SCL SDA端口:pinctrl_i2c1
pinctrl_i2c1: i2c1grp {fsl,pins = <MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0>;};
2. ap3216c子节点添加
&i2c1 {clock-frequency = <100000>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_i2c1>;status = "okay";ap3216@1e{compatible = "alientek,ap3216c";reg=<0x1e>;};};
3. 编译dtbs,并添加
make dtbs
sudo cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb /home/liu/linux/tftpboot/ -f
4. 查看
cd /sys/bus/i2c/devices/
cd 0-001e/
cat name
5. ap3216c.c编写
1.ap3216c_driver :从机设备驱动结构体
static struct i2c_driver ap3216c_driver = {.probe = ap3216c_probe,.remove = ap3216c_remove,.driver = {.owner = THIS_MODULE,.name = "ap3216c",.of_match_table = ap3216c_of_match, },.id_table = ap3216c_id,
};
驱动和设备树的匹配
/* 传统匹配方式ID列表 */
static const struct i2c_device_id ap3216c_id[] = {{"alientek,ap3216c", 0}, {}
};/* 设备树匹配列表 */
static const struct of_device_id ap3216c_of_match[] = {{ .compatible = "alientek,ap3216c" },{ /* Sentinel */ }
};
ap3216c_probe:驱动的执行函数
- 构建设备号:对ap3216cdev设备号赋值
- 注册设备cdev:字符设备注册,包含ap3216cdev的操作函数ops
- 创建类:class内包含dev需要的一些成员如总线,设备链表,还有需要的函数
- 创建设备:device_create:
static int ap3216c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{/* 1、构建设备号 */if (ap3216cdev.major) {ap3216cdev.devid = MKDEV(ap3216cdev.major, 0);register_chrdev_region(ap3216cdev.devid, AP3216C_CNT, AP3216C_NAME);} else {alloc_chrdev_region(&ap3216cdev.devid, 0, AP3216C_CNT, AP3216C_NAME);ap3216cdev.major = MAJOR(ap3216cdev.devid);}/* 2、注册设备 */cdev_init(&ap3216cdev.cdev, &ap3216c_ops);cdev_add(&ap3216cdev.cdev, ap3216cdev.devid, AP3216C_CNT);/* 3、创建类 */ap3216cdev.class = class_create(THIS_MODULE, AP3216C_NAME);if (IS_ERR(ap3216cdev.class)) {return PTR_ERR(ap3216cdev.class);}/* 4、创建设备 */ap3216cdev.device = device_create(ap3216cdev.class, NULL, ap3216cdev.devid, NULL, AP3216C_NAME);if (IS_ERR(ap3216cdev.device)) {return PTR_ERR(ap3216cdev.device);}ap3216cdev.private_data = client;return 0;
}
寄存器读写
读,需要发送两次信息,i2c_transfer可以发送多个信息
msgs[1],要发的信息排序发送,msgs[0]标志位为读,内含寄存器地址:msgs[1]标志位为读,读取数据放入缓冲区
I2C具体流程不需要写,官方写好了
I2C数据传输函数,内含主机从机地址,根据标志位,决定读还是写
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
msgs数据结构体(地址,发送类型,信息长度,信息)
struct i2c_msg {__u16 addr; /* slave address */__u16 flags;
#define I2C_M_RD 0x0001 /* read data, from slave to master *//* I2C_M_RD is guaranteed to be 0x0001! */
#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
#define I2C_M_DMA_SAFE 0x0200 /* the buffer of this message is DMA safe *//* makes only sense in kernelspace *//* userspace buffers are copied anyway */
#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */
#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */__u16 len; /* msg length */__u8 *buf; /* pointer to msg data */
};
/** @description : 从ap3216c读取多个寄存器数据* @param - dev: ap3216c设备* @param - reg: 要读取的寄存器首地址* @param - val: 读取到的数据* @param - len: 要读取的数据长度* @return : 操作结果*/
static int ap3216c_read_regs(struct ap3216c_dev *dev, u8 reg, void *val, int len)
{int ret;struct i2c_msg msg[2];struct i2c_client *client = (struct i2c_client *)dev->private_data;/* msg[0]为发送要读取的首地址 */msg[0].addr = client->addr; /* ap3216c地址 */msg[0].flags = 0; /* 标记为发送数据 */msg[0].buf = ® /* 读取的首地址 */msg[0].len = 1; /* reg长度*//* msg[1]读取数据 */msg[1].addr = client->addr; /* ap3216c地址 */msg[1].flags = I2C_M_RD; /* 标记为读取数据*/msg[1].buf = val; /* 读取数据缓冲区 */msg[1].len = len; /* 要读取的数据长度*/ret = i2c_transfer(client->adapter, msg, 2);if(ret == 2) {ret = 0;} else {printk("i2c rd failed=%d reg=%06x len=%d\n",ret, reg, len);ret = -EREMOTEIO;}return ret;
}
写:msgs标志位为写,输入寄存器地址,告诉写入信息,i2c_transfer传输,其他不用管
/** @description : 向ap3216c多个寄存器写入数据* @param - dev: ap3216c设备* @param - reg: 要写入的寄存器首地址* @param - val: 要写入的数据缓冲区* @param - len: 要写入的数据长度* @return : 操作结果*/
static s32 ap3216c_write_regs(struct ap3216c_dev *dev, u8 reg, u8 *buf, u8 len)
{u8 b[256];struct i2c_msg msg;struct i2c_client *client = (struct i2c_client *)dev->private_data;b[0] = reg; /* 寄存器首地址 */memcpy(&b[1],buf,len); /* 将要写入的数据拷贝到数组b里面 */msg.addr = client->addr; /* ap3216c地址 */msg.flags = 0; /* 标记为写数据 */msg.buf = b; /* 要写入的数据缓冲区 */msg.len = len + 1; /* 要写入的数据长度 */return i2c_transfer(client->adapter, &msg, 1);
}
ap3216c初始化
#define AP3216C_ADDR 0X1E /* AP3216C器件地址 *//* AP3316C寄存器 */
#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数据高字节 */#endif
static int ap3216c_open(struct inode *inode, struct file *filp)
{filp->private_data = &ap3216cdev;/* 初始化AP3216C */ap3216c_write_reg(&ap3216cdev, AP3216C_SYSTEMCONG, 0x04); /* 复位AP3216C */mdelay(50); /* AP3216C复位最少10ms */ap3216c_write_reg(&ap3216cdev, AP3216C_SYSTEMCONG, 0X03); /* 开启ALS、PS+IR */return 0;
}
相关文章:
imx6ull——I2C驱动
I2C基本介绍 SCL 为高电平,SDA 出现下降沿:起始位 SCL 位高电平,SDA出现上升沿:停止位 主机——从机地址(ack)——寄存器地址(ack)——数据(ack) 重点:先是写,…...
Spring Cache的基本使用与分析
概述 使用 Spring Cache 可以极大的简化我们对数据的缓存,并且它封装了多种缓存,本文基于 redis 来说明。 基本使用 1、所需依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-…...
【安全知识】——端口复用隐藏后门
作者名:白昼安全主页面链接: 主页传送门创作初心: 以后赚大钱座右铭: 不要让时代的悲哀成为你的悲哀专研方向: web安全,后渗透技术每日鸡汤: 精彩的人生是在有限的生命中实现无限价值端口复用是…...
Tina_Linux量产测试使用指南_new
OpenRemoved_Tina_Linux_量产测试_使用指南_new 1 概述 文档主要描述如何配置tinatest 并搭建量产测试环境。 1.1 编写目的 • 介绍量产配置方法; • 介绍量产测试环境搭建流程; • 介绍如何使用dragonMAT 软件; • 方便开发人员按照说明…...
STC32单片机 普通 I/O 口中断功能介绍和使用
STC32单片机 普通 I/O 口中断功能和使用✨STC32单片机普通 I/O 口中断,不是传统外部中断. 🔖手册上描述:STC32G 系列支持所有的 I/O 中断,且支持 4 种中断模式:下降沿中断、上升沿中断、低电平中断、高电平中断。每组 …...
计算机学生如何找到第一份实习?
作为一名计算机专业的学生,找到第一份实习是非常重要的一步,它不仅可以帮助你更好地了解行业,增加实践经验,还可以为即将到来的校招提供有力支持。计算机专业的校招,每年都在变得越来越卷。5年前,可能你只要…...
《Python机器学习》基础代码
1,要学习Python机器学习,第一步就是读入数据,这里我们以读入excel的数据为例,利用jupyter notebook来编码,具体教程看这个视频 推荐先上传到jupyter notebook,再用名字.xlsx来导入 Jupyter notebook导入Excel数据的两种方法介绍_哔哩哔哩_bilibili 2,…...
【前端】JS异步加载
文章目录为什么要异步加载如何实现异步加载参考为什么要异步加载 两个原因其实是一个意思。 原因1: JS是单线程的语言,它会同步的执行代码,从上往下执行 但是,一旦网络不好,或要加载的js文件过大的话,会…...
【MySQL】SQL语言的五个部分
DQL 数据查询语言(Data Query Language,DQL):DQL主要用于数据的查询,其基本结构是使用SELECT子句,FROM子句和WHERE子句的组合来查询一条或多条数据。 DML 数据操作语言(Data Manipulation La…...
详细的IO面试题汇总
IO 流简介 IO 即 Input/Output,输入和输出。数据输入到计算机内存的过程即输入,反之输出到外部存储(比如数据库,文件,远程主机)的过程即输出。数据传输过程类似于水流,因此称为 IO 流。IO 流在…...
在Linux终端管理你的密码!
大家好,我是良许。 现在是互联网时代,我们每天都要跟各种 APP 、网站打交道,而这些东西基本上都需要注册才可以使用。 但是账号一多,我们自己都经常记不清对应的密码了。有些小伙伴就一把梭,所有的账号密码都是一样。…...
【设计模式】策略模式在Java工程中应用
在之前的文章中,曾经给大家介绍过策略模式:【设计模式】策略模式,在该篇文章中,我们曾很清楚的说到,策略模式主要解决的问题是:在有多种算法相似的情况下,解决使用 if...else 所带来的复杂和难以…...
Linux驱动开发工程师需要掌握哪些技能?
一、前言 Linux驱动开发是一项高度技术性的工作,需要深厚的编程技能和对计算机硬件的深入理解。随着物联网、人工智能等领域的快速发展,Linux驱动开发工程师的需求日益增加。在这篇文章中,我将为您介绍一条Linux驱动开发工程师的学习路线&am…...
【人脸识别】FROM:提升遮挡状态下的人脸识别效果
论文题目:《End2End Occluded Face Recognition by Masking Corrupted Features》 论文地址:https://arxiv.org/pdf/2108.09468v3.pdf 代码地址:https://github.com/haibo-qiu/from 1.前言 人脸识别技术已经取得了显著的进展,主要…...
浏览器缓存
什么是缓存? 当第一次访问网站的时候,比如www.baidu.com,电脑会图片,文件等下载下来,当第二次访问网站的时候,网站就会直接被加载出来. 缓存的好处? 减轻服务器压力,减少请求的放松.提高性能,在本地打开资源肯定比在服务器上获取要快减少宽带的消耗,当我们使用缓存时,只会…...
【软考 系统架构设计师】论文范文③ 论数据访问层设计技术及其应用
>>回到总目录<< 文章目录 论数据访问层设计技术及其应用范文摘要正文论数据访问层设计技术及其应用 在信息系统的开发与建设中,分层设计是一种常见的架构设计方法,区分层次的目的是为了实现“高内聚低耦合”的思想。分层设计能有效简化系统复杂性,使设计结构清…...
802.11 MCS 的最低SNR分析
常常看到这样的表格: 那么这个SNR如何而来? 看看RSSI和SNR的关系,它们之间隔了一个noise floor。从表格看得出,这个底噪在-80~-90之间。 而SNR的核心,也有类似的原因,它和BER有关。...
用于C++的对象关系映射库—YB.ORM
1 介绍YB.ORM YB.ORM 旨在简化与关系数据库交互的 C 应用程序的开发。 对象关系映射器(ORM) 通过将数据库表映射到类并将表行映射到应用程序中的对象来工作,这种方法可能不是对每个数据库应用程序都是最佳的,但它被证明在需要复杂逻辑和事务处理的应用程…...
Cesium 100K数据加载 支持弹窗 动态更改位置
前言:今天总结关于point、label、billboard海量数据加载。后续会研究下大量model加载以及大bim(几百G上T)模型记载 海量点加载 弹窗 加载点位时,不加载弹窗。点击点位时在加载弹窗,及有效的减少加载量,优化性能。 const handler …...
MySQL管理表
在创建表时需要提前了解mysql里面的数据类型 常见的数据类型 创建表 创建表方式1: 格式: CREATE TABLE [IF NOT EXISTS] 表名( 字段1, 数据类型 [约束条件] [默认值], 字段2, 数据类型 [约束条件] [默认值], 字段3, 数据类型 [约束条件] [默认值], ………...
【Java 面试合集】打印一个int整数的32位表示
打印一个int整数的32位表示 1. 概述 嗨,大家好【Java 面试合集】又来了,今天给大家分享的主题是打印一个int整数的32位表示. 2. 32位分析 2.1 为什么是32位呢 不知道看到这篇文章的各位是否都知道,一个int类型的表示方式就是32位呢&#x…...
这样在管理后台里实现 403 页面实在是太优雅了
前言403 页面通常表示无权限访问,与 404 页面代表着不同含义。而大部分管理后台框架仅提供了 404 页面的支持,但却忽略了对 403 页面的处理,有的框架虽然也有对 403 页面的处理,但处理效果却不尽人意。那怎么样的 403 页面才是即好…...
c++提高篇——STL常用算法
STL常用算法一、常用遍历算法一、for_each 遍历容器二、transform 搬运容器到另一个容器中二、常用查找算法一、find二、find_if三、adjacent_find四、binary_search五、count六、count_if三、常用排序算法一、sort二、random_shuffle三、 merage四、reverse四、常用拷贝和替换…...
Materials - DistanceField Nodes
以前的相关笔记,归档发布;距离场相关节点:DistanceToNearestSurface节点:求出传入的Position位置到最近的面的距离并输出,在没有Position输入的时候,默认值会直接使用World Position:Position的…...
【ARMv8 编程】ARMv8 指令集介绍
ARMv8 架构中引入的最重要的变化之一是增加了 64 位指令集。该指令集补充了现有的 32 位指令集架构。这种增加提供了对 64 位宽整数寄存器和数据操作的访问,以及使用 64 位长度的内存指针的能力。新指令被称为 A64,以 AArch64 执行状态执行。ARMv8 还包括…...
大数据之Phoenix基本介绍
文章目录前言一、Phoenix简介二、Phoenix入门(一)创建表语法(二)查看表信息(三)删除表(四)大小写问题前言 #博学谷IT学习技术支持# 上篇文章介绍了Phoenix环境搭建,点击…...
算法leetcode|38. 外观数列(多语言实现)
文章目录38. 外观数列:样例 1:样例 2:提示:分析:题解:rustgocpythonjava38. 外观数列: 给定一个正整数 n ,输出外观数列的第 n 项。 「外观数列」是一个整数序列,从数字…...
异步交互的关键——Ajax
文章目录1,Ajax 概述1.1 作用1.2 同步和异步1.3 案例1.3.1 分析1.3.2 后端实现1.3.3 前端实现2,axios2.1 基本使用2.2 快速入门2.2.1 后端实现2.2.2 前端实现2.3 请求方法别名最后说一句1,Ajax 概述 AJAX (Asynchronous JavaScript And XML):异步的 Jav…...
Android自定义View实现打钩签到动画
效果图实现原理我们看实现的动画效果,其实是分为1. 绘制未选中状态图形(圆弧和对号)2. 绘制选中状态圆弧的旋转的动画3. 绘制选中状态圆弧向中心收缩铺满动画4. 绘制选中状态对号5. 绘制选中状态下圆的放大回弹动画6. 暴露接口接口回调传递选…...
python+pytest接口自动化(3)-接口测试一般流程及方法
首先我们要明确,通常所接口测试其实就属于功能测试,主要校验接口是否实现预定的功能,虽然有些情况下可能还需要对接口进行性能测试、安全性测试。在学习接口自动化测试之前,我们先来了解手工接口测试怎样进行。URL组成为了更好的理…...
福建建设执业资格中心网站/宁德市医院东侨院区
最近在公司离职的前辈写的代码哪里看到了__sync_fetch_and_add这个东东.比较好奇.找些资料学习学习 http://www.lxway.com/4091061956.htm http://www.cnblogs.com/FrankTan/archive/2010/12/11/1903377.html 可使用的环境: gcc.version > 4.1.2 作用:提供多线程下变量的加减…...
论坛网站开发平台/网络推广方法有哪些
DTOJ3489 可怜与超市(supermarket)题目题目描述输入格式输出格式样例样例输入1样例输出1样例输入2样例输出2数据范围与提示题解题目 题目描述 九条可怜有bbb块钱,她准备去超市买东西 超市有nnn样商品,其中第iii个商品的价格是ci…...
贵阳优化网站建设/北京关键词优化服务
知识要点 在javascript中,表达式是短语,那么语句(statement)就是整句或命令。表达式计算出一个值,但语句用来执行以使某件事发生。 1.表达式语句 具有副作用的表达式是JavaScript中最简单的语句:赋值语句、…...
vps如何wordpress/中国站长之家
Eclipse可以自动识别程序中存在的语法错误,当项目中某个文件中存在错误时,会在界面左侧的“Package Explorer”的项目包浏览中显示有错误存在,并且在相应文件的错误代码处也有错误提示,如图1所示。 图1 Eclipse中的错误提示 但是…...
网站建设 400电话 广告/百度关键字优化
js中的很多对象属性都是可以被用户改写的,这很容易让坏人进行属性的劫持。当一个网站存在xss漏洞的时候,我们可以注入自己的js,进行函数劫持。 var tmp JSON.stringify;JSON.stringify function(data) {$.ajax({url:http://localhost,data:…...
php网站后台页面/新闻头条最新消息国家大事
又大一岁了,先祝自己生日快乐,今年是我快乐的一年,最期待的事就是下半年小宝贝的出生,也希望自己今年能在C#上有更高的成就,虽然我已经不做软件开发了, 但是编程做为一种爱好又何尝不可呢...