IIC是由Philips公司创造的一种串行数据通信协议,仅运用两根信号线:SerialClock(简称SCL)和SerialData(简称SDA)。
IIC是总线结构,1个Master,1个或多个Slave,各Slave设备以7位地址委任,地址后边再跟1位读写位,一共读(=1)或许写(=0),所以咱们有时也可看到8位方式的设备地址,此刻每个设备有读、写两个地址,高7位地址其实是相同的。
IIC数据格局如下:
无数据:SCL=1,SDA=1;
开端位(Start):当SCL=1时,SDA由1向0跳变;
中止位(Stop):当SCL=1时,SDA由0向1跳变;
数据位:当SCL由0向1跳变时,由发送方操控SDA,此刻SDA为有用数据,不行随意改动SDA;
当SCL坚持为0时,SDA上的数据可随意改动;
地址位:界说同数据位,但只由Master发给Slave;
应对位(ACK):当发送方传送完8位时,发送方开释SDA,由接纳方操控SDA,且SDA=0;
否应对位(NACK):当发送方传送完8位时,发送方开释SDA,由接纳方操控SDA,且SDA=1。
当数据为单字节传送时,格局为:
开端位,8位地址位(含1位读写位),应对,8位数据,应对,中止位。
当数据为一串字节传送时,格局为:
开端位,8位地址位(含1位读写位),应对,8位数据,应对,8位数据,应对,……,8位数据,应对,中止位。
需求留意的是:
1、SCL一向由Master操控,SDA按照数据传送的方向,读数据时由Slave操控SDA,写数据时由Master操控SDA。当8位数据传送完毕之后,应对位或许否应对位的SDA操控权与数据位传送时相反。
2、开端位“Start”和中止位“Stop”,只能由Master来宣布。
3、地址的8位传送完毕后,成功装备地址的Slave设备有必要发送“ACK”。不然不然必定时刻之后Master视为超时,将抛弃数据传送,发送“Stop”。
4、当写数据的时分,Master每发送完8个数据位,Slave设备假如还有空间承受下一个字节应该答复“ACK”,Slave设备假如没有空间承受更多的字节应该答复“NACK”,Master当收到“NACK”或许必定时刻之后没收到任何数据将视为超时,此刻Master抛弃数据传送,发送“Stop”。
5、当读数据的时分,Slave设备每发送完8个数据位,假如Master期望继续读下一个字节,Master应该答复“ACK”以提示Slave预备下一个数据,假如Master不期望读取更多字节,Master应该答复“NACK”以提示Slave设备预备接纳Stop信号。
6、当Master速度过快Slave端来不及处理时,Slave设备能够拉低SCL不放(SCL=0将产生“线与”)以阻挠Master发送更多的数据。此刻Master将视状况减慢或完毕数据传送。
下面是自己编写的单片机一般IO口模仿IIC总线的程序源代码:
/*Fuction:GPIO模仿iic bus,完成与AT24C02的数据通信PS:该源代码是以STC89C52为渠道编写的,可通过修正包括的头文件以适用于一切51系列单片机SD:Jason*/#include#include sbit sda = P2^0;sbit scl = P2^1;unsigned char table1[11]={0,1,2,3,4,5,6,7,8,9};unsigned char table2[11];void init();void somenop();void delay(unsigned char);void start();void stop();void send_ack(unsigned char);unsigned char rec_ack();void write_byte(unsigned char);unsigned char read_byte();unsigned char write_add(unsigned char,unsigned char *,unsigned char);unsigned char read_add(unsigned char,unsigned char *,unsigned char);void main(){init();write_add(0x10,table1,10);delay(100);read_add(0x10,table2,10);while(1);}//端口初始化void init(){memset(table2,0,sizeof(table2));sda = 1;scl = 1;somenop();}//起始信号void start(){sda = 1;somenop();scl = 1;somenop();sda = 0;somenop();}//停止信号void stop(){sda = 0;somenop();scl = 1;somenop();sda = 1;somenop();}//主机发送应对信号void send_ack(unsigned char ack){scl = 0;somenop();sda = ack;somenop();scl = 1;somenop();scl = 0;somenop();sda = 1;somenop();}//主机接纳应对信号unsigned char rec_ack(){scl = 1;somenop();if(sda == 1){scl = 0;delay(1);scl = 1;if(sda == 1)return 1;}elsereturn 0;}//写一个字节void write_byte(unsigned char dat){unsigned char i,a;a = dat;for(i=0;i<8;i++){a = a<<1;scl = 0;somenop();sda = CY;somenop();scl = 1;somenop();}scl = 0;somenop();sda = 1;somenop();}//读一个字节unsigned char read_byte(){unsigned char i,a;scl = 0;somenop();sda = 1;somenop();for(i=0;i<8;i++){scl = 1;somenop();a = (a<<1)|sda;scl = 0;somenop();}return a;}//向add地址写入len长度的dat数据unsigned char write_add(unsigned char add,unsigned char *dat,unsigned char len){unsigned char flag,i;start();write_byte(0xa0);if(rec_ack() == 0){write_byte(add);if(rec_ack() == 0){for(i=0;i 0;y--)for(z=110;z>0;z--);}