一、IIC简介
IIC是一种串行、半双工总线,主要用于近距离、低速的芯片之间的通信。有两根信号线,一根为SCL(时钟线),一根为SDA(数据线) 。 IIC是一种多主机总线,连接在IIC总线上的器件分为主机和从机,主机有权发起和结束一次通信,而从机只能被呼叫;当总线上有多个主机同时启用总线时,IIC也具备冲突检测和仲裁的功能来防止错误产生;每个连接到IIC总线上的器件都有唯一的地址(7bit),并且每个器件都可以作为主机和从机;IIC总线在通信时总线上发送数据的为发送器,接受数据的为接受器。
二、IIC总线通信过程
1、主机发出起始信号占用总线 2、主机发送一个字节的数据指明从机地址和后续字节的传送方向 3、被寻址的从机发送应答信号回应主机 4、发送器发送一个字节的数据 5、接受器发送应答信号 重复步骤4、5 最后由发送器发送停止信号释放总线。 在步骤2时,发送的一个字节数据,高7位为器件ID,最后一位为数据的发送方向。0为主机发送到从机,1为从机发送到主机。此步骤发送的数据所有器件都可以收到,并和自己ID进行比对。
三、IIC典型信号
1、起始信号SCL为高电平,SDA由高变低表示起始信号。 代码如下:
void IIC_Start(){
SDA = 1;//先拉高SDA
delay_ms(5);
SCL = 1;//再拉高SCL
SDA = 0;
delay(5);
SCL = 0;//钳住总线,准备发送或接收数据
}
2、结束信号,SCL为高电平时,SDA由低变高表示停止信号。
void IIC_Stop(){
SCL = 0;
SDA = 0;
delay_us(5);
SCL = 1;
delay_us(5);
SDA = 1;
delay_us(5);
}
3、字节传送 数据的有效性 在传输数据的过程中,当SCL为高电平时,数据线SDA必须保持稳定状态,此时接受器接受一位的数据,当SCL为低电平时,SDA允许跳动,此时发送器可以发送一位的数据。 IIC通信时每个字节为8为长度,数据传送时,先传送高位,后传送低位,发送器发送完一个字节后,接收器必须发送一位的响应信号。也就是每一帧数据为9位。 如果是发送数据:8位数据位+ 1位ACK 如果是发送地址:7位地址位 + 1位方向 + 1位ACK
//IIC发送一个字节数据
//返回从机有无应答
//1、有应答
//0、无应答
void IIC_Send_Byte(uint8_t txd){
uint8_t t;
SDA_OUT();
IIC_SCL = 0;//拉低时钟线开始传输
for( t = 0; t < 8; t++){
if((txd & 0x80) == 1)
IIC_SDA = 1;
else
IIC_SDA = 0;
txd <<= 1;//向左移一位
delay_us(2);
IIC_SCL = 1;
delay_us(2);
IIC_SCL = 0;
delay_us(2);
}
}
//IIC读取一个字节数据
uint8_t IIC_Read_byte(unsigned char ack){
unsigned char i, receive = 0;
SDA_IN();
for(i = 0; i < 8; i++){
IIC_SCL = 0;
delay_us(2);
IIC_SCL = 1;
receive <<= 1;
if(READ_SDA) receive++;
delay_us(1);
}
if(ack)
IIC_Ack();
else
IIC_NACK();
return receive;
}
4、应答信号和非应答信号
//产生应答信号
void IIC_ACK(){
IIC_SCL = 0;//先拉低SCL,使SDA数据可以改变
IIC_SDA = 0;
delay_us(2);
IIC_SCL = 1;
delay_us(5);
IIC_SCL = 0;
}
//不产生应答信号
void IIC_NACK(){
IIC_SCL = 0;
IIC_SDA = 1;
delay_us(2);
IIC_SCL = 1;
delay_us(5);
IIC_SCL = 0;
}
//等待应答信号
//1:接收应答信号失败
//0:接收应答信号成功
uint8_t IIC_Wait_ACK(){
uint8_t ucErrorTime = 0;
IIC_SDA = 1;delay_us(1);
IIC_SCL = 1;delay_us(1);
while(READ_SDA){
ucErrorTime++;
if(ucErrorTime > 250){
IIC_Stop();
return 1;
}
}
IIC_SCL = 0;//占住总线
return 0;
}
四、典型IIC时序
1、主机向从机发送数据 START:起始信号 DEVICE ADDRESSS:7位设备地址 R/W:读写信号 ACK:应答信号 WORD ADDRESS:从机中的寄存器地址 ACK:响应信号 DATA:数据 STOP:停止信号 2、主机向从机读取数据
五、下面以AT24C02为例
AT24C02是一个2Kbit的串行EEPROM,内部含有256个8位的字节。 A0,A1,A2:地址引脚 WP:写保护引脚,接高电平只读,接低电平可读可写 SCL,SDA:IIC信号线 对于不同容量的AT24C02,具有不同的地址,由下图可得
本例程中AT2C402高四位地址为1010,A0-A2由管脚电平决定,我们将其接地,那么A0-A2为000,最低位表示读写,所以 读AT24C02的时候,地址为10100001B(0xa0) 写AT24C02的时候,地址为10100000B(0xa1) 向AT24C02中写数据
操作时序为:
1、主机发出起始信号 2、主机发送器件地址,在本例中为0xa0 3、等待应答信号 4、发送数据的存储地址。AT24C02共有256个可寻址空间,地址从0x00-0xff,想把数据存储在哪里,此时就是写的哪个地址 5、等待应答信号 6、发送要写入的数据,每写入一个字节,等待一个应答信号,如果没有应答,说明写入失败。 7、发送停止信号,结束通信
注意:在写数据的时候,每成功写入一个字节,EEPROM的地址就会+1.当到0xff后,在写入一个字节,地址就会变成0x00。 写数据的时候,EEPROM是先写到缓冲区,然后在搬运到掉电非易失区。所以需要一定的时间,AT24C02一般不超过5ms,所以在写入多个字节时,需要延时5ms。
从AT24C02中读取数据 1、读取当前地址的数据
AT24WC01/02/04/08/16 的地址计数器内容为最后操作字节的地址加 1。也就是说 如果上次读/写的操作地址为 N,则立即读的地址从地址 N+1 开始。如果 N=E(这里对 24WC01 E=127;对 24WC02 E=255;对 24WC04 E=511;对 24WC08 E=1023;对 24WC16 E=2047)则计数器将翻转到 0 且继续输出数据。AT24WC01/02/04/08/16 接收到从器件地址信号后(R/W 位置 1),它首先发送一个应答信号,然后发送一个 8 位字节数据。主器件不需发送一个应答信号,但要产生一个停止信号。
按照时序就可以完成 2、读随机地址的数据
1、主机首先发出一个起始信号 2、主机发送写操作地址,本例中为0xa0(这里写操作是为了将要读的数据的地址先写进去,告诉EEPROM要读哪个地址的数据),等待一个ACK信号 3、发送内存的地址,说明要读哪个地址的信息 4、重新开始发送起始信号 5、主机发送读操作地址,本例为0xa1 6、EEPROM会自动向主机发送数据, 7、主机回复一个NACK信号,发送结束信号,结束通信。
3、连续读数据 当主机接收到一个字节的数据后,还想继续接受数据,就可以发送一个ACK信号,从机就会继续发送数据。