基于iic ds3231 linux驱动说明
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);}。
linux i2c协议类型 -回复

linux i2c协议类型-回复Linux I2C协议类型I2C(Inter-Integrated Circuit)是一种串行通信协议,用于连接微控制器和外围设备。
在Linux操作系统中,支持多种I2C协议类型。
本文将详细介绍Linux中常用的I2C协议类型,并一步一步回答相关问题。
第一步:了解I2C协议I2C是一种全双工的串行通信协议,使用两根线进行数据传输:SDA(Serial Data Line)和SCL(Serial Clock Line)。
SDA线用于传输数据,SCL线用于同步时钟。
I2C协议支持多主机和多从机的连接,并能够在不同电压和数据速率下工作。
第二步:设置I2C驱动在Linux系统中,需要配置I2C驱动,以便与外围设备进行通信。
首先,确保内核已经编译了适当的I2C驱动。
然后,加载I2C核心模块,例如i2c-dev模块。
可以使用以下命令加载该模块:sudo modprobe i2c-dev第三步:查看I2C适配器在Linux系统中,I2C适配器负责实际的物理层传输。
可以使用`i2cdetect`工具来查看可用的I2C适配器。
例如,使用以下命令可以列出所有的I2C 适配器:i2cdetect -l该命令将显示适配器号、适配器类型和所使用的总线号。
第四步:选择合适的I2C协议类型在Linux系统中,支持多种I2C协议类型,每种类型有不同的驱动和功能。
以下是一些常见的I2C协议类型:1. SMBus(System Management Bus)是一种基于I2C的通信协议,用于管理系统中的各种设备。
SMBus提供了一组标准的功能和命令,例如读取和写入数据、查询设备ID等。
大多数传感器和监控设备都支持SMBus协议。
2. I2C-ALGOBIT(I2C Algorithm Bit-Banging)是一种软件实现的I2C 协议类型。
它不依赖于硬件特性,可以在任何GPIO引脚上使用。
ALGOBIT允许用户定义I2C协议的时序和速率,但相比硬件实现的I2C,其性能较低。
linux驱动之i2c子系统device注册driver注册简单分析

linux驱动之i2c⼦系统device注册driver注册简单分析Linux 驱动设计主要是根据分层分离思想,i2c⼦系统分为i2cocre、adapter、及device_driver层,其实adapter也是个device,只不过是我们主控芯⽚的I2C控制接⼝⽽已,我们的主控芯⽚有⼏个I2C接⼝就有⼏个adapter;i2ccore这⼀层linux已经帮我们实现,主要的⼯做是类似platform总线的作⽤,负责drvier及设备的注册,相⽐platform多了个adapter的注册管理⼯作,以及i2c的数据发送接收等等算法,说算法有点夸⼤,其实就是按照i2c的通讯协议做的收发时序⽽已;adapter这⼀层⼀般主控芯⽚⼚家会提供,所以也不需⾃⼰编写,s3c2440芯⽚这⼀层是采⽤的s3c2410的适配器驱动,⼤致框架是采⽤platform虚拟总线,向i2ccore注册adapter驱动;device_driver这端的驱动就要求⾃⼰编写了,这主要是我们外接设备的驱动,⽐如⼀些i2c接⼝的三轴加速度计、at24c0x系列的eeprom等等……这部分代码其实就是实现如何操作他们,⽐如发什么数据给他们可以启动他们、发什么数据给他们可以读到数据。
按照i2ccore的框架,device_driver 分为两部分内容,⼀个是device的注册,另⼀部分是driver的注册,在两边分别完成注册的时候,会分别调⽤i2ccore的match函数,进⾏匹配,匹配和platform的匹配⽅式⼀致,是通过名字进⾏匹配,不过这个名字和platform的名字不⼀样⽽已;如下列出device及driver注册在i2ccore中的调⽤过程,从过程中可以看出匹配、绑定及调⽤driver端的probe函数过程:注册device:i2c_new_devicedevice_registerdevice_addbus_probe_device/* 判断device与driver是否匹配 */device_attach/* 匹配成功,调⽤bind函数绑定 */device_bind_driver/* 绑定成功,调⽤driver端的probe函数 */driver_deferred_probe_del ( dev ); driver_deferred_probe_trigger();注册driver:i2c_register_driverdriver_registerbus_add_driverdriver_attach/* 在总线上的没个设备轮训匹配,实际是调⽤__driver_attach函数进⾏匹配 */bus_for_each_dev ( drv->bus, NULL, drv, __driver_attach );if ( !dev->driver ) // 如果设备还未绑定driver driver_probe_device ( drv, dev ); ret = really_probe ( dev, drv ); dev->driver = drv; // 设备和driver绑定 ret = drv->probe ( dev ); // 调⽤driver的probe driver_bound ( dev ); // device和driver绑定总结下就是编写i2c设备驱动,和platform虚拟总线⼀致,只不过最后是注册到了i2c总线⽽已;linux驱动还是采⽤分离分层的思想设计驱动。
Linux_I2C设备驱动文件操作接口

I2C适配器驱动被作为一个单独的模块被加载进内核,在模块的加载和卸载函数中,只需注册和注销一个platform_driver结构体,如代码清单。
代码清单 S3C2410 I2C总线驱动模块加载与卸载1 static int __init i2c_adap_s3c_init(void)2 {3 int ret;45 ret = platform_driver_register(&s3c2410_i2c_driver);6 if (ret == 0) {7 ret =platform_driver_register(&s3c2440_i2c_driver);8 if (ret)9 platform_driver_unregister(&s3c2410_i2c_driver);10 }1112 return ret;13 }1415 static void __exit i2c_adap_s3c_exit(void)16 {17 platform_driver_unregister(&s3c2410_i2c_driver);18 platform_driver_unregister(&s3c2440_i2c_driver);19 }20 module_init(i2c_adap_s3c_init);21 module_exit(i2c_adap_s3c_exit);platform_driver结构体包含了具体适配器的probe()函数、remove()函数、resume()函数指针等信息,它需要被定义和赋值,如代码清单。
代码清单 platform_driver结构体1 static struct platform_driver s3c2410_i2c_driver = {2 .probe = s3c24xx_i2c_probe,3 .remove = s3c24xx_i2c_remove,4 .resume = s3c24xx_i2c_resume,5 .driver = {6 .owner = THIS_MODULE,7 .name = "s3c2410-i2c",8 },9 };当通过Linux内核源代码/drivers/base/文件中定义platform_driver_unregister()函数注册platform_driver结构体时,其中probe指针指向的s3c24xx_i2c_probe()函数将被调用以初始化适配器硬件,如代码清单。
LINUX设备驱动开发详解

LINUX设备驱动开发详解概述LINUX设备驱动开发是一项非常重要的任务,它使得硬件设备能够与操作系统进行有效地交互。
本文将详细介绍LINUX设备驱动开发的基本概念、流程和常用工具,帮助读者了解设备驱动开发的要点和技巧。
设备驱动的基本概念设备驱动是连接硬件设备和操作系统的桥梁,它负责处理硬件设备的输入和输出,并提供相应的接口供操作系统调用。
设备驱动一般由设备驱动程序和设备配置信息组成。
设备驱动程序是编写解决设备驱动的代码,它负责完成设备初始化、IO操作、中断处理、设备状态管理等任务。
设备驱动程序一般由C语言编写,使用Linux内核提供的API函数进行开发。
设备配置信息是定义硬件设备的相关参数和寄存器配置的文件,它告诉操作系统如何与硬件设备进行交互。
设备配置信息一般以设备树或者直接编码在设备驱动程序中。
设备驱动的开发流程设备驱动的开发流程包括设备初始化、设备注册、设备操作函数编写和设备驱动注册等几个主要步骤。
下面将详细介绍这些步骤。
设备初始化设备初始化是设备驱动开发的第一步,它包括硬件初始化和内存分配两个主要任务。
硬件初始化是对硬件设备进行基本的初始化工作,包括寄存器配置、中断初始化等。
通过操作设备的寄存器,将设备设置为所需的状态。
内存分配是为设备驱动程序分配内存空间以便于执行。
在设备初始化阶段,通常需要为设备驱动程序分配一块连续的物理内存空间。
设备注册设备注册是将设备驱动程序与设备对象进行关联的过程,它使得操作系统能够正确地管理设备。
设备注册包括设备号分配、设备文件创建等操作。
设备号是设备在系统中的唯一标识符,通过设备号可以找到设备对象对应的设备驱动程序。
设备号分配通常由操作系统负责,设备驱动程序通过注册函数来获取设备号。
设备文件是用户通过应用程序访问设备的接口,它是操作系统中的一个特殊文件。
设备文件的创建需要通过设备号和驱动程序的注册函数来完成。
设备操作函数编写设备操作函数是设备驱动程序的核心部分,它包括设备打开、设备关闭、读和写等操作。
IIC设备驱动程序

IIC设备驱动程序IIC设备是一种通过IIC总线连接的设备,由于其简单性,被广泛引用于电子系统中。
在现代电子系统中,有很多的IIC设备需要进行相互之间通信IIC总线是由PHILIPS公司开发的两线式串行总线,用于连接微处理器和外部IIC设备。
IIC设备产生于20世纪80年代,最初专用与音频和视频设备,现在在各种电子设备中都广泛应用IIC总线有两条总线线路,一条是串行数据线(SDA),一条是串行时钟线(SCL)。
SDA负责数据传输,SCL负责数据传输的时钟同步。
IIC设备通过这两条总线连接到处理器的IIC总线控制器上。
一种典型的设备连接如图:与其他总线相比,IIC总线有很多重要的特点。
在选择一种设备来完成特定功能时,这些特点是选择IIC设备的重要依据。
主要特点:1,每一个连接到总线的设备都可以通过唯一的设备地址单独访问2,串行的8位双向数据传输,位速率在标准模式下可达到100kb/s;快速模式下可以达到400kb/s;告诉模式下可以达到3.4Mb/s3,总线长度最长7.6m左右4,片上滤波器可以增加抗干扰能力,保证数据的完成传输5,连接到一条IIC总线上的设备数量只受到最大电容400pF的限制6,它是一个多主机系统,在一条总线上可以同时有多个主机存在,通过冲突检测方式和延时等待防止数据不被破坏。
同一时间只能有一个主机占用总线IIC总线在传输数据的过程中有3种类型的信号:开始信号、结束信号、和应答信号>>开始信号(S): 当SCL为高电平时,SDA由高电平向低电平跳变,表示将要开始传输数据>>结束信号(P):当SCL为高电平时,SDA由低电平向高电平跳变,表示结束传输数据>>响应信号(ACK): 从机接收到8位数据后,在第9个周期,拉低SDA电平,表示已经收到数据。
这个信号称为应答信号开始信号和结束信号的波形如下图:主机:IIC总线中发送命令的设备,对于ARM处理器来说,主机就是IIC控制器从机:接受命令的设备主机向从机发送数据:主机通过数据线SDA向从机发送数据。
《Linux4.0设备驱动开发详解》笔记--第十五章:LinuxI2C核心、总线与设备驱动
《Linux4.0设备驱动开发详解》笔记--第⼗五章:LinuxI2C核⼼、总线与设备驱动15.1 Linux I2C体系结构I2C核⼼I2C核⼼提供了I2C总线驱动和设备驱动的注册、注销的⽅法,I2C通信(Algorithm)⽅法上层的与具体适配器⽆关代码以及探测设备、检测设备地址的上层代码等I2C总线驱动是对I2C体系结构中适配器端的实现,适配器可由CPU控制,甚⾄可以直接集成在CPU内部总线驱动包含I2C适配器数据结构i2c_adapter、I2C适配器的Algorithm数据结构i2c_algorithm和控制I2C适配器产⽣通信信号的函数I2C设备驱动它是对I2C硬件体系结构中设备端的实现,设备⼀般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU通信I2C驱动主要包含数据结构i2c_driver和i2c_client,需要根据的设备实现其中的成员函数所有的I2C设备都在sysfs⽂件系统中显⽰,存在/sys/bus/i2c⽬录下,以适配器地址和芯⽚地址的形式列出/drivers/i2c/下的⽂件介绍i2c-core.c:实现了I2C核⼼的功能以及/proc/bus/i2c*接⼝i2c-dev.c:实现I2C适配器设备⽂件的功能,每⼀个适配器被分配⼀个设备设配器的主设备号位89,次设备号位:0-255i2c_dev.c并不是根据具体的设备⽽设计的,只是提供了同⽤的read()、write()和ioctl()等接⼝,应⽤层可以通过这些接⼝访问挂接在适配器上的I2C设备的存储空间或寄存器,并控制I2C设备的⼯作⽅式busses⽂件夹:包含⼀些I2C主机控制器驱动,如i2c_omap.c、i2c_s3c2440c.等algos⽂件夹:实现了⼀些I2C总线适配器的通信⽅法i2c_adapter、i2c_algorithm、i2c_driver和i2c_client数据结构的作⽤及其之间的关系i2c_adapter与i2c_algorithmi2c_adapter对应于物理上的⼀个适配器,⽽i2c_algorithm对应于⼀套通信⽅法⼀个i2c_adapter需要i2c_algorithm提供的通信函数来控制适配器产⽣特定的访问周期i2c_algorithm中的关键函数master_xfer()⽤于产⽣I2C访问周期需要的信号,以i2c_msg(即I2C消息)为单位i2c_driver与i2c_clienti2c_driver对应于⼀套驱动⽅法,struct i2c_device_id形式的id_table是该驱动所⽀持的I2C设备的ID表i2c_client对应于真实的物理设备,每个I2C设备都需⼀个i2c_client来描述⼀个i2c_driver⽀持多个同类型的i2c_clienti2c_client的信息通常在BSP的板⽂件中通过i2c_board_info填充,包括设备的ID号、地址、中断号等信息在I2C总线驱动i2c_bus_type的match()函数i2c_device_match()中,会调⽤i2c_match_id()函数匹配在板⽂件中定义的ID和i2c_driver所⽀持的ID表i2c_adapter与i2c_client其关系与I2C设备体系中适配器与设备的关系⼀致,即i2c_client依附于i2c_driver⼀个i2c_driver可以被多个i2c_client依附,i2c_driver中包含有依附它的i2c_client的链表15.2 I2C核⼼增加、删除i2c_adapterint i2c_add_adapter(struct i2c_adapter *adap);int i2c_del_adapter(struct i2c_adapter *adap);增加、删除i2c_driverint i2c_register_driver(struct module *owner, struct i2c_driver *driver);int i2c_del_driver(struct i2c_driver *driver);inline int i2c_add_driver(struct i2c_driver *driver);i2c_client依附/脱离int i2c_attach_client(struct i2c_client *client);int i2c_detach_client(struct i2c_client *client);当⼀个具体的client被侦测到并被关联的时候,设备和sysfs⽂件将被注册。
Linux驱动之i2c用户态调用
一、概述I2C只有两条线,一条串行数据线:SDA,一条是时钟线SCL.正因为这样,它方便了工程人员的布线.二、用户态实现设备驱动在Linux内核代码文件i2c-dev.c中实现了I2C适配器设备文件的功能,针对每个适配器生成一个主设备号为89的设备节点(次设备号为0-255),I2c-dev.c并没有针对特定的设备而设计,只是提供了通用的read(),write(),和ioctl()等文件操作接口,在用户空间的应用层就可以借用这些接口访问挂接在适配器上的I2C设备的存储空间或寄存器,并控制I2C设备的工作方式。
i2c适配器的设备节点是/dev/i2c-x,其中x是数字。
由于适配器编号是动态分配的(和注册次序有关),所以想了解哪一个适配器对应什么编号,可以查看/sys/class/i2c-dev/目录下的文件内容。
三、用户态调用3.1、i2c-dev用户空间操作i2c,需要包含以下头文件。
打开适配器对应的设备节点i2c-dev为打开的线程建立一个i2c_client,但是这个i2c_client并不加到i2c_adapter的client链表当中。
他是一个虚拟的临时client,当用户打开设备节点时,它自动产生,当用户关闭设备节点时,它自动被释放。
3.2、ioctl()查看include/linux/i2c-dev.h文件,可以看到i2c支持的IOCTL命令1.#define I2C_RETRIES0x0701/*设置收不到ACK时的重试次数*/2.#define I2C_TIMEOUT0x0702/*设置超时时限的jiffies*/3.#define I2C_SLAVE0x0703/*设置从机地址*/4.#define I2C_SLAVE_FORCE0x0706/*强制设置从机地址*/5.#define I2C_TENBIT0x0704/*选择地址位长:=0for7bit,!=0for10bit*/6.#define I2C_FUNCS0x0705/*获取适配器支持的功能*/7.#define I2C_RDWR0x0707/*Combin ed R/W transfer(one STOP only)*/8.#define I2C_PEC0x0708/* !=0to use PEC with SMBus*/9.#define I2C_SMBUS0x0720/*SMBus transfer*/例如:1、设置重试次数:ioctl(fd, I2C_RETRIES,m);设置适配器收不到ACK时重试的次数为m。
LinuxIIO驱动
LinuxIIO驱动⼯业场合⾥⾯也有⼤量的模拟量和数字量之间的转换,也就是我们常说的 ADC 和 DAC。
⽽且随着⼿机、物联⽹、⼯业物联⽹和可穿戴设备的爆发,传感器的需求只持续增强。
⽐如⼿机或者⼿环⾥⾯的加速度计、光传感器、陀螺仪、⽓压计、磁⼒计等,这些传感器本质上都是ADC,⼤家注意查看这些传感器的⼿册,会发现他们内部都会有个 ADC,传感器对外提供 IIC或者 SPI 接⼝,SOC 可以通过 IIC 或者 SPI 接⼝来获取到传感器内部的 ADC 数值,从⽽得到想要测量的结果。
Linux 内核为了管理这些⽇益增多的 ADC 类传感器,特地推出了 IIO ⼦系统,本章我们就来学习如何使⽤ IIO ⼦系统来编写 ADC 类传感器驱动。
1.IIO⼦系统简介IIO 全称是 Industrial I/O,翻译过来就是⼯业 I/O,⼤家不要看到“⼯业”两个字就觉得 IIO是只⽤于⼯业领域的。
⼤家⼀般在搜索 IIO ⼦系统的时候,会发现⼤多数讲的都是 ADC,这是因为 IIO 就是为 ADC 类传感器准备的,当然了 DAC 也是可以的。
⼤家常⽤的陀螺仪、加速度计、电压/电流测量芯⽚、光照传感器、压⼒传感器等内部都是有个 ADC,内部 ADC 将原始的模拟数据转换为数字量,然后通过其他的通信接⼝,⽐如 IIC、SPI 等传输给 SOC。
因此,当你使⽤的传感器本质是 ADC 或 DAC 器件的时候,可以优先考虑使⽤ IIO 驱动框架。
1.1 iio_deviio_dev 结构体第 478 ⾏,currentmode 为当前模式。
第 483 ⾏,buffer 为缓冲区。
第 484 ⾏,buffer_list 为当前匹配的缓冲区列表。
第 485 ⾏,scan_bytes 为捕获到,并且提供给缓冲区的字节数。
第 488 ⾏,available_scan_masks 为可选的扫描位掩码,使⽤触发缓冲区的时候可以通过设置掩码来确定使能哪些通道,使能以后的通道会将捕获到的数据发送到 IIO 缓冲区。
Linux内核i2c读写操作驱动架构
成员变量解说: 1) addr, flags 分别表示从设备的地址和访问操作标志,最初源头为由开发人员构造和初始
化的 i2c_board_info{}结构 2) adapter 在从设备与适配器匹配后,在后端的 i2c_new_device()中被初始化
struct i2c_msg { __u16 addr; __u16 flags; __u16 len; __u8 *buf;
struct i2c_algorithm { int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); u32 (*functionality) (struct i2c_adapter *);
};
成员变量解说: 1) master_xfer 启动 i2c 适配器,分流读写操作的总接口 2) functionality 表示当前 i2c 适配器,支持和实现的操作功能
struct i2c_board_info { unsigned short addr; unsigned short flags; ... ...;
};
成员变量解说: 1) addr 将初始化 i2c_client.addr 2) flags 将初始化 i2c_client.flags
struct i2c_client { unsigned short addr; unsigned short flags; struct i2c_adapter *adapter; ... ...;
具体适配器驱动读写
#define I2C_M_TEN
0x0010
#define I2C_M_RD
0x0001
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于I2C 实时时钟DS3231驱动说明:1Linux的I2C的整体架构Linux的i2c框架中各个部分的关系如图(1)所示:图(1)内核中i2c相关代码可以分为三个层次:●i2c框架:i2c.h和i2c-core.c为i2c框架的主体,提供了核心数据结构的定义、i2c适配器驱动和设备驱动的注册、注销管理,i2c通信方法上层的、与具体适配器无关的代码、检测设备地址的上层代码等;i2c-dev.c用于创建i2c适配器的/dev/i2c/%d设备节点,提供i2c设备访问方法等。
●i2c总线适配器驱动:定义描述具体i2c总线适配器的i2c_adapter数据结构、实现在具体i2c适配器上的i2c总线通信方法,并由i2c_algorithm数据结构进行描述。
●i2c设备驱动:定义描述具体设备的i2c_client和可能的私有数据结构、借助i2c框架的i2c_probe函数实现注册设备的attach_adapter方法、提供设备可能使用的地址范围、以及设备地址检测成功后创建i2c_client数据结构的回调函数。
2I2C驱动相关的数据结构I2C传送信息的数据结构体struct i2c_msg {__u16 addr; /* slave address */__u16 flags;#define I2C_M_TEN 0x10 /* we have a ten bit chip address */#define I2C_M_RD 0x01#define I2C_M_NOSTART 0x4000#define I2C_M_REV_DIR_ADDR 0x2000#define I2C_M_IGNORE_NAK 0x1000#define I2C_M_NO_RD_ACK 0x0800__u16 len; /* msg length */__u8 *buf; /* pointer to msg data */};其中addr 成员是指向器件的地址,flags 是读写标志位,len 是要发送的信息长度,*buf 是发送信息的数据指针,如果是读操作的buf是读到数据的指针。
I2C低层数据传输函数结构体struct i2c_algorithm {/* If an adapter algorithm can't do I2C-level access, set master_xferto NULL. If an adapter algorithm can do SMBus access, setsmbus_xfer. If set to NULL, the SMBus protocol is simulatedusing common I2C messages *//* master_xfer should return the number of messages successfullyprocessed, or a negative value on error */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);/* --- ioctl like call to set div. parameters. */int (*algo_control)(struct i2c_adapter *, unsigned int, unsigned long);/* To determine what the adapter supports */u32 (*functionality) (struct i2c_adapter *);};master_xfer 函数为I2C适配器提供数据传输函数,smbu_xfer 函数为subus协议函数,functionality 函数I2C适配器所支持的功能函数。
I2c 适配器数据结构体struct i2c_adapter {struct module *owner;unsigned int id;unsigned int class;const struct i2c_algorithm *algo; /* the algorithm to access the bus */void *algo_data;/* --- administration stuff. */int (*client_register)(struct i2c_client *);int (*client_unregister)(struct i2c_client *);/* data fields that are valid for all devices */u8 level; /* nesting level for lockdep */struct mutex bus_lock;struct mutex clist_lock;int timeout;int retries;struct device dev; /* the adapter device */struct class_device class_dev; /* the class device */int nr;struct list_head clients;struct list_head list;char name[I2C_NAME_SIZE];struct completion dev_released;struct completion class_dev_released;};适配器主要通过i2c_algorithm 结构体成员确定低层数据的传输方法,client_register 函数用来注册一个i2c_client设备,client_unregister 函数用来注销一个i2c_client 设备,bus_lock 总线互斥锁定义,I2C设备的描述结构体struct i2c_client {unsigned int flags; /* div., see below */unsigned short addr; /* chip address - NOTE: 7bit *//* addresses are stored in the *//* _LOWER_ 7 bits */struct i2c_adapter *adapter; /* the adapter we sit on */struct i2c_driver *driver;/* and our access routines */int usage_count; /* How many accesses currently *//* to the client */struct device dev; /* the device structure */struct list_head list;char name[I2C_NAME_SIZE];struct completion released;};addr 设备芯片的地址,adapter 指针指向设备所在的适配器结构体,driver指针指向所属的i2c驱动结构,dev 设备结体I2C 驱动结构体struct i2c_driver {int id;unsigned int class;/* Notifies the driver that a new bus has appeared. This routine* can be used by the driver to test if the bus meets its conditions* & seek for the presence of the chip(s) it supports. If found, it* registers the client(s) that are on the bus to the i2c admin. via* i2c_attach_client.*/int (*attach_adapter)(struct i2c_adapter *);int (*detach_adapter)(struct i2c_adapter *);/* tells the driver that a client is about to be deleted & gives it* the chance to remove its private data. Also, if the client struct* has been dynamically allocated by the driver in the function above,* it must be freed here.*/int (*detach_client)(struct i2c_client *);/* a ioctl like command that can be used to perform specific functions* with the device.*/int (*command)(struct i2c_client *client,unsigned int cmd, void *arg);struct device_driver driver;struct list_head list;};Attach_adapter 注册I2C设备引用的函数指针,detach_adapter 注销I2C设备引用的函数指针。
3引用到的I2C相关函数3.1. 用到的I2C驱动中各个函数的说明s tatic inline void *dev_get_drvdata(struct device *dev)返回设备私有数据的指针。
static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)保存一个数据到设备的私有数据中。
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)I2C数据信息到设备中去,s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)写一个值到指定位置。