TI-I2C驱动
51单片机的I2C底层驱动程序(IO口模拟)

51单片机的I2C底层驱动程序(IO口模拟)/*Title:I2C for 80C51Author:yuyouliang51单片机(本人使用STC89C52单片机,12T模式)的I2C驱动程序,使用逻辑分析仪对该协议进行分析,发现波形比较美观,SCL 的频率在70KHz左右(11.0592M晶振),低于标准的100K,可以适应大多数的I2C器件。
如果感觉速度过快或过慢,可以自行修改延时。
希望可以给读者一个参考,给读者一些帮助!*//*i2c.h文件 */#ifndef __I2C_H_#define __I2C_H_sbit SCL = P2^1;sbit SDA = P2^0;void start_i2c(); //启动I2C总线:SCL高电平期间,SDA由高变低void stop_i2c(); //停止I2C总线:SCL高电平期间,SDA由低变高void send_i2c(unsigned char c); //主机发送一个字节,先发送最高位unsigned char receive_i2c(); //主机接收一个字节,先接收最高位void master_ack(bit ack); //主机非应答信号(填参数0)或应答信号(填参数1)void slave_ack(); //等待从机应答信号#endif/* i2c.c文件 */#include#include#include#define nop() _nop_()void start_i2c() //启动I2C总线:SCL高电平期间,SDA由高变低{SDA=1;SCL=1;nop();nop();nop();nop();SDA=0;SCL=0;}void stop_i2c() //停止I2C总线,SCL高电平期间,SDA由低变高{SDA=0;SCL=1;nop();nop();nop();nop();SDA=1;}void slave_ack() //等待从机应答信号,如果从机迟迟没有应答,则结束总线。
详细讲解RT-Thread I2C设备驱动框架及相关函数

详细讲解RT-Thread I2C设备驱动框架及相关函数本应用笔记以驱动I2C接口的6轴传感器MPU6050为例,说明了如何使用I2C设备驱动接口开发应用程序,并详细讲解了RT-Thread I2C设备驱动框架及相关函数。
1 本文的目的和结构1.1 本文的目的和背景I2C(或写作i2c、IIC、iic)总线是由Philips公司开发的一种简单、双向二线制(时钟SCL、数据SDA)同步串行总线。
它只需要两根线即可在连接于总线上的器件之间传送信息,是半导体芯片使用最为广泛的通信接口之一。
RT-Thread中引入了I2C设备驱动框架,I2C 设备驱动框架提供了基于GPIO模拟和硬件控制器的2种底层硬件接口。
1.2 本文的结构本文首先描述了RT-Thread I2C设备驱动框架的基本情况,然后详细描述了I2C设备驱动接口,并使用I2C设备驱动接口编写MPU6050的驱动程序,并给出了在正点原子STM32F4探索者开发板上验证的代码示例。
2 I2C设备驱动框架简介在使用MCU进行项目开发的时候,往往需要用到I2C总线。
一般来说,MCU带有I2C 控制器(硬件I2C),也可以使用MCU的2个GPIO自行编写程序模拟I2C总线协议实现同样的功能。
RT-Thread提供了一套I/O设备管理框架,它把I/O设备分成了三层进行处理:应用层、I/O 设备管理层、底层驱动。
I/O设备管理框架给上层应用提供了统一的设备操作接口和I2C 设备驱动接口,给下层提供的是底层驱动接口。
应用程序通过I/O设备模块提供的标准接口访问底层设备,底层设备的变更不会对上层应用产生影响,这种方式使得应用程序具有很好的可移植性,应用程序可以很方便的从一个MCU移植到另外一个MCU。
本文以6轴惯性传感器MPU6050为例,使用RT-Thread I2C设备驱动框架提供的GPIO模拟I2C控制器的方式,阐述了应用程序如何使用I2C设备驱动接口访问I2C设备。
TI CC2541 I2C 不稳定的解决方法

TI CC2541 I2C 不稳定的解决方法最近用CC2541 开发一个设备,用它自带的硬件I2C, 发现很不稳定,很烦恼。
于是自己写了一个软件I2C ,解决了问题。
贡献给大家,共勉。
//-----------------------------------------------------------------------------// Includes//-----------------------------------------------------------------------------#include "common.h"#include "I2C.h"#include <ioCC2541.h>/* ------------------------------------------------------------------------------------------------* Constants* ------------------------------------------------------------------------------------------------*/// I2CWC#define I2C_OVR BV(7) // 1: GPIO functionality.0: I2C functionality#define I2C_SCLPUE BV(3) //SCL pin pullup enable#define I2C_SDAPUE BV(2) //SDA pin pullup enable.#define I2C_SCLOE BV(1) //SCL pin output enable#define I2C_SDAOE BV(0) //SDA pin output enable// I2CIO#define I2C_SCLD BV(1) //SCL data value#define I2C_SDAD BV(0) //SDA data value#define SDA_0 I2CIO &= ~I2C_SDAD //SDA=0#define SDA_1 I2CIO |= I2C_SDAD //SDA=1#define SCL_0 I2CIO &= ~I2C_SCLD //SCL=0#define SCL_1 I2CIO |= I2C_SCLD //SCL=1#define SDA_IN I2CWC &= ~I2C_SDAOE //SDA INPUT#define SDA_OUT I2CWC |= I2C_SDAOE //SDA OUTPUT#define SCL_IN I2CWC &= ~I2C_SCLOE //SCL INPUT#define SCL_OUT I2CWC |= I2C_SCLOE //SCL OUTPUT#define I2C_GPIO I2CWC = 0x80; //1: I2C GPIO//***************************************************************************** ******//*名称:i2c_send_noack()*//*功能:无应答I2C总线*//*参数:无*//*返回:1 有NOACK信号0 无NOACK信号*//***************************************************************************** ******voidsend_noack(){SDA_OUT; //开路输出,SDA_1; //SDA = 1; NO ACKasm("nop");SCL_1; //SCL = 1;asm("nop");SCL_0; //SCL = 0; //START}// iic应答for slavervoidsend_ack() {SDA_OUT; //开路输出,SDA_0; //OUT 0 ACKasm("nop");SCL_1;asm("nop");SCL_0;}/**停止iic*/static void stop(){SDA_OUT; //开路输出,并输出0.SCL_0; //SCL = 0;asm("nop");SCL_1; //SCL = 1; STOPasm("nop");SDA_1; //SDA = 1;SDA_IN;SCL_IN;}/** 启动iic*/// static void start() {static void start(){SDA_OUT; //开路输出,并输出0.SCL_OUT;SDA_1; //SDA = 1;SCL_1; //SCL = 1;asm("nop");SDA_0; //SDA = 0;asm("nop");SCL_0; //SCL = 0; //START}/** iic写一个字节*/voidiic_write(uint8 datIn) {uint8dat, j;dat = datIn;SDA_OUT;for (j = 0; j < 8; j++) {if((dat& 0x80)) SDA_1;else SDA_0;asm("nop"); asm("nop"); asm("nop");SCL_1; //write TDOS_SDA begin asm("nop");dat<<= 1;SCL_0; //write TDOS_SDA end }}boolcheck_ack() {boolack_flag;SDA_IN; //开路输入,asm("nop");SCL_1; //read ask beginasm("nop");if((I2CIO & I2C_SDAD) ==1){ //if (SDA==1)ack_flag = 0; //1: err}else{ack_flag = 1; //0: ok}SCL_0; //read ask endreturnack_flag;}/** iic读一个字节*/uint8 iic_read() {uint8 j, dat = 0;SDA_IN; //开路输入,for (j = 0; j < 8; j++) {SCL_1; //read TDOS_SDA begin. delay 0.7usdat<<= 1;asm("nop"); asm("nop"); asm("nop");if((I2CIO & I2C_SDAD) ==1){ //if (SDA==1)dat |= 0x01; //input TDOS_SDA}SCL_0; //read TDOS_SDA end. delay 1.4us }returndat;}/** 通过I2C总线向某一寄存器写入一个字节数据*/void I2C_write_byte(uint8 I2C_addr, uint8 Raddr, uint8 dat) { start(); //发启动信号iic_write(I2C_addr | 0X00); //WRITE i2cif (check_ack()==0) {goto err;}iic_write(Raddr); //发送寄存器地址if (check_ack()==0) {goto err;}iic_write(dat); //发送数据字节if (check_ack()==0) {goto err;}err:stop();}/** 通过I2C总线读出某一寄存器的数据*/uint8 I2C_read_byte(uint8 I2C_addr, uint8 Raddr) { uint8dat;start();iic_write(I2C_addr | 0X00); //WRITE i2cif (check_ack()==0) {goto err;}iic_write(Raddr); //TDOS'registerif (check_ack()==0) {goto err;}start(); //重发起动信号iic_write(I2C_addr | 0X01); //READif (check_ack()==0) {goto err;}dat = iic_read(); //接收读出的数据send_noack();err:stop();returndat;}/** 通过I2C总线读出某一寄存器的数据*/uint32 I2C_read_3byte(uint8 I2C_addr, uint8 Raddr) { uint8 dat1,dat2,dat3;start();iic_write(0X98 | 0X00); //WRITE i2cif (check_ack()==0) {goto err;}iic_write(0X00); //TDOS'registerif (check_ack()==0) {goto err;}start(); //重发起动信号iic_write(0X98 | 0X01); //READif (check_ack()==0) {goto err;}dat1 = iic_read(); //接收读出的数据send_ack();dat2 = iic_read(); //接收读出的数据send_ack();dat3 = iic_read(); //接收读出的数据send_noack();err:stop();return (dat1<<16) | (dat2<<8) | dat3;}//----------------------------------------------------------------------------- // End Of File//---------------。
防止gpio模拟iic驱动被其他线程打断的方法

防止gpio模拟iic驱动被其他线程打断的方法防止GPIO模拟I2C驱动在多线程环境下被打断是一个重要的问题。
在这篇文章中,我将介绍一些方法来解决这个问题,以确保GPIO模拟I2C驱动的稳定性和可靠性。
首先,让我们了解一下什么是GPIO和I2C。
GPIO是通用输入输出端口,它可以用来控制外部设备或读取外部设备的状态。
而I2C是一种通信协议,它可以用于连接和控制多个设备,通过两根线进行数据传输。
在使用GPIO模拟I2C驱动时,我们需要保证驱动程序能够正确地处理并发访问和时序要求。
为了实现这一点,我们可以采取以下几个步骤:1. 锁定访问:在GPIO模拟I2C驱动中,我们可以使用信号量或互斥锁来实现对共享资源的访问控制。
当一个线程访问I2C总线时,它可以获得锁,阻止其他线程同时访问。
2. 设置优先级:在多线程环境中,我们可以通过设置线程的优先级来控制它们的执行顺序。
将GPIO模拟I2C驱动的线程设置为较高的优先级,可以确保它能够及时地响应,并且不会被低优先级的线程打断。
3. 中断处理:在一些特殊情况下,我们可能需要使用中断来处理GPIO模拟I2C驱动的数据请求。
通过配置中断处理程序,我们可以在需要时及时响应外部设备的请求,而不会被其他线程的操作打断。
4. 错误处理:在GPIO模拟I2C驱动中,我们应该实现错误处理机制,以便在发生错误时进行适当的处理。
例如,在发送或接收数据时发生错误,我们可以采取一些补救措施,如重新发送或重新接收数据,以确保数据的可靠性。
综上所述,要防止GPIO模拟I2C驱动在多线程环境下被打断,我们可以采取一系列的措施来确保驱动程序的稳定性和可靠性。
通过锁定访问、设置优先级、中断处理和错误处理等方法,我们可以保证GPIO模拟I2C驱动能够正确地处理并发访问和时序要求,从而实现可靠的数据传输和外设控制。
希望本文能够对需要实现GPIO模拟I2C驱动的开发者有所帮助,并能够在实际应用中发挥指导作用。
LED驱动芯片集锦

T6315A 草坪灯 规格书
T6317A MR16-1W 7-24V 350mA 1W多颗驱动IC 规格书
美国灿瑞科技公司 15
美商茂力公司(MPS) 16
美国CATALYST 16
欧洲英国IXYS半导体公司 17
美国迈瑞半导体公司 17
欧洲部分: 17
德国英பைடு நூலகம்凌 17
奥地利微电子 17
NXP 荷兰皇家飞利浦公司I&SUP2;C LED 显示控制 17
NXP 荷兰皇家飞利浦公司 高功率系统用 SMPS 芯片 17
台湾台晶科技
T6309A 手机背光 规格书
T6309B 手机背光 规格书
AMC7140 5-50V DC&DC 最大500mA电流可调,1颗或多颗LED驱动IC 规格书
AMC7150 5-24V DC&DC 最大1.5A固定式, 1-3颗LED驱动IC 规格书
AMC7169 LED保护IC 规格书
台湾聚积科技公司
MBI1801 1路恒流驱动1.2A电流可设定PWM信号灰度调节 规格书
MBI1802 2路恒流驱动360mA电流可两路单独设定PWM信号灰度调节 规格书
MBI1804 4路恒流驱动240mA电流可设定PWM信号灰度调节 规格书
T6325A MR16-3/5W 7-24V 700mA 多颗LED驱动IC 规格书
ON 安森美半导体 7
美国超科公司 (SUPERTEX) 7
TI 美国德州仪器公司 屏幕驱动部分 8
TI 美国德州仪器公司 白光LED驱动器 8
美国美信集成产品公司 白光LED驱动器 9
I2C是什么,什么类型设备支持I2C,为什么要使用它?

I2C 是什么,什么类型设备支持I2C,为什么要使用
它?
我相信互联网搜索引擎可为我提供可靠、快速的答案,因此当我第一次遇到I2C 协议时,我首先寻求互联网搜索引擎获得帮助。
我的搜索给出如下响应:内部集成电路(I2C)协议是双向双线串行总线,其提供集成电路之间的通信链路。
这一解释已经很清楚了,但我还有更多的问题:它究竟是什幺?什幺类型的设备使用I2C?I2C 如何帮我解决系统中遇到的实际问题?
I2C 是使主设备(例如处理器,微控制器(MCU)或专用集成电路(ASIC))能够与同一双线总线上的其它外围设备通信的流行通信协议。
一
条线专用于数据传输,而另一条用于时钟信号。
想象它就像一个双车道公路:每个车道都有汽车从一端流向另一端,就像数据包将从主设备(处理器、MCU、ASIC)传输到外围设备(温度传感器、湿度传感器及其它设备)。
那I2C 到底是什幺呢现在,为什幺要使用它?I2C 可以在同一总线上轻松
实现多个外设- 例如,使用各种传感器来监视服务器的温度。
I2C 协议实际上设计用于在单个总线上支持多个设备,而如串行外设接口(SPI)的其他协议的设计用于点对点单设备支持。
双线I2C 接口还可以帮助简化对四线SPI
接口的布线,并减少通用输入/输出(GPIO)。
I2C总线8位远程IO扩展口芯片PCF8574的驱动程序

//......................................//名称: PCF8574(A).c I2C扩展8位I/O芯片的接口程序//编程: 不详//日期: 20111025////发现问题请指点,谢谢!//......................................//CPU: 89C55 11.0592MHz//环境:KeilC51 V8.01//引脚定义://CPU_P2.0--- P CF8574X_SC L 时钟// CP U_P2.1 ---PCF8574X_SDA 数据//CPU_P2.2 --- PC F8574X_INT中断//......................................#incl ude <Publi c.h>#incl ude <Intri ns.h>#inc lude"dela y_s.h"#in clude "pcf8574.h"//PCF8574(A)芯片指令的定义#defi ne PC F8574_WRIT E 0x40 //器件地址= 0111 A2 A1 A0r/w#defin e PCF8574_READ0x41//器件地址= 0111 A2 A1A0 r/w#de finePCF8574A_W RITE0x70//器件地址= 0111 A2 A1A0 r/w#de finePCF8574A_R EAD 0x71 //器件地址= 0111 A2 A1 A0 r/w#de fineP CF8574X_R EGIST ER_AD DR_MA X 7 //器件内部寄存器地址的最大值//内部函数s tatic void i2c_star t_con d(voi d);s tatic void i2c_stop_cond(void);st aticuchar i2c_read_byte(void);sta tic u chari2c_r ead_b yte_n ack(v oid);stat ic vo id i2c_wr ite_b yte(u charda);//============================================================== ===============//接口调用函数部分//*******************************************************//序号:// HD_PC F8574X_S01//功能://读出芯片的复位状态// is_pcf8574a=1 是A芯片// ad d_of_part器件的子地址 0~3//输出://端口的数据//********************************************************uch ar PC F8574X_rea d_io(uchar is_p cf8574a, u charadd_o f_par t){uchar i;i2c_s tart_cond();i f(is_pcf8574a !=0){i2c_wr ite_b yte(P CF8574A_RE AD |((add_of_pa rt <<1) &0x0E));//器件地址=0111 A2 A1 A0 r/w}else{i2c_write_byte(PCF8574_R EAD |((add_of_p art <<1) &0x0E));//器件地址=0100 A2 A1A0 r/w}i =i2c_re ad_by te_na ck();//顺序读的方式读出一个字节i2c_st op_co nd();ret urn(i);}//*******************************************************//序号:// H D_PCF8574X_S02//功能://写数据到I/O端口//输入://is_pcf8574a =1 是A芯片//add_of_p art:器件的子地址 0~7//dat:写入的字节//输出: // 无//********************************************************voidPCF8574X_w rite_io(uc har i s_pcf8574a, uch ar ad d_of_part, ucha r dat){i2c_s tart_cond();i f(is_pcf8574a !=0){i2c_wr ite_b yte(P CF8574A_WR ITE |((add_of_p art <<1) &0x0E)); //器件地址=0111A2 A1 A0 r/wel se{i2c_wri te_by te(PC F8574_WRIT E |((add_o f_par t <<1) &0x0E));//器件地址=0100 A2 A1 A0 r/w}i2c_write_byte(dat);i2c_st op_co nd();}//==============//内部调用函数部分//==============//----------------------------------------------//I2C发启始条件:时钟线为高时数据线发生下降沿跳变//----------------------------------------------sta tic v oid i2c_st art_c ond(v oid){CO DE_SC L_LOW;_D ELAY_NOP3;COD E_SDA_HIGH;_D ELAY_NOP3;COD E_SCL_HIGH;_D ELAY_NOP3;COD E_SDA_LOW;_DE LAY_N OP3;}//----------------------------------------//I2C 发结束条件:时钟线为高时数据线发生上升沿跳变//----------------------------------------st aticvoidi2c_s top_c ond(v oid){CO DE_SC L_LOW;_D ELAY_NOP3;COD E_SDA_LOW;_DE LAY_N OP3;CODE_SCL_HIGH;_DE LAY_N OP3;CODE_SDA_HIGH;_DE LAY_N OP3;}//----------------------------------------// I2C 读取一个中间字节的数据//----------------------------------------/*stat ic uc har i2c_re ad_by te(vo id){uch ar i;uch ar da=0;for(i =0;i<8;i++){da <<=1; //传输的数据高位在前C ODE_S CL_LO W;_DELA Y_NOP3;CODE_SCL_H IGH;//时钟为高时读数据//N OP3;if(JUDG E_PCF8574X_SDA) da++;}CODE_SCL_LOW;_DEL AY_NO P3;CODE_SDA_L OW; //发送应答位_DELA Y_NOP3;C ODE_S CL_HI GH;_DELA Y_NOP3;C ODE_S CL_LO W;_DELAY_NOP3;CO DE_SD A_HIG H;r eturn(da);}*///----------------------------------------// I2C读取一个结尾字节的数据//----------------------------------------stat ic uc har i2c_re ad_by te_na ck(vo id){uch ar i;uch ar da =0;for(i =0; i<8; i++){da<<=1;CO DE_SC L_LOW;_DELAY_NOP3;C ODE_S CL_HI GH;//NOP3;i f(JUD GE_PC F8574X_SDA) da++;}COD E_SCL_LOW;_DE LAY_N OP3;CODE_SDA_HIGH;_DE LAY_N OP3;CODE_SCL_HIGH;_DE LAY_N OP3;CODE_SCL_LOW;retu rn( d a );}//----------------------------------------// I2C 写入一个字节的数据//----------------------------------------stat ic vo id i2c_wri te_by te(uc har d a ){uch ar i;for(i =0; i<8; i++){COD E_SCL_LOW;if(da&0x80){COD E_SDA_HIGH;}el se{CODE_SDA_L OW;}CODE_SCL_H IGH;da<<=1;}CODE_SCL_L OW; //第8个SCL下降沿,写入8位数据_DELA Y_NOP3;C ODE_S DA_HI GH;_DELA Y_NOP3;C ODE_S CL_HI GH;}//============================================================== ===============//End O f Fil e。
Linux下基于I2C的电源管理芯片驱动设计

0 引 言
内部 集 成 电路 (ne—ne rtd crut 2 itritg ae i i c ,IC)
12 IC 总 线 信 号 时序 . 2
S DA 和 S L2条 信 号 线 都 处 于 高 电平 ,即 总 线 C 空 闲状 态 , 2条 信 号 线 各 自的 上 拉 电阻 把 电平 拉 高 ;
( tritgae i ut u d r iu . h 2 u miga dtese il rhtcueo eICb s nte n xk re ae i e— e rtdcr i n e n x T eICb s i n n p ca ac i tr fh 2 u u en l r n n c ) L t h e t i h Li
23 I C设 备 驱 动 . 2
CON Dn1 oN
图 1 IC总 线起 始 信 号 与结 束信 号【 2
定 义 描 述 具 体 设 备 的 IC cin 2 l t和 可 能 的私 有 e 数 据 结 构 、借 助 IC 框 架 的 IC pr be 函 数 实 现 注 2 2 o
S
‘ 、
.
源 转 换 输 出 的应 用 ,提 供 简 单 易 用 而 又 可 以灵 活 配 置 的完 整 电源 解 决 方 案 , 充 分 满 足 目前 日益 复 杂 的 应 用 处 理器 系 统 对 于 电源 相 对 复 杂 而 精 确 控 制 的要 求 。AXP 9 提 供 了一 个 与主 机 通 讯 的 两 线 串行 通 12
接 收 端 接 收 完 一 个 字 节 后 , 会 立 刻 在 AC 周 期 内 K
1 IC总线 概 述 与时序 2
11 IC 总 线 介 绍 . 2
将 S DA 由高 电平 翻 转 为低 电 平 ,这 便 产 生 了 一 个
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
TI-I2C驱动
一、与I2C驱动相关的文件分成两部分:
1)应用层接口部分:
程序在svn中的路径如下:
在https://dareglob-971006/svn/eocOS/branches/eocOS_v4/branches/bsp/user/i2c目录下,i2ctest.c文件,提供了lm75a_temp_read()方法,用来读取LM75A设备温度寄存器中的温度信息的功能。
2)内核驱动部分:
内核位于svn中的路径如下:
https://dareglob-971006/svn/eocOS/branches/eocOS_v4/branches/bsp/kernel
(1)总线驱动:
i2c-davinci.c:在内核目录中driver/i2c/busses目录下,适用于TI的I2C总线驱动程序。
I2C总线驱动是对I2C硬件体系结构中适配器端的实现。
(2)I2C驱动代码核心:
i2c-core.c:在内核目录中driver/i2c/目录下,是I2C代码的核心,用于沟通虚拟文件系统与底层实现。
该文件提供了I2C总线驱动和设备驱动的注册、注销方法,I2C通信方法上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。
(3)I2C设备驱动:
lm75.c:在内核目录中driver/hwmon目录下,是针对LM75A以及其他能兼容的温度传感器的设备驱动。
I2C设备驱动是对I2C硬件体系结构中设备端的实现,设备一般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。
二、I2C简要工作流程
1)在总线驱动初始化时候,当通过Linux内核源代码/driver/base/platform.c文件中定义platform_driver_register()函数注册platform_driver结构体时,其中probe指针指向的davinci_i2c_probe()函数将被调用,以初始化适配器硬件。
2)而davinci_i2c_remove()函数则完成与davinci_i2c_probe()相反的功能。
用于内存和中断等系统资源的释放和注销。
3)总线驱动i2c-davinci.c中,定义了i2c_davinci_xfer函数。
该函数是I2C总线通信传输函数。
并且I2C适配器对应的i2c_algorithm结构体实例为i2c_davinci_algo,其中的master_xfer函数指针指向i2c_davinci_xfer函数。
4)当设备被打开,并且用户开始读操作时,会调用设备驱动lm75.c中show_temp()函数,该函数会调用i2c-core.c中的i2c_smbus_xfer()函数,i2c_smbus_xfer()函数会检查适配器对应的i2c_algorithm结构体中是否注册了smbus_xfer函数(目前i2c_davinci_algo中未注册smbus_xfer函数),程序会调用i2c_smbus_xfer_emulated()函数,最终,还是会调用标准的I2C总线通信函数master_xfer(),由于master_xfer 已经指向i2c_davinci_xfer函数,所以会调用总线驱动i2c-davinci.c中的i2c_davinci_xfer函数来读取信息。
三、接口函数
1)应用层接口:
Int lm75a_temp_read(float *temp) 读取lm75a 温度
2)内核中:lm75.c文件
static ssize_t show_temp(struct device *dev, struct device_attribute *da,char *buf)
当应用层开始读操作时,内核中会调用show_temp()函数,该函数最终会调用master_xfer()函数来获取数据。
四、修改记录
1)i2c-davinci.c:davinci_i2c_remove函数中,
- free_irq(IRQ_I2C, dev);
+ free_irq(dev->irq, dev);
2)lm75.c:
-static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
-0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
+ static const unsigned short normal_i2c[] = { 0x48,I2C_CLIENT_END };
+ #define LM75A_ID 0xA1
lm75_detect()函数中,主要增加了对LM75A的检查,
if (i2c_smbus_read_byte_data(new_client, 7) == LM75A_ID) {
/* LM75A returns 0xff on unused registers so
just to be sure we check for that too. */
if (i2c_smbus_read_byte_data(new_client, 4) != 0xff
|| i2c_smbus_read_byte_data(new_client, 5) != 0xff
|| i2c_smbus_read_byte_data(new_client, 6) != 0xff)
return -ENODEV;
is_lm75a = 1;
hyst = i2c_smbus_read_byte_data(new_client, 2);
os = i2c_smbus_read_byte_data(new_client, 3);
}
3)lm75.h:
- return ((s16)reg / 128) * 500;
+ return reg;
3)kernel根目录下,.config文件:
+ CONFIG_HWMON=y
+ CONFIG_SENSORS_LM75=y。