使用E2PROM可能被误认为是开启信号波形合成误差分析吗

51单片机——EEPROM
单片机——E2PROM
宗旨:技术的学习是有限的,分享的精神是无限的。
24C02:256 个字节的 EEPROM。一般情况下,EEPROM 拥有 30 万到 100 万次的寿命。基于 I2C 通信协议的器件。I2C 是一个通信协议,它拥有严密的通信时序逻辑要求,而EEPROM 是一个器件,只是这个器件采样了 I2C 协议的接口与单片机相连而已,二者并没有必然的联系,EEPROM 可以用其它接口, I2C 也可以用在其它很多器件上。
1、EEPROM写数据流程
第一步,首先是 I2C 的起始信号,接着跟上首字节,也就是我们前边讲的 I2C 的器件地
址,并且在读写方向上选择“写”操作。
第二步,发送数据的存储地址。24C02一共 256 个字节的存储空间,地址从 0x00~0xFF,我们想把数据存储在哪个位置,此刻写的就是哪个地址。
第三步,发送要存储的数据第一个字节、第二个字节,,,,注意在写数据的过程中,
EEPROM 每个字节都会回应一个“应答位 0”,来告诉我们写 EEPROM 数据成功,如果没有回应答位,说明写入不成功。
在写数据的过程中,每成功写入一个字节,EEPROM 存储空间的地址就会自动加 1,当加到 0xFF 后,再写一个字节,地址会溢出又变成了 0x00。
2、EEPROM读数据流程
第一步,首先是 I2C 的起始信号,接着跟上首字节,也就是我们前边讲的 I2C 的器件地址,并且在读写方向上选择“写”操作。这个地方可能有同学会诧异,我们明明是读数据为何方向也要选“写”呢?刚才说过了,24C02 一共有 256 个地址,我们选择写操作,是为了把所要读的数据的存储地址先写进去,告诉 EEPROM 我们要读取哪个地址的数据。这就如同我们打电话,先拨总机号码(EEPROM 器件地址),而后还要继续拨分机号码(数据地址),而拨分机号码这个动作,主机仍然是发送方,方向依然是“写”。
第二步,发送要读取的数据的地址,注意是地址而非存在EEPROM 中的数据,通知EEPROM 我要哪个分机的信息。
第三步,重新发送 I2C 起始信号和器件地址,并且在方向位选择“读”操作。
这三步当中,每一个字节实际上都是在“写”,所以每一个字节EEPROM 都会回应一个“应答位 0”。
第四步,读取从器件发回的数据,读一个字节,如果还想继续读下一个字节,就发送一个“应答位ACK(0)”,如果不想读了,告诉 EEPROM,我不想要数据了,别再发数据了,那就发送一个“非应答位NAK(1)”。
和写操作规则一样,我们每读一个字节,地址会自动加 1,那如果我们想继续往下读,给EEPROM 一个 ACK(0)低电平,那再继续给 SCL 完整的时序,EEPROM 会继续往外送数据。如果我们不想读了,要告诉 EEPROM 不要数据了,那我们直接给一个NAK(1)高电平即可。这个地方大家要从逻辑上理解透彻,不能简单的靠死记硬背了,一定要理解明白。梳理一下几个要点: A、在本例中单片机是主机,24C02 是从机; B、无论是读是写, SCL 始终都是由主机控制的; C、写的时候应答信号由从机给出,表示从机是否正确接收了数据;
D、读的时候应答信号则由主机给出,表示是否继续读下去。
#include &reg52.h&
extern void I2CStart();
extern void I2CStop();
extern unsigned char I2CReadACK();
extern unsigned char I2CReadNAK();
extern bit I2CWrite(unsigned char dat);
/* E2读取函数,buf-数据接收指针,addr-E2中的起始地址,len-读取长度 */
void E2Read(unsigned char *buf, unsigned char addr, unsigned char len)
//用寻址操作查询当前是否可进行读写操作
I2CStart();
if(I2CWrite(0x50 && 1)) //应答则跳出循环,非应答则进行下一次查询
I2CStop();
I2CWrite(addr);
//写入起始地址
I2CStart();
//发送重复启动信号
I2CWrite((0x50 && 1) | 0x01); //寻址器件,后续为读操作
while (len & 1)
//连续读取len-1个字节
*buf++ = I2CReadACK(); //最后字节之前为读取操作+应答
*buf = I2CReadNAK();
//最后一个字节为读取操作+非应答
I2CStop();
/* E2写入函数,buf-源数据指针,addr-E2中的起始地址,len-写入长度 */
void E2Write(unsigned char *buf, unsigned char addr, unsigned char len)
while (len & 0)
//等待上次写入操作完成
//用寻址操作查询当前是否可进行读写操作
I2CStart();
if(I2CWrite(0x50 && 1)) //应答则跳出循环,非应答则进行下一次查询
I2CStop();
//按页写模式连续写入字节
I2CWrite(addr);
//写入起始地址
while(len & 0)
I2CWrite(*buf++);
//写入一个字节数据
//待写入长度计数递减
//E2地址递增
if ((addr & 0x07) == 0) //检查地址是否到达页边界,24C02每页8字节,
//所以检测低3位是否为零即可
//到达页边界时,跳出循环,结束本次写操作
I2CStop();
看过本文的人也看了:
我要留言技术领域:
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?51单片机控制24C02串行E2PROM的读写_电子技术_中国百科网
51单片机控制24C02串行E2PROM的读写
    
  I2C总线是一种用于IC器件之间连接的二线制总线。它通过SDA(串行数据线)及SCL(串行时钟线)两根线在连到总线上的器件之间传送信息,并根据地址识别每个器件:不管是单片机、存储器、LCD驱动器还是键盘接口。  1.I2C总线的基本结构 采用I2C总线标准的单片机或IC器件,其内部不仅有I2C接口电路,而且将内部各单元电路按功能划分为若干相对独立的模块,通过软件寻址实现片选,减少了器件片选线的连接。CPU不仅能通过指令将某个功能单元电路挂靠或摘离总线,还可对该单元的工作状况进行检测,从而实现对硬件系统的既简单又灵活的扩展与控制。I2C总线接口电路结构如图1所示。
2.双向传输的接口特性 传统的单片机串行接口的发送和接收一般都各用一条线,如MCS51系列的TXD和RXD,而I2C总线则根据器件的功能通过软件程序使其可工作于发送或接收方式。当某个器件向总线上发送信息时,它就是发送器(也叫主器件),而当其从总线上接收信息时,又成为接收器(也叫从器件)。主器件用于启动总线上传送数据并产生时钟以开放传送的器件,此时任何被寻址的器件均被以为是从器件。I2C总线的控制完全由挂接在总线上的主器件送出的地址和数据决定。在总线上,既没有中心机,也没有优先机。  总线上主和从(即发送和接收)的关系不是一成不变的,而是取决于此时数据传送的方向。SDA和SCL均为双向I/O线,通过上拉电阻接正电源。当总线空闲时,两根线都是高电平。连接总线的器件的输出级必须是集电极或漏极开路,以具有线“与”功能。I2C总线的数据传送速率在标准工作方式下为100kbit/s,在快速方式下,最高传送速率可达400kbit/s。  3.I2C总线上的时钟信号 在I2C总线上传送信息时的时钟同步信号是由挂接在SCL时钟线上的所有器件的逻辑“与”完成的。SCL线上由高电平到低电平的跳变将影响到这些器件,一旦某个器件的时钟信号下跳为低电平,将使SCL线一直保持低电平,使SCL线上的所有器件开始低电平期。此时,低电平周期短的器件的时钟由低至高的跳变并不能影响SCL线的状态,于是这些器件将进进高电同等待的状态。  当所有器件的时钟信号都上跳为高电平时,低电平期结束,SCL线被开释返回高电平,即所有的器件都同时开始它们的高电平期。其后,第一个结束高电平期的器件又将SCL线拉成低电平。这样就在SCL线上产生一个同步时钟。可见,时钟低电平时间由时钟低电平期最长的器件确定,而时钟高电平时间由时钟高电平期最短的器件确定。  4.数据的传送 在数据传送过程中,必须确认数据传送的开始和结束。在I2C总线技术规范中,开始和结束信号(也称启动和停止信号)的定义如图2所示。当时钟线SCL为高电平时,数据线SDA由高电平跳变为低电平定义为“开始”信号;当SCL线为高电平时,SDA线发生低电平到高电平的跳变为“结束”信号。开始和结束信号都是由主器件产生。在开始信号以后,总线即被以为处于忙状态;在结束信号以后的一段时间内,总线被以为是空闲的。
I2C总线的数据传送格式是:在I2C总线开始信号后,送出的第一个字节数据是用来选择从器件地址的,其中前7位为地址码,第8位为方向位(R/W)。方向位为“0”表示发送,即主器件把信息写到所选择的从器件;方向位为“1”表示主器件将从从器件读信息。开始信号后,系统中的各个器件将自己的地址和主器件送到总线上的地址进行比较,假如与主器件发送到总线上的地址一致,则该器件即为被主器件寻址的器件,其接收信息还是发送信息则由第8位(R/W)确定。  在I2C总线上每次传送的数据字节数不限,但每一个字节必须为8位,而且每个传送的字节后面必须跟一个认可位(第9位),也叫应答位(ACK)。数据的传送过程如图3所示。每次都是先传最高位,通常从器件在接收到每个字节后都会作出响应,即开释SCL线返回高电平,预备接收下一个数据字节,主器件可继续传送。假如从器件正在处理一个实时势件而不能接收数据时,(例如正在处理一个内部中断,在这个中断处理完之前就不能接收I2C总线上的数据字节)可以使时钟SCL线保持低电平,从器件必须使SDA保持高电平,此时主器件产生1个结束信号,使传送异常结束,迫使主器件处于等待状态。当从器件处理完毕时将开释SCL线,主器件继续传送。
当主器件发送完一个字节的数据后,接着发出对应于SCL线上的一个时钟(ACK)认可位,在此时钟内主器件开释SDA线,一个字节传送结束,而从器件的响应信号将SDA线拉成低电平,使SDA在该时钟的高电平期间为稳定的低电平。从器件的响应信号结束后,SDA线返回高电平,进进下一个传送周期。  I2C总线还具有广播呼唤地址用于寻址总线上所有器件的功能。若一个器件不需要广播呼唤寻址中所提供的任何数据,则可以忽略该地址不作响应。假如该器件需要广播呼唤寻址中提供的数据,则应对地址作出响应,其表现为一个接收器。  5.总线竞争的仲裁 总线上可能挂接有多个器件,有时会发生两个或多个主器件同时想占用总线的情况。例如,多单片机系统中,可能在某一时刻有两个单片机要同时向总线发送数据,这种情况叫做总线竞争。I2C总线具有多主控能力,可以对发生在SDA线上的总线竞争进行仲裁,其仲裁原则是这样的:当多个主器件同时想占用总线时,假如某个主器件发送高电平,而另一个主器件发送低电平,则发送电平与此时SDA总线电平不符的那个器件将自动封闭其输出级。总线竞争的仲裁是在两个层次上进行的。首先是地址位的比较,假如主器件寻址同一个从器件,则进进数据位的比较,从而确保了竞争仲裁的可靠性。由于是利用I2C总线上的信息进行仲裁,因此不会造成信息的丢失。  6. I2C总线接口器件 目前在视频处理、移动通讯等领域采用I2C总线接口器件已经比较普遍。另外,通用的I2C总线接口器件,如带I2C总线的单片机、RAM、ROM、A/D、D/A、LCD驱动器等器件,也越来越多地应用于计算机及自动控制系统中。&
AT24C02是美国ATMEL公司的低功耗CMOS串行EEPROM,它是内含256×8位存储空间,具有工作电压宽(2.5~5.5V)、擦写次数多(大于10000次)、写进速度快(小于10ms)等特点。
AT24C02的1、2、3脚是三条地址线,用于确定芯片的硬件地址。在AT89C51试验开发板上它们都接地,第8脚和第4脚分别为正、负电源。第5脚SDA为串行数据输进/输出,数据通过这条双向I2C总线串行传送,在AT89C51试验开发板上和单片机的P3.5连接。第6脚SCL为串行时钟输进线,在AT89C51试验开发板上和单片机的P3.6连接。SDA和SCL都需要和正电源间各接一个5.1K的电阻上拉。第7脚需要接地。
24C02中带有片内地址寄存器。每写进或读出一个数据字节后,该地址寄存器自动加1,以实现对下一个存储单元的读写。所有字节均以单一操纵方式读取。为降低总的写进时间,一次操纵可写进多达8个字节的数据。
这是将0600H地址中以下的8个数据写到24C02的01H为首址单元中往的汇编程序
SCL BIT P3.4;定义24C02的串行时钟线  SDA BIT P3.5;定义24C02的串行数据
LJMP STARTSTART:LCALL STAR;调用MOV R2,#08H;一个数占有8位MOV DPTR,#0600H;定义源数据的位置LOOP:MOV A,#00HMOVC A,@A+DPTRLCALL SDATALCALL ACKJC LOOPINC DPTRDJNZ R2,LOOP
LCALL STOP;调用停止子程序
STAR:SETB SDASETB SCLNOPNOPNOPNOPCLR SDANOPNOPNOPNOPCLR SCLRETSDATA:MOV R0,#08HLOOP0:RLC AMOV SDA,CNOPNOPSETB SCLNOPNOPNOPNOPCLR SCLDJNZ R0,LOOP0RETACK:SETB SDANOPNOPSETB SCLNOPNOPNOPNOPMOV C,SDACLR SCLRETSTOP:CLR SDANOPNOPNOPNOPSETB SCLNOPNOPNOPNOPSETB SDANOPNOPNOPNOPRETORG 0600HDB 0A0H,10H,01H,02H,03H,04H,05H,06HEND
读写子程序如下:
;写串行E2PROM子程序EEPW; R3=(命令1010+器件3位地址+读/写。 器件地址一个芯片,是000); (R4)=片内字节地址; (R1)=欲写数据存放地址指针; (R7)=连续写字节数nEEPW: MOV P1,#0FFH
  CLR  P1.0  ;发开始信号  MOV  A,R3  ;送器件地址  ACALL  SUBS  MOV  A,R4  ;送片内字节地址
ACALL SUBS
AGAIN: MOV A,@R1
  ACALL SUBS ;调发送单字节子程序INC   R1
  DJNZ  R7,AGAIN;连续写n个字节
  CLR    P1.0  ;SDA置0, 预备送停止信号
  ACALL DELAY ;延时以满足传输速率要求
  SETB   P1.1  ;发停止信号
  ACALL DELAY
  SETB   P1.0
SUBS: MOV R0,#08H ;发送单字节子程序
LOOP: CLR P1.1
  MOV  P1.0,
  SETB P1.1
  ACALL DELAY
  DJNZ R0,LOOP ;循环8次送8个bit
  CLR  P1.1
  ACALL DELAY
SETB P1.1
REP: MOV C,P1.0
  JC  REP  ;判应答到否,未到则&
  CLR  P1.1
DELAY: NOP
;读串行E2PROM子程序EEPR
;(R1)=欲读数据存放地址指针&
;; R3=(命令1010+器件3位地址+读/写。 器件地址一个芯片,是000)
;(R4)=片内字节地址
;(R7)=连续读字节数
EEPR: MOV P1,#0FFH
CLR  P1.0  ;发开始信号
MOV  A,R3  ;送器件地址
  ACALL SUBS   ;调发送单字节子程序MOV A,R4   ;送片内字节地址
  ACALL SUBS
  MOV P1,#0FFH&
  CLR P1.0   ;再发开始信号&
  MOV A,R3&
  SETB ACC.0  ;发读命令&
ACALL SUBS
MORE: ACALL SUBR
  MOV @R1,A
  INC R1
  DJNZ R7,MORE
  CLR P1.0
  ACALL DELAY
  SETB P1.1&
  ACALL DELAY
  SETB P1.0 ;送停止信号&
SUBR: MOV  R0,#08H ;接受单字节子程序
LOOP2: SETB  P1.1
  ACALL DELAY&
  MOV C,P1.0
  RLC &
  CLR P1.1
  ACALL DELAY
  DJNZ R0,LOOP2
  CJNE R7,#01H,LOW
  SETB P1.0  ;若是最后一个字节置A=1
  AJMP SETOK
LOW: CLR P1.0  ;否则置A=0
SETOK: ACALL DELAY
  SETB  P1.1
  ACALL DELAY
  CLR  P1.1
  ACALL DELAY
  SETB P1.0  ;应答毕,SDA置1
  程序中多处调用了DELAY子程序(仅两条NOP指令),这是为了满足I2C总线上数据传送速率的要求,只有当SDA数据线上的数据稳定下来之后才能进行读写(即SCL线发出正脉冲)。另外,在读最后一数据字节时,置应答信号为“1”,表示读操纵即将完成。
&&&& 欢迎转载,信息来自维库电子市场网(www.dzsc.com)&&来源:ks99
Copyright by ;All rights reserved.博客访问: 123062
博文数量: 62
博客积分: 2010
博客等级: 大尉
技术积分: 840
注册时间:
*By Neil Chiao ()
*转载请注明出处:
*欢迎到“新星湾()”指导
、I2C总线原理
I2CSDA SCL
&&&&&& I2CI2CI2CI2CCPUI2CI2CI2CI2CCPUEEPROM I2C .I2CI2CAT24C02
、IIC读写EEPROM原理
IIC/1SCLSDASCLSDA
1 IIC Start-Stop Signal
1.1.1 IICByte Write
2ByteIICByteEEPROMDATA
NOTEIICByteIICACKByte7801IICACKStartStop
2 IIC Byte Write
&&&&&& Write3
(1)GPIOIIC
(2)IICACKIICCLK
(3)IICDS IICSTATIICIICEEPROM
(4)ByteEEPROMACK
(5)ByteACK
(6)ByteEEPROM
(8)IIC StopIIC
3 IIC Write Operation
NOTEEEPROMIICDSRing bufferstopEEPROMEEPROMCPUpage write
NOTEEEPROMring bufferStopEEPROMWriteslvaddrACKACK
1.1.2 IICRandom Read
IICCurrent Address ReadRandom ReadSequential Read
IICRandom Read4CPUByte(IIC)Byte(EEPROM)IICCPUbyteCPUIICEEPROMACKACK
4 IIC Random Read Operation
Device Address
A0~A2EEPROMEEPROMdevice address3(A2A1A0)+word address(8)13
、Linux中的I2C驱动结构
2C驱动概述
I2C I2CI2Calgorithmi2c-core.cI2CI2CI2CI2C
I2CI2Ci2c_adapterI2Calgorithm
I2CI2CCPUI2CI2CCPUI2Ci2c_driveri2c_client
1i2c_adapter—I2C CPUI2C
2i2c_algorithm—I2CI2CI2C
3i2c_client—I2CI2C
4i2c_driver—I2CI2C
4include/linux/i2c.h
i2c_driveri2c_clienti2c_driveri2c_clientI2Ci2c_clienti2c_clienti2c i2c_driver i2c_clienti2c_driverattach_adapter()attach_adapter()clientclienti2c_clientadapteri2c_adapter driveri2c_driveri2c_adapterclient_register() i2c_driver detach_client()
i2c_adpater i2c_clientI2Ci2c_clienti2c_adpaterI2Ci2c_adpateri2c_clienti2c_adpateri2c_client
i2c.h4i2c_msg
struct i2c_msg {
&&&&&& __u16&&& /* slave address*/
&&&&&& __u16
#define I2C_M_TEN&&&&&&&&&&& 0x0010&&& /* this is a ten bit chip address */
#define I2C_M_RD&&&&&&&&&&&&& 0x0001&&& /* read data, from slave to master */
#define I2C_M_NOSTART&&&&&&&&&& 0x4000&&& /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR 0x2000&&& /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK&&& 0x1000&&& /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK&&&&&&&&&&&& 0x0800&&& /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN&&&&&&&& 0x0400&&& /* length will be first received byte */
&&&&&& __u16&&&&&&&&&&&& /* msg length&&&&&&&&&&&&&&&&&&&&&& */
&&&&&& __u8 *&&&&&&&&&&&& /* pointer to msg data&&&&&&&&&&&&&&&&& */
slave address
内核中的I2C驱动
Linuxdriversi2c
& i2c-core.c
I2C/proc/bus/i2c*
& i2c-dev.c
I2CI2C890255 i2c-%d (i2c-0, i2c-1, ..., i2c-10, ...)open()write()read()ioctl()close()
i2c-dev.cread()write()ioctl()I2CI2C
I2CRTCI2CEEPROM
I2CS3C2410I2Ci2c-s3c2410.c
I2Calgorithm
i2c-core.c
1adapterclient
int i2c_add_adapter(struct i2c_adapter *adap); //adapter
int i2c_del_adapter(struct i2c_adapter *adap);
int i2c_register_driver(struct module *, struct i2c_driver *); // (i2c_add_driver)
int i2c_del_driver(struct i2c_driver *driver);
int i2c_attach_client(struct i2c_client *client); //client
int i2c_detach_client(struct i2c_client *client);
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num);int i2c_master_send(struct i2c_client *client,const char *buf ,int count);int i2c_master_recv(struct i2c_client *client, char *buf ,int count);
i2c_transferI2CI2Ci2c_master_sendi2c_master_recvi2c_transferi2c_transferadap->algo->master_xfer(adap,msgs,num);i2c_algorithmmaster_xfer
i2c_algorithm
struct i2c_algorithm {
&&&&&& 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);
&&&&&& u32 (*functionality) (struct i2c_adapter *);
&&&&&& i2c_algorithmmaster_xfer()functionality()
2C驱动实例简析
S3C2410 I2Cat24E2PROME2PROM
at24drivers/i2c/chips/at24.c
static struct i2c_driver at24_driver = {
&&&&&& .driver = {
&&&&&&&&&&&&& .name = "at24",
&&&&&& &&&&&& .owner = THIS_MODULE,
&&&&&& .probe = at24_probe,&&&& //write, read
&&&&&& .remove = __devexit_p(at24_remove),
&&&&&& .id_table = at24_ids,
static int __init at24_init(void)
&&&&&& io_limit = rounddown_pow_of_two(io_limit);
&&&&&& return i2c_add_driver(&at24_driver);
module_init(at24_init);&&&&&&&&& //at24
&&&&&& at24_probe
&&&&&& static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
&&&&&& struct at24_platform_
&&&&&& mutex_init(&at24->lock);
&&&&&& at24->use_smbus = use_
&&&&&& at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR;
&&&&&& at24->bin.read = at24_bin_&&&&&&&&&& //read
if (writable) {
&&&&&&&&&&&&& if (!use_smbus || i2c_check_functionality(client->adapter,
&&&&&&&&&&&&&&&&&&&&&&&&&&& I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
&&&&&&&&&&&&&&&&&&&& unsigned write_max = chip.page_
&&&&&&&&&&&&&&&&&&&& at24->bin.write = at24_bin_ //write
&&&&&&&&&&&&&&&&&&&& at24->bin.attr.mode |= S_IWUSR;
&&&&&&&&&&&&&&&&&&&& if (write_max > io_limit)
&&&&&&&&&&&&&&&&&&&&&&&&&&& write_max = io_
&&&&&&&&&&&&&&&&&&&& if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
&&&&&&&&&&&&&&&&&&&&&&&&&&& write_max = I2C_SMBUS_BLOCK_MAX;
&&&&&&&&&&&&&&&&&&&& at24->write_max = write_
&&&&&& at24->client[0] =
&&&&&& for (i = 1; i < num_ i++) {
&&&&&&&&&&&&& at24->client[i] = i2c_new_dummy(client->adapter,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& client->addr + i);
&&&&&&&&&&&&& if (!at24->client[i]) {
&&&&&&&&&&&&&&&&&&&& dev_err(&client->dev, "address 0x%02x unavailable\n",
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& client->addr + i);
&&&&&&&&&&&&&&&&&&&& err = -EADDRINUSE;
&&&&&&&&&&&&&&&&&&&& goto err_
&&&&&&&&&&&&& }
&&&&&& err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin);
&&&&&& i2c_set_clientdata(client, at24);
err_clients:
&&&&&& for (i = 1; i < num_ i++)
&&&&&&&&&&&&& if (at24->client[i])
&&&&&&&&&&&&&&&&&&&& i2c_unregister_device(at24->client[i]);
at24_bin_writeat24_eeprom_write
mutex_lock(&at24->lock);
&&&&&& while (count) {
&&&&&&&&&&&&& ssize_t&&&&
&&&&&&&&&&&&& status = at24_eeprom_write(at24, buf, off, count);
&&&&&&&&&&&&& if (status <= 0) {
&&&&&&&&&&&&&&&&&&&& if (retval == 0)
&&&&&&&&&&&&&&&&&&&& &&&&&& retval =
&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&& }
&&&&&&&&&&&&& buf +=
&&&&&&&&&&&&& off +=
&&&&&&&&&&&&& count -=
&&&&&&&&&&&&& retval +=
&&&&&& mutex_unlock(&at24->lock);
&&&&&& at24_eeprom_write
static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf,
&&&&&&&&&&&&& unsigned offset, size_t count)
&&&&&& struct i2c_client *
&&&&&& struct i2c_
&&&&&& timeout = jiffies + msecs_to_jiffies(write_timeout);
&&&&&& do {
&&&&&&&&&&&&& write_time =
&&&&&&&&&&&&& if (at24->use_smbus) {
&&&&&&&&&&&&&&&&&&&& status = i2c_smbus_write_i2c_block_data(client,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& offset, count, buf);
&&&&&&&&&&&&&&&&&&&& if (status == 0)
&&&&&&&&&&&&&&&&&&&&&&&&&&& status =
&&&&&&&&&&&&& } else {
&&&&&&&&&&&&&&&&&&&& status = i2c_transfer(client->adapter, &msg, 1);
&&&&&&&&&&&&&&&&&&&& if (status == 1)
&&&&&&&&&&&&&&&&&&&&&&&&&&& status =
&&&&&&&&&&&&& }
&&&&&&&&&&&&& /* REVISIT: at HZ=100, this is sloooow */
&&&&&&&&&&&&& msleep(1);
&&&&&& } while (time_before(write_time, timeout));
i2c_transferI2Ci2c-core.c
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
&&&&&& if (adap->algo->master_xfer) {
&&&&&&&&&&&&& if (in_atomic() || irqs_disabled()) {
&&&&&&&&&&&&&&&&&&&& ret = mutex_trylock(&adap->bus_lock);
&&&&&& &&&&&&&&&&&&& if (!ret)
&&&&&&&&&&&&&&&&&&&&&&&&&&& return -EAGAIN;
&&&&&&&&&&&&& } else {
&&&&&&&&&&&&&&&&&&&& mutex_lock_nested(&adap->bus_lock, adap->level);
&&&&&&&&&&&&& }
&&&&&&&&&&&&& ret = adap->algo->master_xfer(adap,msgs,num);
&&&&&&&&&&&&& mutex_unlock(&adap->bus_lock);
&&&&&& CPUI2Cs3c2410drivers/i2c/busses/i2c-s3c2410.c
static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
&&&&&& .master_xfer&&&&&&&&& = s3c24xx_i2c_xfer,
&&&&&& .functionality&&&&&&&&& = s3c24xx_i2c_func,
&&&&&& s3c24xx_i2c_xfer
static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
&&&&&&&&&&&&&&&&&&&& struct i2c_msg *msgs, int num)
&&&&&& for (retry = 0; retry
retry++) {
&&&&&&&&&&&&& ret = s3c24xx_i2c_doxfer(i2c, msgs, num);
&&&&&&&&&&&&& if (ret != -EAGAIN)
&&&&&&&&&&&&&&&&&&&&
&&&&&& s3c24xx_i2c_xfers3c24xx_i2c_doxfer
static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num)
&&&&&& spin_lock_irq(&i2c->lock);
&&&&&& i2c->msg&&&& =
&&&&&& i2c->msg_num =
&&&&&& i2c->msg_ptr = 0;
&&&&&& i2c->msg_idx = 0;
&&&&&& i2c->state&& = STATE_START;
&&&&&& s3c24xx_i2c_enable_irq(i2c);
&&&&&& s3c24xx_i2c_message_start(i2c, msgs);
&&&&&& spin_unlock_irq(&i2c->lock);
&&&&&& s3c24xx_i2c_doxfers3c24xx_i2c_message_start
static void s3c24xx_i2c_message_start (struct s3c24xx_i2c *i2c,
&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&& struct i2c_msg *msg)
&&&&&& writeb(addr, i2c->regs + S3C2410_IICDS);
&&&&&& //write slave addr to IICDS
&&&&&& ndelay(i2c->tx_setup);
&&&&&& writel(iiccon, i2c->regs + S3C2410_IICCON);
&&&&&& //write to IICCONstart
&&&&&& stat |=& S3C2410_IICSTAT_START;
&&&&&& writel(stat, i2c->regs + S3C2410_IICSTAT);
& &&&& s3c24xx_i2c_message_startslave addrs3c24xx_i2c_irq i2s_s3c_irq_nextbyte
&&&&&& s3c24xx_i2c_message_startstartACKi2s_s3c_irq_nextbyte
&&&&&& I2CE2PROM
E2PROMdrivers/i2c/chips/at24.ce2prom_writeeeprom_i2c_write
I2C corecorei2c-core.ci2c_transfer
drivers/i2c/busses/i2c-s3c2410.cs3c24xx_i2c_xfer
drivers/i2c/busses/i2c-s3c2410.cs3c24xx_i2c_doxfer
drivers/i2c/busses/i2c-s3c2410.cs3c24xx_i2c_message_start
drivers/i2c/busses/i2c-s3c2410.ci2s_s3c_irq_nextbyte
阅读(684) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
请登录后评论。

我要回帖

更多关于 误差信号 的文章

 

随机推荐