IIC工作时序总结
I2C时序分析和基础知识总结

3、仲裁
是一个在有多个主机同时尝试控制总线但只允许其中一个控制总线并使报 文不被破坏的过程。
所有主机在SCL 线上产生它们自己的时钟来传输I2C 总线上的报文。数 据只在时钟的高电平周期有效。因此,需要一个确定的时钟进行逐位仲裁。 时钟同步通过线与连接I2C 接口到SCL 线来执行。这就是说:SCL 线的 高到低切换会使器件开始数它们的低电平周期,而且一旦器件的时钟变低电 平,它会使SCL 线保持这种状态直到到达时钟的高电平。但是,如果另一个 时钟仍处于低电平周期,这个时钟的低到高切换不会改变SCL 线的状态。因 此,SCL 线被有最长低电平周期的器件保持低电平。此时,低电平周期短的 器件会进入高电平的等待状态。 当所有有关的器件数完了它们的低电平周期后,时钟线被释放并变成高 电平,之后器件时钟和SCL线的状态没有差别,而且所有器件会开始数它们 的高电平周期。首先完成高电平周期的器件会再次将SCL线拉低,这样产生 的同步SCL 时钟的低电平周期由低电平时钟周期最长的器件决定,而高电平 周期由高电平时钟周期最短的器件决定。
•
连接到I2C总线上的器件,若具有I2C总线的硬件接口,则 很容易检测到起始和终止信号。对于不具备I2C总线硬件接 口的有些单片机来说,为了检测起始和终止信号,必须保证 在每个时钟周期内对数据线SDA采样两次。
• 接收器件收到一个完整的数据字节后,有可能需要完成 一些其它工作,如处理内部中断服务等,可能无法立刻接收 下一个字节,这时接收器件可以将SCL线拉成低电平,从而 使主机处于等待状态。直到接收器件准备好接收下一个字节 时,再释放SCL线使之为高电平,从而使数据传送可以继续 进行。
这发生在仲裁之前,这部分称为同步。
仲裁
主机只能在总线空闲的时侯启动传输。两个或多个主机可能在起始条件的 最小持续时间 (tHD; STA) 内产生一个起始条件,结果在总线上产生一个规定 的起始条件。 当SCL 线是高电平时,仲裁在SDA 线发生;这样,在其他主机发送低电 平时,发送高电平的主机将断开它的数据输出级,因为总线上的电平与它自 己的电平不相同。
FPGA_IIC时序实验

FPGA_IIC时序实验概述:这篇文章通过FPGA实现对EEPROM的读写操作,演示了如何看懂芯片时序和结构建模风格的verilog实现的一般方法。
以对IIC总线的FPGA实现为例子,揭示了芯片时序的分析的一般方法,和结构化建模风格的verilog实现如何对算法进行描述以及如何对时序的精确控制的一般方法。
这篇文章分为两个部分,第一个部分是如何看懂时序图,第二个部分是结构化建模风格的verilog如何对算法进行描述和对时序进行精确控制。
第一个部分尽量独立于第二个部分,也就是说这里的如何看懂时序图不仅仅适合FPGA对时序的描述,也同样适合单片机等控制器对时序的描述。
我觉得说明时序图是如何看懂的,和代码是如何思考和写出来的,比分析个别时序和解释个别代码如何工作更具有普遍性。
所以这篇文章主要是记录如何看懂时序图和如何把时序图写成对应的verilog模块。
接下来一部分主要讲结构化建模的思考方式。
对如何看懂时序感兴趣的可以直接跳到时序分析部分。
对如何通过verilog实现IIC总线感兴趣的可以直接跳过到代码分析部分。
建模的首要任务是管理复杂度。
管理复杂度可以通过以下方法来实现。
一般思路是首先找出要实现功能对应的抽象数据对象(ADT),然后通过建立原型的方法搭建模块的骨架,以增量式的开发方式构建肌肉、神经、血管和皮肤,然后构成完整的功能模块。
增量式的开发原则是每一步以能够最快的实现预期现象为目的进行的。
如果不能以最快的看到预期现象为目的,只是搭建完成各模块的后进行整合直接看结果的话,通常结果是什么都没有的。
这里借用了软件开发的一个原理,提高软件工程效率有效方法是把错误产生时间和解决的时间控制在越早,整个软件工程的代价就越小;否则,解决问题的时间离产生问题的时间越晚,整个软件工程的代价会成指数增长,最终会导致整个工程崩溃。
增量式开发的原则中的最快的实现预期现象,要运用到测试和调试的方法。
这里需要注意的一点是要看到实际的现象,而不仅仅是仿真的时序图符合预想。
24C02数据读写

sbit wei1=P1^0;
sbit wei2=P1^1;
/************24C02 数据和时钟端口定义*****************/
sbit sda=P2^7;
sbit scl=P2^6;
/***************八段共阳 LED 编码***********************/ uchar code table[]={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92, 0x82,0xf8,0x80,0x90,0x40};
//---实现功能:
//---开始时从 24C02 中读取秒表信息
//
//---每一秒向 24C02 中写一次信息
//---断电或复位重启后从断点前的那一秒开始计数
//
/****************************************************/
/**************包含头文件****************************/
void respons() //应答 {
uchar i; scl=1; delay(); while((sda==1)&&(i<250))i++; scl=0; delay(); } /************IIC 初始化****************************/ void init() { sda=1;
寻址。 1.总线上数据的有效性
IIC 总线是以串行方式传输数据,从数据字节的最高位开始传送,每一个数据位在 SCL 上都有一个时钟脉冲相对应。 在时钟线高电平期间数据线上必须保持稳定 的逻辑电平状态,高电平为数据 1,低电平为数据 0。只有在时钟线为 低电平时,才允许数据线上的电平状态变化,如图 11-2 所示。 2.总线上的信号 IIC 总线在传送数据过程中共有四种类型信号,它们分别是:开始信号、停止信号、重新开始信号和应答信号。
I2C调试笔记

I2C调试笔记最近被VK3344搞的昏头转向,今天代理商打电话居然说这款芯⽚不兼容硬件IIC总线控制器,真是崩溃!就当花时间买个教训吧!总结⼀下免得以后不长进⼜犯这种低级错误。
1。
先分析⽰波器抓到的iic时序图,该时序图是vk3344在 smart arm lpc3250 & linux 下由主机发出的往VK3344写数据的时序图。
图中1处标出的尖峰⾼电平值很奇怪只有每次写寄存器地址的时候在最后从机应答之后释放总线到⾼电平的信号都是这么⼀个尖峰,应该跟⽰波器采集数据的频率没关系吧?尖峰过后应该是通信结束了,但是却出现了2标出的⼀个低电平周期信号,后来仔细阅读IIC协议⽂档才想起来,IIC的结束信号⼀定是要在IIC的SCAL保持稳定⾼电平的时候SDA由低到⾼的的⼀个上升沿跳变。
之所以如2那样拉低是因为当时的时钟信号为低,这时候如果SDA就⼀直保持⾼电平的话那么就成了在SCAL为低的时候SDA⼀直保持⾼电平了,这样也就不算是结束信号了,所以⼀定要有2中的在SCAL为低的时候SDA拉低⼀个周期然后再跳变才⾏。
这⾥的时钟脉冲是⾼电平的时候SDA信号保持电平稳定才算是⼀个有效数据,也就是说⼀个SDA的电平信号⼀定要在整个时钟为⾼电平的⼀个周期内保持不变才算有效数据。
2。
这⾥说说IIC设备驱动的⼤致情况。
这个没多少要说的,因为是作为串⼝扩展的,所以就注册成了字符驱动,IIC的设备检测直接调⽤IIC的核⼼代码就⾏了,这个是IIC设备驱动和总线适配器之间的⼀个连接纽带,就不多说了,看代码就明⽩了。
还有⼀点差点忘了,就是IIC设备的中断的响应和处理,最好的办法是在驱动⾥⾯注册中断的时候的中断回调函数(服务函数)⾥⾯完成所有的读写,读写的内容分别⾃⼰在内核空间⾥⾯开辟⼀块内存来保持,在驱动函数的⽤户层接⼝那⾥最好留连个读写缓存状态标志,当然留个读写回调函数接⼝更好,这样就直接通过回调函数把数据从内核空间内存拷贝到⽤户⾃⼰的内存⾥⾯就⾏了,然后在线程⾥⾯遍历缓存也⾏,或者消息触发也⾏,随便怎么做都可以,看⾃⼰的喜好了。
I2C操作时序问题总结(内附大量实用代码和详解)

I2C 总线在单片机操作中用到的很多。
特别是以I2C总线进行数据和命令传输的器件,比如AT24C02存储芯片等。
特此做了相关操作过程中经常用到的操作和一些操作的解释。
相信看完之后,肯定会对I2C总线有深刻的理解。
I2C总线操作(从高位开始进行读写操作)写操作时序启动之后先进行一个字节的指令写入操作,然后进行应答;在进行字节数据的传送;然后再进行应答;I2C读操作时序基本上与写操作相同,不同的是读操作只需进行指令的写入,不写数据(应该不绝对),最后主机产生非应答信号,结束数据的读取;在对E2PROM(24C02)进行操作时,写入写操作指令后,然后写入需要操作的存储器地址号,最后写入数据。
且每个存储器地址只能赋值一次,重复对该存储器地址赋值会使前一个数据丢失。
读操作过程中需对将指令改写为读指令,在读取数据时需要写入指令指明需要读出数据时的存储器地址号下面是对24C02的写操作和读操作void write_add(uchar address,uchar date){start();write_byte(0xa0); //写指令respons();write_byte(address); //写入要操作的存储器地址respons();write_byte(date); //写入存储器数据respons();stop();}uchar read_add(uchar address){uchar date;start();write_byte(0xa0); //写入指令respons();write_byte(address); //写入读取操作时,要读取的存储器地址respons();stop();start();write_byte(0xa1); //写入指令,进行读操作respons();date=read_byte(); //进行读取数据norespons();stop();return date;}void main(){init();write_add(23,0xcc); //写入存储器地址号为23中,数据为0xcc delay1(100);P1=read_add(23); //读入存储器地址号为23中的数据,并将数据赋值给P1口,通过数码管显示while(1); //停留在此处}I2C串行总线的操作程序起始信号(时钟线为高,数据线由高变低):void AT24C04_Start(){SDA = 1; //拉高数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时SDA = 0; //产生下降沿 Delay5us(); //延时SCL = 0; //拉低时钟线}结束信号:(时钟线为高,数据线由低变高)void AT24C04_Stop(){SDA = 0; //拉低数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时SDA = 1; //产生上升沿 Delay5us(); //延时}字节传输:(每个字节为8位,一个字节带一个相应位)发送数据:void AT24C04_SendByte(BYTE dat){BYTE i;for (i=0; i<8; i++) //8位计数器{dat <<= 1; //移出数据的最高位SDA = CY; //送数据口SCL = 1; //拉高时钟线Delay5us(); //延时SCL = 0; //拉低时钟线,以便下一次传送数据 Delay5us(); //延时}AT24C04_RecvACK();}接收数据:BYTE AT24C04_RecvByte(){BYTE i;BYTE dat = 0;SDA = 1; //使能内部上拉,准备读取数据for (i=0; i<8; i++) //8位计数器{dat <<= 1;SCL = 1; //拉高时钟线Delay5us(); //延时dat |= SDA; //读数据SCL = 0; //拉低时钟线以便下一个数据传送 Delay5us(); //延时}return dat;数据响应:每次数据传输成功后,接收器件发送一个应答信号,当第九个信号产生时,产生应答信号的器件将SDA拉低。
iic通信时序

iic通信时序
iic通信时序
IIC(Inter-Integrated Circuit,又称为TWI(Two-Wire Interface),是被广泛应用在各种设备之间实现两线全双工通信的总线标准。
IIC总线由两个线组成,即SDA(数据线)和SCL(时钟线),其中,SCL负责传输控制信号,而SDA则负责传输数据。
具体的IIC通信时序如下:
1. Master端发出位置信号START:t首先,Master端需要发出一个位置信号START,确定一次slave发送操作的开始。
2. Master端发出从设备地址与操作动作:t之后,Master端还需要发出从设备地址和操作动作,使Slave端可以确定是谁发来的操作请求。
3. Slave端发出ACK应答:tSlave端收到Master端发出的地址信息及操作动作之后,会向Master端发出一个ACK应答,来表示该地址是有效的。
4. Master端发出Data:t接着,Master端会向Slave发出所要传输的data,进行数据传输。
5. Slave端发出ACK应答:tSlave端收到Master端发出的数据之后,会向Master端发出一个ACK应答,来表示数据已经收到。
6. Master端发出STOP信号:t最后,Master端发出一个STOP 信号,确定一次slave发送操作的结束。
24C02数据读写

一这物行时每如一、认识IIC 这是最常用、物理结构上,行信息 传输。
时钟。
信息传每个器件都有如:存储器)C 总线的工作方最典型的II IIC 系统由一。
在数据传输传输的对象和方有一个唯一的地。
发送器或接方式C 总线连接方一条串行数据输时,由主机初方向以及信息地址,而且可接收器可以在IIC 时方式。
据线SDA 和一条初始化一次数息传输的开始可以是单接收的在主模式或从模时序24C02的条串行时钟线数据传输,主和终 止均由的器件(例如模式下操作,的操作 线SCL 组成。
主机使数据在S 主机决定。
如:LCD 驱动器这取决于芯片主机按一定的SDA 线上传输器)或者可以接片是否必须启的通信协议向输的同时还通过接收也可以发启动数据的传从机寻址和进过SCL 线传输发送的器件(例传输还是仅仅被进输例被寻1I 在低2I 寻址。
1.总线上数据IIC 总线是以在时钟线高电低电平时,才2.总线上的信IIC 总线在传据的有效性串行方式传输电平期间数据线才允许数据线上信号送数据过程中输数据,从数据线上必须保持上的电平状态中共有四种类据字节的最高持稳定 的逻辑态变化,如图类型信号,它们高位开始传送,辑电平状态,11-2所示。
们分别是:开,每一个数据位高电平为数据开始信号、停止位在SCL 上都据1,低电平为止信号、重新都有一个时钟为数据0。
只新开始信号和应脉冲相对应。
有在时钟线为应答信号。
为开的停停重之所开始信号(STA 的时候,例如停止信号(STO 停止信号,结重新开始信号之前,主机通所示,当SCL ART):如图1如,没有主动设OP):如图11结束数据通信。
号(Repeated S 通过发送重新开L为高电平时,1-3所示,当设备在使用总-3所示,当。
START):在I 开始信号,可,SDA由高电当SCL 为高电总线(SDA 和S SCL 为高电平IC 总线上,由可以转换与当电平向低电平跳平时,SDA 由CL 都处于高电平时,SDA 由低由主机发送一前从机的通信跳变,产生重由高电平向低电电平),主机通低电平向高电一个开始信号启信模 式,或是重新开始信号,电平跳变,产通过发送开始电平跳变,产生启动一次通信是切换到与另,它的本质就产生开始信号始(START)信号生停止信号。
STM32系列IIC使用总结

STM32系列IIC使用总结STM32系列是意法半导体公司推出的一款32位ARM Cortex-M微控制器系列产品,广泛应用于各类嵌入式系统中。
其中,IIC总线是STM32系列产品中常用的通信接口之一,用于连接各种外部设备,如传感器、存储器、LCD显示屏等。
下面是对STM32系列IIC使用的总结。
一、STM32IIC硬件功能1. IIC接口引脚:STM32的IIC接口引脚有两个,分别是SDA(Serial Data)和SCL(Serial Clock)。
2.多主机模式支持:STM32的IIC接口支持多主机模式,可以实现多个主机同时操作同一个从机设备。
3. 速率控制:STM32的IIC接口支持多种速率配置,包括标准模式(100Kbps)、快速模式(400Kbps)和高速模式(1Mbps)等。
4.IIC总线协议支持:STM32的IIC接口遵循I2C总线协议,支持7位或10位设备地址,支持字节读写、页写、设备寻址等操作。
二、STM32IIC软件开发步骤1.初始化IIC接口:使用STM32提供的库函数,配置IIC引脚为复用功能,并初始化IIC控制器的寄存器,包括速率设置、硬件过滤器配置等。
2.开启IIC总线:调用库函数,使能IIC总线,准备进行通信。
3.生成起始位和停止位:调用库函数,发送起始位和停止位信号,控制IIC总线的起始和停止状态。
4.发送器件地址:调用库函数,发送要操作的设备的地址信息,用于将总线上的控制权交给该设备。
5.发送数据或接收数据:调用库函数,根据需要发送数据或接收数据,并处理数据的传输错误等异常情况。
6.关闭IIC总线:调用库函数,关闭IIC总线,释放总线资源。
三、处理IIC通信中的常见问题1.电源电压:STM32的IIC接口对电源电压要求较高,通常工作电压为3.3V,要确保供电电压稳定。
2.设备地址:在使用IIC接口时,需要正确设置设备的地址信息,确保与从机设备进行正常通信。
3.速率设置:根据实际需求,选择合适的通信速率,避免传输错误和数据丢失。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.概述:I²C是Inter-Integrated Circuit的缩写,发音为"eye-squared cee" or "eye-two-cee", 它是一种两线接口。
I²C 只是用两条双向的线,一条 Serial Data Line (SDA) ,另一条Serial Clock (SCL)。
SCL:上升沿将数据输入到每个EEPROM器件中;下降沿驱动EEPROM 器件输出数据。
(边沿触发)SDA:双向数据线,为OD门,与其它任意数量的OD与OC门成"线与"关系。
2.输出级每一个I2C总线器件内部的SDA、SCL引脚电路结构都是一样的,引脚的输出驱动与输入缓冲连在一起。
其中输出为漏极开路的场效应管,输入缓冲为一只高输入阻抗的同相器,这种电路具有两个特点:1)由于SDA、SCL为漏极开路结构(OD),因此它们必须接有上拉电阻,阻值的大小常为 1k8, 4k7 and 10k ,但1k8 时性能最好;当总线空闲时,两根线均为高电平。
连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线"与"关系。
2)引脚在输出信号的同时还将引脚上的电平进行检测,检测是否与刚才输出一致,为"时钟同步"和"总线仲裁"提供了硬件基础。
3.主设备与从设备系统中的所有外围器件都具有一个7位的"从器件专用地址码",其中高4位为器件类型,由生产厂家制定,低3位为器件引脚定义地址,由使用者定义。
主控器件通过地址码建立多机通信的机制,因此I2C总线省去了外围器件的片选线,这样无论总线上挂接多少个器件,其系统仍然为简约的二线结构。
终端挂载在总线上,有主端和从端之分,主端必须是带有CPU的逻辑模块,在同一总线上同一时刻使能有一个主端,可以有多个从端,从端的数量受地址空间和总线的最大电容 400pF的限制。
o主端主要用来驱动SCL line;o从设备对主设备产生响应;二者都可以传输数据,但是从设备不能发起传输,且传输是受到主设备控制的。
4.速率:普通模式:100kHz;快速模式:400kHz;高速模式:3.4MHz;没有任何必要使用高速SCL,将SCL保持在100k或以下,然后忘了它吧。
一、协议1.空闲状态I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。
此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。
2.起始位与停止位的定义:∙起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
∙停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
3.ACK发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。
应答信号为低电平时,规定为有效应答位(ACK 简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。
如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。
如下图逻辑分析仪的采样结果:释放总线后,如果没有应答信号,sda应该一直持续为高电平,但是如图中蓝色虚线部分所示,它被拉低为低电平,证明收到了应答信号。
这里面给我们的两个信息是:1)接收器在SCL的上升沿到来之前的低电平期间拉低SDA;2)应答信号一直保持到SCL的下降沿结束;正如前文红色标识所指出的那样。
4.数据的有效性:I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
我的理解:虽然只要求在高电平期间保持稳定,但是要有一个提前量,也就是数据在SCL的上升沿到来之前就需准备好,因为在前面I2C 总线之(一)---概述一文中已经指出,数据是在SCL的上升沿打入到器件(EEPROM)中的。
5.数据的传送:在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。
数据位的传输是边沿触发。
二、工作过程总线上的所有通信都是由主控器引发的。
在一次通信中,主控器与被控器总是在扮演着两种不同的角色。
1.主设备向从设备发送数据主设备发送起始位,这会通知总线上的所有设备传输开始了,接下来主机发送设备地址,与这一地址匹配的slave将继续这一传输过程,而其它slave将会忽略接下来的传输并等待下一次传输的开始。
主设备寻址到从设备后,发送它所要读取或写入的从设备的内部寄存器地址;之后,发送数据。
数据发送完毕后,发送停止位:写入过程如下:发送起始位∙发送从设备的地址和读/写选择位;释放总线,等到EEPROM拉低总线进行应答;如果EEPROM接收成功,则进行应答;若没有握手成功或者发送的数据错误时EEPROM不产生应答,此时要求重发或者终止。
∙发送想要写入的内部寄存器地址;EEPROM对其发出应答;∙发送数据∙发送停止位.∙EEPROM收到停止信号后,进入到一个内部的写入周期,大概需要10ms,此间任何操作都不会被EEPROM响应;(因此以这种方式的两次写入之间要插入一个延时,否则会导致失败,博主曾在这里小坑了一下)详细:需要说明的是:①主控器通过发送地址码与对应的被控器建立了通信关系,而挂接在总线上的其它被控器虽然同时也收到了地址码,但因为与其自身的地址不相符合,因此提前退出与主控器的通信;2.主控器读取数据的过程:读的过程比较复杂,在从slave读出数据前,你必须先要告诉它哪个内部寄存器是你想要读取的,因此必须先对其进行写入(dummy write):∙发送起始位;∙发送slave地址+write bit set;∙发送内部寄存器地址;∙重新发送起始位,即restart;∙重新发送slave地址+read bit set;∙读取数据主机接收器在接收到最后一个字节后,也不会发出ACK信号。
于是,从机发送器释放SDA线,以允许主机发出P信号结束传输。
∙发送停止位详细:为了加深对I2C总线的理解,用C语言模拟IIC总线,边看源代码边读波形:如下图所示的写操作的时序图:读时序的理解同理。
对于时序不理解的朋友请参考“I2C总线之(二)---时序”完整的程序如下:#include<reg51.h>#define uchar unsigned char#define uint unsigned int#define write_ADD 0xa0#define read_ADD 0xa1uchar a;sbit SDA=P2^0;sbit SCL=P2^1;void SomeNop(); //短延时void init(); //初始化void check_ACK(void);void I2CStart(void);void I2cStop(void);void write_byte(uchar dat);//写字节void delay(uint z);uchar read_byte(); //读字节void write(uchar addr,uchar dat); //指定地址写uchar read(uchar addr); //指定地址读bit flag; //应答标志位void main(){init();write_add(5,0xaa); //向地址5写入0xaadelay(10); //延时,否则被坑呀!!!P1=read_add(5); //读取地址5的值while(1);}//**************************************************************** ***********void delay()//简单延时函数{ ;; }//**************************************************************** ***********void start() //开始信号 SCL在高电平期间,SDA一个下降沿则表示启动信号{sda=1; //释放SDA总线delay();scl=1;delay();sda=0;delay();}//**************************************************************** ***********void stop() //停止 SCL在高电平期间,SDA一个上升沿则表示停止信号{sda=0;delay();scl=1;delay();sda=1;delay();}//**************************************************************** ***********void respons() //应答 SCL在高电平期间,SDA被从设备拉为低电平表示应答{uchar i;scl=1;delay();//至多等待250个CPU时钟周期while((sda==1)&&(i<250))i++;scl=0;delay();}//**************************************************************** ***********void init()//总线初始化将总线都拉高一释放总线发送启动信号前,要先初始化总线。
即总有检测到总线空闲才开始发送启动信号{sda=1;delay();scl=1;delay();}//**************************************************************** ***********void write_byte(uchar date) //写一个字节{uchar i,temp;temp=date;for(i=0;i<8;i++){temp=temp<<1;scl=0;//拉低SCL,因为只有在时钟信号为低电平期间按数据线上的高低电平状态才允许变化;并在此时和上一个循环的scl=1一起形成一个上升沿delay();sda=CY;delay();scl=1;//拉高SCL,此时SDA上的数据稳定delay();}scl=0;//拉低SCL,为下次数据传输做好准备delay();sda=1;//释放SDA总线,接下来由从设备控制,比如从设备接收完数据后,在SCL为高时,拉低SDA作为应答信号delay();}//**************************************************************** ***********uchar read_byte()//读一个字节{uchar i,k;scl=0;delay();sda=1;delay();for(i=0;i<8;i++){scl=1;//上升沿时,IIC设备将数据放在sda线上,并在高电平期间数据已经稳定,可以接收啦delay();k=(k<<1)|sda;scl=0;//拉低SCL,使发送端可以把数据放在SDA上delay();}return k;}//**************************************************************** ***********void write_add(uchar address,uchar date)//任意地址写一个字节{start();//启动write_byte(0xa0);//发送从设备地址respons();//等待从设备的响应write_byte(address);//发出芯片内地址respons();//等待从设备的响应write_byte(date);//发送数据respons();//等待从设备的响应stop();//停止}//**************************************************************** ***********uchar read_add(uchar address)//读取一个字节{uchar date;start();//启动write_byte(0xa0);//发送发送从设备地址写操作respons();//等待从设备的响应write_byte(address);//发送芯片内地址respons();//等待从设备的响应start();//启动write_byte(0xa1);//发送发送从设备地址读操作respons();//等待从设备的响应date=read_byte();//获取数据stop();//停止return date;//返回数据}。