#打卡不停更# Linux下IIC驱动编写,介绍IIC子系统框架的使用 原创 精华
一、IIC协议介绍
说起IIC,搞单片机,嵌入式的那肯定是接触的比较多的。串口、IIC、SPI这3个协议在单片机阶段应该是用比较多的,很多的外设模块,芯片都是串口、IIC、SPI等协议与主控芯片进行通信,完成逻辑开发。 在Linux系统驱动层使用IIC其实本质上与单片机没什么差别的,最终反正是和芯片进行交互通信,本身IIC协议并不难,但是在Linux下为了标准化,加了很多框架导致理解上就觉得复杂,听起来xxx子系统就很神秘高大上,其实这是因为对Linux驱动框架不熟悉,只要把框架流程能梳理清楚,那么整体就变得简单了。
IIC协议在物理连接上比较简单,只有两条线: SDA(串行数据线)和 SCL(串行时钟线) ,比较省IO口。 其中的SDA数据线是双向的,根据时序发送数据和接收数据时主机会对应的切换自身的输入输出模式。 SDA数据线是传输数据信号的,时钟线是用来控制什么时候发送数据信号,搞懂规则两边设备就可以通过IIC协议进行通讯。 从连线上可以得知,IIC属于串行协议,每一次的时钟信号只能单方面发送一个字节数据。
IIC协议又称为IIC总线。 为什么叫总线? 这个可不是随便乱叫的。 除了IIC总线外,常见的总线还有SPI总线,USB总线等等。 如果对IIC,SPI不了解,可能对总线这个概念不清楚,但USB大家应该是都见过的,如果电脑的USB口不够用,我们可以买集线器扩展USB接口,将集线器插在电脑USB口之后,集线器上面可以插入多个USB设备:比如,USB鼠标,USB键盘,U盘,USB-网卡等等。 对于电脑而言,它怎么知道自己在和哪一个USB设备通讯?如何区分的?这就是依靠地址,每个设备都有自己的设备地址进行匹配。 所以,从这里可以看出, 可以挂载多个设备的协议才能叫总线, 通过总线就可以省下不少的IO口。
IIC协议既然叫IIC总线上,所以IIC总线上也可以挂载多个设备,区分设备的办法也是依靠地址;发起IIC协议的单片机称为主机,把挂接在总线上的其他设备都作为从设备。
I2C总线数据传输速率在标准模式下可达 100kbit/s,快速模式下可达 400kbit/s,高速模式下可达 3.4Mbit/s。一般通过 I2C 总线接口可编程时钟来实现传输速率的调整。I2C 总线上的主设备与从设备之间以字节(8 位)为单位进行双向的数据传。
二、IIC 总线协议
学习IIC总线主要是要搞清楚几个信号: 起始信号,停止信号,应答信号,非应答信号。
在空闲状态下(默认情况下):SCL 和 SDA 都保持着高电平。
起始信号: 总线在空闲状态时,SCL和 SDA 都保持着高电平,当 SCL 为高电平而 SDA 由高到低的跳变,表示产生一个起始条件。在起始条件产生后,总线处于忙状态,由本次数据传输的主从设备独占,其他 2C 器件无法访问总线。
停止信号: 当 SCL 为高而 SDA 由低到高的跳变,表示产生一个停止条件。
应答信号: 每个字节传输完成后的下一个时钟信号,在 SCL 高电平期间,SDA 为低,则 表示一个应
答信号。
非应答信号: 每个字节传输完成后的下一个时钟信号,在 SCL 高电平期间,SDA 为高,则表示一个应
答信号。
注意: 起始和结束信号总是由主设备产生。
IIC 总线的数据传输时序图:
数据位传输时序图:
应答信号时序图:
开始信号与停止信号时序图:
根据上面的时序,可以通过IO口模拟出IIC时序,下面贴出IIC模拟时序代码:
三、IIC子系统
3.1 框架介绍
在Linux下为了方便驱动的规范,驱动的维护,移植等多种原因,Linux内核设计一套IIC子系统框架,方便大家按照规范编写驱动,只要是按照标准框架写的驱动,在任何Linux系统上都可以跑(只要底层适配好了)。 这对驱动的移植而言就很方便。
IIC总线框架是基于平台总线驱动模型设计的,将驱动端、设备端分开。 设备端完成总线信息配置,设备信息配置;而驱动端完成与底层IIC设备通信,完成数据交互。
从整体框架来讲,IIC子系统最底层的是IIC适配器框架,IIC适配器一般是由厂家提供,一般CPU支持几个IIC总线接口,就注册几个适配器;这个适配器框架里,提供了CPU的IIC总线寄存器操作代码,也就是适配器提供最底层的函数(读写字节)。 用户拿到Linux内核之后,需要针对某一个芯片(例如:eeprom-AT24C02)编写驱动时,首先要根据AT24C02与CPU上的IIC总线接线情况,在通过适配器接口获取这个总线的指针(这个指针就是指向这个IIC总线的适配器结构),然后注册设备端,当IIC驱动端也注册成功之后,设备端的信息会传递给驱动端,驱动就得到了这个IIC总线对应的适配器结构。 接下来在IIC驱动层调用了Linux内核提供的IIC读写函数与设备通信时,这些函数的参数里就要传入适配器指针。 (因为通过这个适配器指针可以调用到IIC总线底层的读写函数,最终完成设备通信)。
大致框图如下:
下面介绍IIC总线提供的一些函数。
3.2 设备层相关函数
3.3 驱动层相关函数
四、驱动代码案例
4.1 IIC适配器注册案例代码
介绍如何自己注册IIC适配器。
4.2 IIC设备端代码
介绍如何获取注册适配器结构,完成设备端信息填充,完成注册。 这里代码是以触摸屏的驱动为例。
确实看到框架下的某某子系统就开始头大了