实例解析linux内核I2C体系结构(2)
Linux下I2C驱动介绍
1、I2C概述I2C是philips公司提供的外设总线,I2C有两条数据线,一条是串行数据线SDA、一条是时钟线SCL,使用SDA和SCL实现了数据的交换,便于布线。
I2C总线方便用在EEPROM、实时钟、小型LCD等与CPU外部的接口上。
2、Linux下的驱动思路Linux系统下编写I2c驱动主要有两种方法:一种是把I2C当做普通字符设备来使用;另一种利用Linux下驱动的体系结构来实现。
第一种方法:优点:思路比较直接,不用花费大量时间去了解Linux系统下I2C体系结构缺点:不仅对I2C设备操作要了解,还有了解I2C的适配器操作不仅对I2C设备器和设备操作需要了解,编写的驱动移植性差,内核提供的I2C设备器都没有用上。
第二种方法:第一种的优点就是第二种的缺点,第一种的缺点就是第二种的优点。
3、I2C框架概述Linux的I2C体系结构分为3部分:1)I2C核心I2C核心提供了I2C总线驱动和设备驱动的注册和注销的方法,I2C 通信方法(algorithm)上层,与具体适配器无关的代码,检测设备上层的代码等。
2)I2C总线驱动I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可以直接受CPU来控制。
3)I2C设备驱动I2C设备驱动是对I2C硬件体系结构中设备端的实现,设备端挂在受CPU控制的适配器上,通过I2C适配器与CPU交换数据。
Linux下的I2C体系结构:1)Linux下的I2C体系结构4、I2C设备驱动编写方法首先让我们明白适配器驱动的作用是让我们能够通过它发出标准的I2C时序,在linux内核源代码中driver/I2C/buss包含一些适配器的驱动,例如s3c2410的驱动I2C-s3c2410.c,适配器被加载到内核中,接下的任务就是实现设备驱动的编写。
编写设备驱动的方法主要分为两种方法:第一种:利用设备提供的I2C-dev.c来实现I2C适配器设备文件,然后通过上层应用程序来操作I2C设备器来控制I2C设备。
I2C详解——精选推荐
I2C详解1、基本概念主机初始化发送,产⽣时钟信号和终⽌发送的器件从机被主机寻址的器件发送器发送数据到总线的器件接收器从总线接收数据的器件多主机同时有多于⼀个主机尝试控制总线但不破坏报⽂仲裁是⼀个在有多个主机同时尝试控制总线,但只允许其中⼀个控制总线并使报⽂不被破坏的过程同步两个或多个器件同步时钟信号的过程2、硬件结构每⼀个I2C总线器件内部的SDA、SCL引脚电路结构都是⼀样的,引脚的输出驱动与输⼊缓冲连在⼀起。
其中输出为漏极开路的场效应管、输⼊缓冲为⼀只⾼输⼊阻抗的同相器。
这种电路具有两个特点:(1)由于SDA、SCL 为漏极开路结构,借助于外部的上拉电阻实现了信号的“线与”逻辑;(2)引脚在输出信号的同时还将引脚上的电平进⾏检测,检测是否与刚才输出⼀致。
为“时钟同步”和“总线仲裁”提供硬件基础。
3、时钟同步如果从机希望主机降低传送速度可以通过将SCL主动拉低延长其低电平时间的⽅法来通知主机,当主机在准备下⼀次传送发现SCL的电平被拉低时就进⾏等待,直⾄从机完成操作并释放SCL线的控制控制权。
这样以来,主机实际上受到从机的时钟同步控制。
可见SCL 线上的低电平是由时钟低电平最长的器件决定;⾼电平的时间由⾼电平时间最短的器件决定。
这就是时钟同步,它解决了I2C总线的速度同步问题。
4、主机发送数据流程(1)主机在检测到总线为“空闲状态”(即SDA、SCL 线均为⾼电平)时,发送⼀个启动信号“S”,开始⼀次通信的开始(2)主机接着发送⼀个命令字节。
该字节由7 位的外围器件地址和1 位读写控制位R/W 组成(此时R/W=0)(3)相对应的从机收到命令字节后向主机回馈应答信号ACK(ACK=0)(4)主机收到从机的应答信号后开始发送第⼀个字节的数据(5)从机收到数据后返回⼀个应答信号ACK(6)主机收到应答信号后再发送下⼀个数据字节(7)当主机发送最后⼀个数据字节并收到从机的ACK 后,通过向从机发送⼀个停⽌信号P结束本次通信并释放总线。
linux下iic(i2c)读写AT24C02
/jammy_lee/linux下iic(i2c)读写AT24C02linux驱动2010-02-09 16:02:03 阅读955 评论3 字号:大中小订阅linux内核上已有iic的驱动,因此只需要对该iic设备文件进行读写则能够控制外围的iic器件。
这里以AT24C02为对象,编写一个简单的读写应用程序。
iic设备文件在我的开发板上/dev/i2c/0 ,打开文件为可读写。
AT24C02的器件地址为0x50 ,既是iic总线上从器件的地址,每次只读写一字节数据。
/************************************************************///文件名:app_at24c02.c//功能:测试linux下iic读写at24c02程序//使用说明: (1)// (2)// (3)// (4)//作者:jammy-lee//日期:2010-02-08/************************************************************///包含头文件#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/select.h>#include <sys/time.h>#include <errno.h>//宏定义#define Address 0x50 //at24c02地址#define I2C_RETRIES 0x0701#define I2C_TIMEOUT 0x0702#define I2C_SLAVE 0x0703 //IIC从器件的地址设置#define I2C_BUS_MODE 0x0780typedef unsigned char uint8;uint8 rbuf[8] = {0x00}; //读出缓存uint8 wbuf[8] = {0x01,0x05,0x06,0x04,0x01,0x01,0x03,0x0d}; //写入缓存int fd = -1;//函数声明static uint8 AT24C02_Init(void);static uint8 i2c_write(int fd, uint8 reg, uint8 val);static uint8 i2c_read(int fd, uint8 reg, uint8 *val);static uint8 printarray(uint8 Array[], uint8 Num);//at24c02初始化static uint8 AT24C02_Init(void){fd = open("/dev/i2c/0", O_RDWR); //允许读写if(fd < 0){perror("Can't open /dev/nrf24l01 \n"); //打开iic设备文件失败exit(1);}printf("open /dev/i2c/0 success !\n"); //打开iic设备文件成功if(ioctl(fd, I2C_SLAVE, Address)<0) { //设置iic从器件地址printf("fail to set i2c device slave address!\n");close(fd);return -1;}printf("set slave address to 0x%x success!\n", Address);if(ioctl(fd, I2C_BUS_MODE, 1)<0) //设置iic总线模式printf("set bus mode fail!\n");elseprintf("set bus mode ok!\n");return(1);}/*uint8 AT24C02_Write(uint8 *nData, uint8 Reg, uint8 Num){write(fd, &Reg, 1); //usleep(100); //延时100uswrite(fd, nData, Num);usleep(1000*4); //延时4msreturn(1);}uint8 AT24C02_Read(uint8 nData[], uint8 Reg, uint8 Num) {write(fd, &Reg, 1);usleep(100); //延时100usread(fd, nData, Num);usleep(1000*4); //延时4msreturn(1);}*///at24c02写入一字节static uint8 i2c_write(int fd, uint8 reg, uint8 val){int retries;uint8 data[2];data[0] = reg;data[1] = val;for(retries=5; retries; retries--) {if(write(fd, data, 2)==2)return 0;usleep(1000*10);}return -1;}//at24c02读取一字节static uint8 i2c_read(int fd, uint8 reg, uint8 *val){int retries;for(retries=5; retries; retries--)if(write(fd, ®, 1)==1)if(read(fd, val, 1)==1)return 0;return -1;}//输出数组static uint8 printarray(uint8 Array[], uint8 Num) {uint8 i;for(i=0;i<Num;i++){printf("Data [%d] is %d \n", i ,Array[i]);}return(1);}//主函数int main(int argc, char *argv[]){int i;AT24C02_Init();usleep(1000*100);for(i=0; i<sizeof(rbuf); i++)if(i2c_read(fd, i, &rbuf[i]))break;printarray(rbuf ,8);printf("Before Write Data \n"); sleep(1);for(i=0; i<sizeof(rbuf); i++)if(i2c_write(fd, i, wbuf[i]))break;printarray(wbuf ,8);printf("Writing Data \n");sleep(1);for(i=0; i<sizeof(rbuf); i++)if(i2c_read(fd, i, &rbuf[i]))break;printarray(rbuf ,8);printf("After Write Data \n");close(fd);}。
I2C总线原理及应用实例
I2C总线原理及应用实例I2C总线是一种串行通信总线,全称为Inter-Integrated Circuit,是Philips(飞利浦)公司在1982年推出的一种通信协议。
它可以用于连接各种集成电路(Integrated Circuits,ICs),如处理器、传感器、存储器等。
I2C总线的原理是基于主从架构。
主设备(Master)负责生成时钟信号,并发送和接收数据,从设备(Slave)通过地址识别和响应主设备的命令。
I2C总线使用两根线来传输数据,一根是时钟线(SCL),用于主设备生成的时钟信号;另一根是数据线(SDA),用于双向传输数据。
1. 主设备发送起始位(Start)信号,将SDA线从高电平拉低;然后通过SCL线发送时钟信号,用于同步通信。
2.主设备发送从设备的地址,从设备通过地址识别确定是否响应。
3.主设备发送要传输的数据到从设备,从设备响应确认信号。
4. 主设备可以继续发送数据,或者发送停止位(Stop)信号结束通信。
停止位是将SDA线从低电平拉高。
1.温度监测器:I2C总线可以连接到温度传感器上,通过读取传感器的输出数据,进行温度的监测和控制。
主设备可以设置警报阈值,当温度超过阈值时,可以触发相应的措施。
2.显示屏:很多智能设备上的显示屏都采用了I2C总线,如液晶显示屏(LCD)或有机发光二极管(OLED)等。
主设备通过I2C总线发送要显示的信息,并控制显示效果,如亮度、对比度、清晰度等参数。
3.扩展存储器:I2C总线可以用于连接外部存储器,如电子存储器(EEPROM)。
通过I2C总线,可以读取和写入存储器中的数据,实现数据的存储和传输。
4.触摸屏控制器:许多触摸屏控制器也使用了I2C总线,主要用于将触摸信号传输给主设备,并接收主设备的命令。
通过I2C总线,可以实现对触摸屏的操作,如单击、滑动、缩放等。
5.电源管理器:一些电源管理器也采用了I2C总线,用于控制和监测电池电量、充电状态、电压、电流等参数。
i2c的基本工作原理
I2C(Inter-Integrated Circuit)是一种串行通信协议,用于在芯片之间进行数据传输。
它由飞利浦半导体(现在的恩智浦半导体)于1982年开发,并广泛应用于各种电子设备中。
I2C具有简单、高效和可靠的特点,成为众多芯片和模块之间常用的通信接口之一。
本文将详细介绍I2C的基本工作原理。
一、总线架构I2C采用了主从结构的总线架构,其中主设备(Master)负责发起数据传输请求,而从设备(Slave)则在接收到请求后进行响应。
一个I2C总线上可以连接多个从设备,每个从设备都有一个唯一的地址。
主设备通过发送起始信号(Start)来启动通信,然后选择要与之通信的从设备地址,最后发送停止信号(Stop)结束通信。
二、物理层I2C使用双线制进行数据传输,包括数据线(SDA)和时钟线(SCL)。
数据线上的信号是双向的,用于传输数据。
时钟线则由主设备控制,用于同步数据传输。
三、起始和停止信号I2C通信以起始信号(Start)和停止信号(Stop)来标识通信的开始和结束。
起始信号由主设备产生,它表示将要发起一次新的通信。
停止信号同样由主设备产生,表示一次通信的结束。
四、数据传输格式I2C采用了基于字节的数据传输格式。
每个字节都由8位二进制数据组成,包括7位数据位和1位数据方向位。
数据方向位为0表示发送数据,为1表示接收数据。
在每个字节的传输过程中,都会先发送数据方向位,然后再发送数据位。
五、时钟同步I2C使用时钟同步机制来确保通信的准确性。
时钟线由主设备产生,并控制整个数据传输过程的时序。
在每个时钟周期中,数据线上的数据必须稳定,并且只有在时钟线为低电平时才能改变。
六、地址传输在I2C通信中,每个从设备都有一个唯一的7位地址。
主设备通过发送地址来选择要与之通信的从设备。
地址由8个位组成,最高位是固定的0或1,用于表示读(1)或写(0)操作。
其余的7位用于指定从设备的地址。
七、数据传输流程I2C通信的数据传输流程如下:1. 主设备发送起始信号(Start)。
linux系统i2c协议详解
linux系统i2c协议详解I2C总线概述I2C(两线接口)是一种串行通信协议,用于连接嵌入式系统中的集成电路(IC)。
它以其低成本、低功耗和高可靠性著称。
I2C总线需要两条双向信号线:串行数据线(SDA)和串行时钟线(SCL)。
这些信号线由一个主设备控制,可以与多个从设备通信。
I2C通信I2C通信由以下步骤组成:起始条件:主设备将SDA线下拉至低电平,同时保持SCL线为高电平。
设备地址:主设备发送7位或10位从设备地址,后跟一个读/写位。
数据传输:主设备和从设备交换数据。
停止条件:主设备将SDA线拉至高电平,同时保持SCL线为高电平。
主设备和从设备I2C总线上的设备分为两种:主设备和从设备。
主设备:发起通信并控制总线。
通常是主微控制器或处理器。
从设备:响应主设备请求并提供或接收数据。
可以是传感器、执行器或其他外围设备。
I2C寻址从设备通过唯一的7位或10位地址进行寻址。
地址的最高位表示是否可读/写,0表示写,1表示读。
I2C模式I2C协议支持以下模式:主写从读:主设备向从设备写入数据,然后从从设备读取数据。
主读从写:主设备从从设备读取数据,然后向从设备写入数据。
从读从写:两个从设备在主设备的监督下进行通信。
I2C传输速率I2C传输速率通常在10kbps到400kbps之间。
速率由主设备设置。
I2C错误检测I2C协议包含几个错误检测机制,例如校验和和超时。
这些机制有助于确保数据的可靠传输。
I2C应用I2C总线用于各种应用,包括:传感器和执行器接口EEPROM和闪存编程LED和LCD控制模拟-数字转换器(ADC)和数字-模拟转换器(DAC)接口电源管理时钟同步I2C优点I2C协议的优点包括:低成本:无需额外的硬件接口低功耗:仅使用两根信号线高可靠性:错误检测机制确保数据完整性容易使用:简单的协议易于实施广泛采用:支持广泛的设备和库I2C缺点I2C协议的缺点包括:数据速率低:与其他串行接口相比,数据速率较低主机限制:总线上只能有一个主设备总线无仲裁:在总线冲突的情况下,没有内置的仲裁机制有限的寻址范围:仅支持有限数量的设备地址I2C技术演进I2C协议正在不断发展,以满足新应用的需求。
I2C通信原理及程序详细讲解
I2C通信原理及程序详细讲解I2C(Inter-Integrated Circuit)是一种串行通信协议,常用于连接微控制器、传感器和其他外部设备。
I2C通信协议由荷兰飞利浦公司于1982年开发,它使用两根信号线(SDA和SCL)进行数据传输。
I2C通信协议采用主从结构,一个主设备(如微控制器)可以连接多个从设备(如传感器)。
主从设备之间通过SDA和SCL线进行数据传输。
SDA线是双向数据线,用于传输数据,SCL线是时钟线,用于同步数据传输。
I2C通信协议中,设备的地址是一个重要概念。
每个设备都有一个唯一的地址,通过该地址可以选择和通信特定的设备。
地址由7个位组成,其中最高位是固定的,并取决于设备是主设备还是从设备。
如果最高位为0,则表示该设备是主设备;如果最高位为1,则表示该设备是从设备。
通过以下步骤,让我们详细了解如何在I2C总线上进行通信。
1.初始化I2C总线:在程序开始时,需要初始化I2C总线。
这通常包括初始化SDA和SCL引脚,设置时钟频率等。
具体的初始化步骤取决于使用的硬件和软件环境。
2.发送开始信号:开始信号表示I2C数据传输的开始。
它由主设备发送,并且SDA线从高电平转为低电平时发出。
发送开始信号后,SDA线上的数据将被解释为地址数据。
3.发送设备地址:主设备发送一个包含设备地址和读/写位(R/W)的数据字节。
设备地址是唯一的,并且由主设备选择。
读/写位指示从设备是要读取数据还是写入数据。
4.等待从设备响应:主设备发送设备地址后,会等待从设备的响应。
从设备将响应一个应答位(ACK)来确认地址接收成功。
如果收到ACK位,则继续进行下一步,否则可能是设备未连接或通信错误。
5.发送数据:主设备发送数据给从设备。
数据可以是命令、配置或实际数据,具体取决于应用场景。
发送数据的方式是将每个数据字节传输到SDA线上,并在每个数据字节后发送一个ACK位。
6.接收数据:从设备将数据发送给主设备。
数据可以是传感器读数、存储器数据等。
I2C工作原理
文化在交流中传播高考频度:★★★★☆难易程度:★★★☆☆被誉为中芬文明交流互鉴“架桥人”的赫尔辛基大学孔子学院,作为芬兰认识中国、中国与芬兰深化友谊和合作的重要窗口,在推动汉语在芬兰的发展方面取得了丰硕的成果,已成为芬兰最大的汉语教学、汉语水平考试及中国问题研究中心,孔子学院还在芬兰多所大学的五个语言中心设立了汉语教学点。
赫尔辛基大学孔子学院的创建①扩大了中华文化的国际影响力②表明了中华优秀传统文化是中华文明的重要标志③见证了中华优秀传统文化能够推动芬兰社会发展④为中华文化的传播和中芬文化的交流作出了贡献A.①② B.①④ C.②③ D.③④1.文化交流促进世界文化的发展文化传播的意义——既促进本民族文化的繁荣,又促进世界文化的发展。
2.做传播中外文化交流的友好使者我们既要更加热情地欢迎世界各地优秀文化在中国传播,又要更加主动地推动中华文化走向世界。
做中外文化交流的友好使者,是时代赋予我们的使命。
文化传播的途径和文化传播的手段1.秦国攻灭楚国后,为了加强对南方地区的控制,派50万官兵驻扎岭南地区。
这使得相当一部分中原人留在了粤东北地区,对当地文化产生了深远的影响。
秦统一中国后,为了戍边和开发新区,组织了一系列大规模的人口迁徙。
其中最著名的北戍五原、云中,南戍五岭,人数近百万,对长城沿线和华南的开发起了重要作用。
上述材料体现的文化传播途径是A.教育是文化传播的重要途径B.人口迁徙是文化传播的重要途径C.战争是文化传播的根本途径D.古代商贸活动是文化传播的重要途径2.中央电视台“一带一路”的特别报道《数说命运共同体》,通过讲述贸易、投资、中国制造、基础设旅、饮食文化、人员往来等方面的故事,呈现出“一带一路”沿线国家“命运共同体”图景。
该节目通过最新视频技术,使主持人“走出”演播室,在不同国家之间“穿越”,和观众一起认识“一带一路”沿线国家各方面的情况。
茶叶、丝绸伴随着中国口音旅行到了世界各地,而远方的特产来到中国的同时也把海外“乡音”带进了汉语词典,阿拉伯神话传说在中国家喻户晓,中国的电影海报也张贴在外国的电影院里……这表明A.大众传媒具有文化传递、沟通、感召的强大功能B.文化既是民族的,又是世界的C.大众传媒是古今文化传播的主要途径D.文化与经济相互交融,相互影响3.2017年,中国在德国举办贯穿全年、覆盖全德的系列文化庆祝活动。
i2c通信的详细讲解
i2c通信的详细讲解I2C(全称Inter-IntegratedCircuit)是一种基于两线式总线系统,可以利用它让一台机器和另一台机器或者一个器件与另一个器件之间建立通信连接。
它由一个多晶片系统(Multi-Chip System)所创造出来,可以减少实现多晶片系统的内部连接的数量,从而减少印制电路板的体积。
它允许多达127个从设备以最低物理开销(Low Physical Overhead)与一个主设备连接,具有低成本和高可靠性,现已成为很多类型的微控制器(Microcontroller)和处理器(Processors)的标准总线,应用非常广泛。
1. I2C概述I2C从最初的Philips经过20多年的发展,已经成为一种横跨多个行业的解决方案。
它可以在不同的系统上提供高性能片上系统(System-on-a-Chip,SoC)间的通信和协调,支持多达127的电子设备连接。
主要由两条信号线,称为SDA(Data Line)和SCL(Clock Line)构成,它们分别连接电子设备的数据和时钟,每个设备还有一个物理上的地址,用于标识彼此来进行通信。
I2C总线具有速度快、低功耗、简单易用等优点,现在已经被应用在系统和高速处理器、传感器、可编程逻辑器件(PLD)、多媒体设备、电源管理、液晶/LED等多个行业中。
2. I2C通信原理I2C通信可以说是一种异步通信方式,它是一种时钟控制的异步通信方式,发送一个字节,都要经过下面几个步骤:(1)发送起始条件:S(Start):该条件由SDA和SCL电平组合构成,SDA在SCL电平为高时从高电平变低电平。
(2)发送设备地址:在I2C总线上,设备都会有自己的地址,每个设备可以收发多个字节,这样就可以确定设备的身份。
(3)发送控制位:也称命令位,它用于确定主设备发送的是某种命令,比如写入数据,读取数据,还是其它的控制信息。
(4)发送数据:数据由SDA高低电平传输,而SDA电平的变化必须在SCL的上升沿才能有效。
I2C的原理与应用
I2C的原理与应用I2C(Inter-Integrated Circuit)是一种串行通信协议,由飞利浦公司于1980年代开发,用于在数字电子系统中连接各个芯片。
它主要使用两根线进行通信,即SDA(Serial Data Line,串行数据线)和SCL (Serial Clock Line,串行时钟线),同时支持多主机和多从机的通信方式。
I2C协议被广泛应用于各种数字设备的互连,包括传感器、存储器、协处理器等。
I2C的通信原理如下:1.总线结构:I2C总线包含一个主机和多个从机。
主机负责控制总线,并发起数据传输请求;从机等待主机发送命令,并根据命令执行相应操作。
2.时序:I2C总线上的通信需要依靠时钟信号进行同步。
主机通过时钟信号SCL驱动数据传输。
数据线SDA上的数据在时钟信号的上升沿或下降沿进行采样和发送。
3.起始和停止位置:数据传输始于主机发送一个起始信号,结束于主机发送一个停止信号。
起始信号通知所有从机总线上的数据传输即将开始;停止信号表示数据传输已经结束。
4.地址与数据传输:在起始信号之后,主机发送一个地址帧给从机。
地址帧的最高位表示读写操作,从机通过地址帧判断自身是否为数据传输的对象,并相应地进行操作。
主机可以在同一个传输过程中多次发送数据,并且可以从一个从机读取多个字节的数据。
I2C的应用广泛,以下是一些常见的应用领域:1.传感器:I2C通信协议在许多传感器和芯片中得到应用,例如加速度计、陀螺仪、温度传感器和压力传感器等。
这些传感器通过I2C协议与主处理器进行通信,并将采集到的数据传输到主处理器进行处理。
2. 存储器:I2C接口也广泛应用于存储器设备,如EEPROM (Electrically Erasable Programmable Read-Only Memory)和FRAM (Ferroelectric Random Access Memory)。
这些存储器设备可以通过I2C总线进行读写操作,从而存储和检索数据。
I2C实例解析
实例解析linux内核I2C体系结构(1)一、概述谈到在linux系统下编写I2C驱动,目前主要有两种方式,一种是把I2C设备当作一个普通的字符设备来处理,另一种是利用linux I2C驱动体系结构来完成。
下面比较下这两种驱动。
第一种方法的好处(对应第二种方法的劣势)有:●思路比较直接,不需要花时间去了解linux内核中复杂的I2C子系统的操作方法。
第一种方法问题(对应第二种方法的好处)有:●要求工程师不仅要对I2C设备的操作熟悉,而且要熟悉I2C的适配器操作;●要求工程师对I2C的设备器及I2C的设备操作方法都比较熟悉,最重要的是写出的程序可移植性差;●对内核的资源无法直接使用。
因为内核提供的所有I2C设备器及设备驱动都是基于I2C子系统的格式。
I2C适配器的操作简单还好,如果遇到复杂的I2C适配器(如:基于PCI的I2C适配器),工作量就会大很多。
本文针对的对象是熟悉I2C协议,并且想使用linux内核子系统的开发人员。
网络和一些书籍上有介绍I2C子系统的源码结构。
但发现很多开发人员看了这些文章后,还是不清楚自己究竟该做些什么。
究其原因还是没弄清楚I2C子系统为我们做了些什么,以及我们怎样利用I2C子系统。
本文首先要解决是如何利用现有内核支持的I2C适配器,完成对I2C设备的操作,然后再过度到适配器代码的编写。
本文主要从解决问题的角度去写,不会涉及特别详细的代码跟踪。
二、I2C设备驱动程序编写首先要明确适配器驱动的作用是让我们能够通过它发出符合I2C标准协议的时序。
在Linux内核源代码中的drivers/i2c/busses目录下包含着一些适配器的驱动。
如S3C2410的驱动i2c-s3c2410.c。
当适配器加载到内核后,接下来的工作就要针对具体的设备编写设备驱动了。
编写I2C设备驱动也有两种方法。
一种是利用系统给我们提供的i2c-dev.c来实现一个i2c 适配器的设备文件。
然后通过在应用层操作i2c适配器来控制i2c设备。
Linux I2C设备驱动编写
Linux I2C设备驱动编写(一)在Linux驱动中I2C系统中主要包含以下几个成员:如果一个I2C适配器不支持I2C通道,那么就将master_xfer成员设为NULL。
如果适配器支持SMBUS 协议,那么需要去实现smbus_xfer,如果smbus_xfer指针被设为NULL,那么当使用SMBUS协议的时候将会通过I2C通道进行仿真。
master_xfer指向的函数的返回值应该是已经成功处理的消息数,或者返回负数表示出错了。
functionality指针很简单,告诉询问着这个I2C主控器都支持什么功能。
在内核的drivers/i2c/i2c-stub.c中实现了一个i2c adapter的例子,其中实现的是更为复杂的SMBUS。
SMBus 与I2C的区别通常情况下,I2C和SMBus是兼容的,但是还是有些微妙的区别的。
时钟速度对比:在电气特性上他们也有所不同,SMBus要求的电压范围更低。
I2C driver具体的I2C设备驱动,如相机、传感器、触摸屏、背光控制器常见硬件设备大多都有或都是通过I2C 协议与主机进行数据传输、控制。
结构体如下:如同普通设备的驱动能够驱动多个设备一样,一个I2C driver也可以对应多个I2C client。
以重力传感器AXLL34X为例,其实现的I2C驱动为:这里要说明一下module_i2c_driver宏定义(i2c.h):module_driver():理解上述宏定义后,将module_i2c_driver(adxl34x_driver)展开就可以得到:这一句宏就解决了模块module安装卸载的复杂代码。
这样驱动开发者在实现I2C驱动时只要将i2c_driver结构体填充进来就可以了,无需关心设备的注册与反注册过程。
I2C client即I2C设备。
I2C设备的注册一般在板级代码中,在解析实例前还是先熟悉几个定义:下面还是以adxl34x为例:这样ADXL34X的i2c设备就被注册到了系统中,当名字与i2c_driver中的id_table中的成员匹配时就能够出发probe匹配函数了。
i2c_register_driver函数详解 -回复
i2c_register_driver函数详解-回复标题:i2c_register_driver函数详解在嵌入式系统中,I2C(Inter-Integrated Circuit)是一种常用的通信协议,用于设备之间的数据交换。
在Linux内核中,i2c_register_driver函数是用于注册I2C驱动程序的核心函数。
本文将详细解析i2c_register_driver函数的使用方法和工作原理。
一、函数定义首先,我们来看一下i2c_register_driver函数的定义:cstruct i2c_driver *i2c_register_driver(struct i2c_driver *);该函数接受一个指向i2c_driver结构体的指针作为参数,返回一个指向同一结构体的指针。
这个结构体包含了驱动程序的相关信息,如名称、操作函数等。
二、i2c_driver结构体在深入理解i2c_register_driver函数之前,我们需要先了解i2c_driver 结构体。
以下是一个典型的i2c_driver结构体的例子:cstruct i2c_driver {const char *name;struct module *owner;const struct i2c_device_id *id_table;int (*probe)(struct i2c_client *, const struct i2c_device_id *);int (*remove)(struct i2c_client *);void (*shutdown)(struct i2c_client *);int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);};在这个结构体中,各个字段的含义如下:- name:驱动程序的名称。
- owner:模块的所有者,通常设置为THIS_MODULE。
Linux I2C总线体系结构及I2C设备的访问控制研究
福 建 电
脑
21 0 1年第 3 期
Ln xIC总线体 系结构及 IC设 备 的访 问控 制研 究 iu 2 2
莫 丽娟 .王 静 文
(黄 河水利 职 业技 术 学院 河 南 开封 4 50 7 0 3)
【 摘 要 】 RM iu 用 的越 来越 广 泛,iu :A Ln x应 Ln x驱动 程序 的设计 也成 了工程 师们 开发硬 件设 备 必须
Ln x的 IC体 系结 构 分 为 3个 部 分 : C核 心 、 iu 2 I 2 内核 中 ie 2. h文件 对 ic d vri _ l n 、 c aa 2 _ f e、 e ci ti — d p i 2 e 2 t 和 ic l r m这 四个数 据结构进 行 了定义 . 析 e r 2 a oi g t h 分 IC总线 驱动 、 C设备 驱动 。 2 I 2 IC核 心对 应 的源 码 在 Ln X2 2 iU . 6内核 d vr目录 这 四个 数据 结构 复杂 的关 系是理解 IC体 系结 构 的关 i re 2 下 的 ic c . 2 — oe 它提供 了 IC总线 和 IC设备 驱动 的 键 所在 rc 2 2
C U内部 P
e ( ) c d vr ic ci n 。 2 i _ f e 与 2 l t 2 i ic di r 2 r e 对应 一套驱 动方法 .是 纯粹辅 助作 用 的 v 数 据 结构 。 不对 应 任何 的物 理实 体 。ic ci t 应 于 2 l n 对 e
_
真 实 的物 理设 备 . 每个 IC设 备 都需 要 一 个 icci t 2 2_ l n e
来 描述 。
( ica a t 3) d pe与 ic. in 2 2 l t c e 。‘
LinuxI2C驱动整理(以RK3399Pro+Kernel4.4为例)
LinuxI2C驱动整理(以RK3399Pro+Kernel4.4为例)⼀. Linux I2C驱动架构Linux内核⾥,I2C驱动框架可以分为两层,adapter驱动和deivce驱动。
Adapter驱动也可以理解为I2C总线驱动,指的是SOC⾥的I2C控制器驱动。
⼀个SOC可能包含多个I2C控制器,⽽每个控制器的使⽤⽅式是相同的(寄存器参数、收发数据的⽅法等),因此多个控制器可以共⽤⼀套adapter驱动;Deivce驱动,对应的是SOC外围的I2C设备,不同类型I2C设备需要开发不同的设备驱动,同⼀类型的I2C设备可以使⽤⼀种驱动,但是每⼀个I2C设备都由⼀个唯⼀的client来描述。
⼆. Adapter配置DTSI⽂件(kernel/arch/arm64/boot/dts/rockchip/rk3399.dtsi)描述了RK3399Pro所有的I2C控制器信息:i2c0: i2c@ff3c0000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff3c00000x00x1000>;clocks = <&pmucru SCLK_I2C0_PMU>, <&pmucru PCLK_I2C0_PMU>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c0_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c1: i2c@ff110000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1100000x00x1000>;clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c1_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c2: i2c@ff120000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1200000x00x1000>;clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c2_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c3: i2c@ff130000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1300000x00x1000>;clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c3_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c5: i2c@ff140000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1400000x00x1000>;clocks = <&cru SCLK_I2C5>, <&cru PCLK_I2C5>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c5_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c6: i2c@ff150000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1500000x00x1000>;clocks = <&cru SCLK_I2C6>, <&cru PCLK_I2C6>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c6_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c7: i2c@ff160000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1600000x00x1000>;clocks = <&cru SCLK_I2C7>, <&cru PCLK_I2C7>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c7_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c4: i2c@ff3d0000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff3d00000x00x1000>;clocks = <&pmucru SCLK_I2C4_PMU>, <&pmucru PCLK_I2C4_PMU>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c4_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c8: i2c@ff3e0000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff3e00000x00x1000>;clocks = <&pmucru SCLK_I2C8_PMU>, <&pmucru PCLK_I2C8_PMU>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c8_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};可以看出,该SOC共有9个I2C控制器,分别为I2C0~I2C8, 每个控制器对应了不同的寄存器基地址(例如I2C0对应0xff3c0000),它们的compatible匹配属性都是"rockchip,rk3399-i2c",也就是对应了同⼀个adapter驱动。
i2c的原理及应用
i2c的原理及应用1. 什么是i2ci2c(Inter-Integrated Circuit)是一种通信协议,用于在集成电路之间进行数据传输。
它是一种串行通信协议,通常用于连接多个集成电路芯片,如传感器、显示屏等。
2. i2c的工作原理i2c协议使用两根信号线进行通信:主机发送数据的SDA线和控制信号的SCL 线。
通信是通过主机发起传输并选择从机设备进行通信。
下面是i2c传输的步骤:1.主机发送起始位:主机将SDA线从高电平拉低,然后拉低SCL线。
2.主机发送设备地址和读写位:主机将设备地址和读写位发送到SDA线上,并拉高SCL线。
3.主机等待从机响应:主机等待从机设备响应,响应由SDA线上的电平状态决定。
4.传输数据:主机和从机设备之间可以传输数据,每次传输都由主机提供时钟信号。
5.主机发送停止位:主机将SDA线从低电平拉高,然后拉高SCL线,表示传输结束。
3. i2c的应用领域i2c通信协议在许多电子设备中被广泛应用,以下是一些常见的应用领域:3.1 传感器i2c协议非常适合连接各种类型的传感器,包括温度传感器、湿度传感器、压力传感器等。
它能够提供高速、可靠的数据传输,方便将传感器模块集成到各种电子设备中。
3.2 显示屏i2c协议也可以用于连接显示屏,如液晶显示屏和OLED显示屏等。
通过i2c总线,可以通过发送指令和数据,控制显示屏的亮度、对比度、内容等。
3.3 存储设备i2c协议还可以用于连接存储设备,如EEPROM、Flash存储器等。
通过i2c总线,可以读取和写入存储设备中的数据,方便进行配置和数据存储。
3.4 工业自动化i2c通信协议在工业自动化领域也有广泛的应用。
它可以用于传输传感器数据、控制器之间的通信、参数配置等。
3.5 嵌入式系统i2c协议在嵌入式系统中也被广泛使用。
它可以用于连接各种外设,如键盘、鼠标、音频设备等,实现嵌入式系统的功能扩展。
4. i2c的优点i2c通信协议具有以下几个优点:•多设备连接i2c支持多个设备通过同一条总线进行通信,简化了设备之间的连接,降低了硬件成本。
I2C通信协议详细讲解
I2C通信协议详细讲解I2C(Inter-Integrated Circuit)是一种串行通信协议,由Philips公司于1980年代初开发,旨在实现多个集成电路之间的简单、高效通信。
I2C协议适用于芯片之间的通信,如存储器、A/D转换器、传感器等。
它具有两根线,一根是时钟线(SCL),用于同步数据传输,另一根是数据线(SDA),用于传输数据。
以下是I2C协议的详细讲解。
1.总线拓扑I2C总线是基于主从架构,其中一个设备充当主设备(Master),其他设备作为从设备(Slave)。
总线上最多可以连接112个从设备,每个从设备通过唯一的地址进行识别。
2.通信格式I2C通信由一系列的起始位、地址位、数据位和停止位组成。
在通信开始之前,主设备负责发出起始位(Start Bit),表示通信开始。
接着主设备发送从设备的7位地址(最低位用于指示读写操作),从设备在总线上进行匹配。
如果从设备地址匹配成功,主设备发送数据或命令给从设备;若从设备地址匹配失败,主设备发送停止位(Stop Bit)结束通信。
3.传输速率I2C协议定义了几种标准的传输速率,如标准模式(Standard Mode)的速率为100 kHz,快速模式(Fast Mode)的速率为400 kHz,高速模式(High-Speed Mode)的速率为3.4 MHz。
除此之外,还有更高速的模式如超高速模式(Ultra Fast Mode)和超快速模式(Ultra Fast Mode),速率分别为5 MHz和25 MHz。
4.时钟同步5.主设备模式主设备可以发送起始位、地址位、数据位和停止位。
它与从设备之间可以进行单向或双向通信。
主设备可以向从设备发送读请求或写请求,并且可以按照需要在传输过程中发出重启位(Repeated Start Bit)来处理多个数据传输操作。
6.从设备模式从设备通过地址识别来接受或发送数据。
从设备可以处于可寻址模式(Addressable Mode)或普通模式(General Call Mode)。
I2C详细介绍及编程
I2C详细介绍及编程I2C(Inter-Integrated Circuit)是一种串行通信协议,常用于连接微控制器、传感器、存储器等设备,以实现数据通信。
本文将详细介绍I2C的原理、特点以及编程。
一、I2C的原理和特点I2C协议由飞利浦(Philips)公司于1982年开发,旨在简化数字电路上周边设备的通信。
I2C使用两条线(SCL和SDA)进行数据传输,其中SCL是时钟线,SDA是数据线。
这种双线式的通信使得I2C可以同时进行数据传输和电源供给,极大地简化了设备之间的连接。
在I2C通信中,主设备(通常是微控制器)发起通信,而从设备被动应答。
主设备通过在SCL线上产生时钟信号来控制通信节奏,并通过SDA 线实现数据传输。
数据的传输可以是单向的(主设备向从设备发送数据)或双向的(主设备与从设备之间的双向数据传输)。
I2C协议中的从设备通过一个唯一的地址来识别和寻址。
主设备可以选择与一个或多个从设备进行通信,只需发送相应的地址即可。
在开始通信前,主设备会发送一个开始信号,然后跟着从设备地址和读写位,然后才是数据或命令。
从设备在收到自己地址后会发出应答信号,主设备接收到应答信号后才会继续发送数据。
通信结束后,主设备会发送停止信号。
I2C的特点包括:1.双向通信:主设备和从设备之间可以进行双向的数据传输,减少通信线的需求和复杂度。
2.主-从结构:I2C通信中有一个主设备控制通信的发起和终止,而从设备被动应答。
3.多从结构:主设备可以与多个从设备进行通信,只需要发送不同的地址。
4.低速传输:I2C通信的时钟频率相对较低,一般在100kHz或400kHz。
二、I2C的编程实现在进行I2C编程之前,需要确保硬件上有I2C接口。
常见的I2C接口引脚包括SCL(时钟线)和SDA(数据线),同时需要进行相应的电源连接。
I2C编程的具体实现会有所差异,根据不同的硬件平台和编程语言而有所不同。
以下是一个基于Arduino平台的简单示例:```cpp#include <Wire.h>#define DEVICE_ADDRESS 0x50void setuWire.begin(;Serial.begin(9600);void loo//发送命令Wire.beginTransmission(DEVICE_ADDRESS);Wire.write(0x00); // 使用写入地址0x00Wire.write(0x01); // 写入数据0x01Wire.endTransmission(;delay(100);//读取数据Wire.requestFrom(DEVICE_ADDRESS, 1);if (Wire.available()int data = Wire.read(;Serial.print("Received: ");Serial.println(data);}delay(1000);```上述示例代码中,我们使用Wire库来实现I2C通信。
I2C总线原理介绍AT24C02内部原理介绍
I2C总线原理介绍AT24C02内部原理介绍I2C(Inter-Integrated Circuit)是一种串行通信总线,由Philips公司于1980年代初开发。
它是一种简单而高效的串行通信协议,能够在多个设备之间进行通信。
I2C总线由两根线组成,分别是SCL(时钟线)和SDA(数据线)。
SCL由主设备产生并控制通信速度,SDA用于数据的传输。
每个设备都有一个唯一的地址,以便其他设备可以通过地址找到它并与其通信。
I2C总线使用了主从结构,其中主设备是指负责发起通信的设备,从设备则是被动接受通信的设备。
在I2C总线上,可以连接多个从设备,但只能有一个主设备。
主设备负责发起通信并控制通信的过程,从设备在收到主设备的请求后回应,并传输数据。
在I2C总线上,通信的过程可以分为以下几个步骤:1.主设备将起始信号发送到总线上,通知其他设备开始通信。
2.主设备发送从设备地址和读写标志位,指示通信的目标设备和读写操作。
3.从设备根据接收到的地址判断是否为自己,如果是则回应ACK信号。
4.主设备根据ACK信号判断是否有设备应答,如有应答则继续通信,否则终止通信。
5.主设备发送数据或请求数据,并接收从设备的应答。
6.数据传输完成后,主设备发送停止信号,终止本次通信。
1.双向传输:I2C总线上的数据传输是双向的,主设备既可以发送数据给从设备,也可以从从设备读取数据。
2.多从设备:I2C总线可以连接多个从设备,每个从设备都有唯一的地址,主设备通过地址选择通信的目标设备。
3.速度可变:I2C总线的通信速度可以通过改变时钟频率来调整,可以根据实际需求选择合适的速度。
4.硬件简单:I2C总线只需要两根线即可完成通信,硬件接口简单,成本低廉。
AT24C02内部原理介绍:AT24C02是一种8位串行电子可擦除可编程只读存储器(EEPROM),由Atmel公司生产。
它具有2K字节的存储容量,可以存储2048个8位字节的数据。
AT24C02采用了I2C总线通信接口,可以与其他I2C设备进行通信。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实例解析linux内核I2C体系结构(2)华清远见刘洪涛四、在内核里写i2c设备驱动的两种方式前文介绍了利用/dev/i2c-0在应用层完成对i2c设备的操作,但很多时候我们还是习惯为i2c设备在内核层编写驱动程序。
目前内核支持两种编写i2c驱动程序的方式。
下面分别介绍这两种方式的实现。
这里分别称这两种方式为“Adapter方式(LEGACY)”和“Probe方式(new style)”。
(1)Adapter方式(LEGACY)(下面的实例代码是在2.6.27内核的pca953x.c基础上修改的,原始代码采用的是本文将要讨论的第2种方式,即Probe方式)●构建i2c_driverstatic struct i2c_driver pca953x_driver = {.driver = {.name= "pca953x", //名称},.id= ID_PCA9555,//id号.attach_adapter= pca953x_attach_adapter, //调用适配器连接设备.detach_client= pca953x_detach_client,//让设备脱离适配器};●注册i2c_driverstatic int __init pca953x_init(void){return i2c_add_driver(&pca953x_driver);}module_init(pca953x_init);●attach_adapter动作执行i2c_add_driver(&pca953x_driver)后会,如果内核中已经注册了i2c适配器,则顺序调用这些适配器来连接我们的i2c设备。
此过程是通过调用i2c_driver中的attach_adapter方法完成的。
具体实现形式如下:static int pca953x_attach_adapter(struct i2c_adapter *adapter){return i2c_probe(adapter, &addr_data, pca953x_detect);/*adapter:适配器addr_data:地址信息pca953x_detect:探测到设备后调用的函数*/}地址信息addr_data是由下面代码指定的。
/* Addresses to scan */static unsigned short normal_i2c[] ={0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,I2C_CLIENT_END};I2C_CLIENT_INSMOD;注意:normal_i2c里的地址必须是你i2c芯片的地址。
否则将无法正确探测到设备。
而I2C_ CLIENT_INSMOD是一个宏,它会利用normal_i2c构建addr_data。
构建i2c_client,并注册字符设备驱动i2c_probe在探测到目标设备后,后调用pca953x_detect,并把当时的探测地址address 作为参数传入。
static int pca953x_detect(struct i2c_adapter *adapter, int address, int kind){struct i2c_client *new_client;struct pca953x_chip *chip; //设备结构体int err = 0,result;dev_t pca953x_dev=MKDEV(pca953x_major,0);//构建设备号,根据具体情况设定,这里我只考虑了normal_i2c中只有一个地址匹配的情况。
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA|I2C_FUNC_SMBUS_WORD_DA TA))//判定适配器能力goto exit;if (!(chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL))) {err = -ENOMEM;goto exit;}/****构建i2c-client****/chip->client=kzalloc(sizeof(struct i2c_client),GFP_KERNEL);new_client = chip->client;i2c_set_clientdata(new_client, chip);new_client->addr = address;new_client->adapter = adapter;new_client->driver = &pca953x_driver;new_client->flags = 0;strlcpy(new_client->name, "pca953x", I2C_NAME_SIZE);if ((err = i2c_attach_client(new_client)))//注册i2c_clientgoto exit_kfree;if (err)goto exit_detach;if(pca953x_major){result=register_chrdev_region(pca953x_dev,1,"pca953x");}else{result=alloc_chrdev_region(&pca953x_dev,0,1,"pca953x");pca953x_major=MAJOR(pca953x_dev);}if (result < 0) {printk(KERN_NOTICE "Unable to get pca953x region, error %d\n", result);return result;}pca953x_setup_cdev(chip,0); //注册字符设备,此处不详解return 0;exit_detach:i2c_detach_client(new_client);exit_kfree:kfree(chip);exit:return err;}i2c_check_functionality用来判定设配器的能力,这一点非常重要。
你也可以直接查看对应设配器的能力,如static const struct i2c_algorithm smbus_algorithm = {.smbus_xfer= i801_access,.functionality= i801_func,};static u32 i801_func(struct i2c_adapter *adapter){return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |I2C_FUNC_SMBUS_BYTE_DA TA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DA TA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK| (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);}字符驱动的具体实现struct file_operations pca953x_fops = {.owner = THIS_MODULE,.ioctl= pca953x_ioctl,.open= pca953x_open,.release =pca953x_release,};字符设备驱动本身没有什么好说的,这里主要想说一下,如何在驱动中调用i2c设配器帮我们完成数据传输。
目前设配器主要支持两种传输方法:smbus_xfer和master_xfer。
一般来说,如果设配器支持了master_xfer那么它也可以模拟支持smbus的传输。
但如果只实现smbus_xfer,则不支持一些i2c的传输。
int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg *msgs,int num);int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,unsigned short flags, char read_write,u8 command, int size, union i2c_smbus_data * data);master_xfer中的参数设置,和前面的用户空间编程一致。
现在只是要在驱动中构建相关的参数然后调用i2c_transfer来完成传输既可。
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) smbus_xfer中的参数设置及调用方法如下:static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val){int ret;ret = i2c_smbus_write_word_data(chip->client, reg << 1, val);if (ret < 0) {dev_err(&chip->client->dev, "failed writing register\n");return -EIO;}return 0;}上面函数完成向芯片的地址为reg的寄存器写一个16bit的数据。
i2c_smbus_write_word_data的实现如下:s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value){union i2c_smbus_data data;data.word = value;return i2c_smbus_xfer(client->adapter,client->addr,client->flags,I2C_SMBUS_WRITE,command,I2C_SMBUS_WORD_DATA,&data);}从中可以看出smbus传输一个16位数据的方法。
其它操作如:字符写、字符读、字读、块操作等,可以参考内核的i2c-core.c中提供的方法。
●注销i2c_driverstatic void __exit pca953x_exit(void){i2c_del_driver(&pca953x_driver);}module_exit(pca953x_exit);●detach_client动作顺序调用内核中注册的适配器来断开我们注册过的i2c设备。