IIC是什么?
答:IIC 即Inter-Integrated Circuit(集成电路总线),这种总线类型是由飞利浦半导体公司在八十年代初设计出来的,主要是用来连接整体电路(ICS) ,IIC是一种多向控制总线,也就是说多个芯片可以连接到同一总线结构下,同时每个芯片都可以作为实时数据传输的控制源。这种方式简化了信号传输总线接口。
以上是百科资料。IIC实际上就是随需求的增长应运而生的一种多机(以下分主机、从机)串行数据传输方式,而IIC被冠以“协议”二字就是说我们共同制定了这种规则,大家必须遵守,以保证数据的正确传输。
那么这种协议是怎么规定的?
答:应用IIC协议的器件一定有时钟总线SCL和数据总线SDA(这么聪明的你一定知道)。协议规定(白话文了哈):
1.SCL在高电平期间,SDA不准变化;SCL在低电平期间,SDA可以变化(数据传输);
2.主机的起始与停止信号控制二者数据传输的节奏(主机就是大佬,让你干什么就必须干什么);
3.主机发出读写数据命令后,如果从机敢不应答,主机就不带你玩了,一个stop信号走机!
以下以AT24C02(外部存储芯片EEPROM)分析:
一、AT24C02器件引脚图:
应用IIC协议的器件引脚都相差无几,无非就是SCL时钟总线,SDA数据总线,WP写保护,A0/A1/A2为器件寻址(下面会提到),VCC和GND就不摆了撒。
二、 主机(MCU)与从机(IIC器件)的连接
AT24C02就属于EEPROM,可以只有一个主机和一个从机。
三、数据传输
IIC器件的数据传输:在主机给予start信号后,开始传输数据,主机每传一个字节从机必须要有应答(好比主机去从机家敲门,从机“诶”一声),在主机的stop信号后,数据传输结束。所以,数据完整传输就是四个过程:开始,数据传输,应答,结束。
开始与结束:
由上图及IIC协议知:
开始信号:SCL=1时,主机令SDA=0。
somenop为时序要求,一般为4.7us左右即可,这里用4个_nop_()表示。
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}
结束信号:SCL=1时,SDA=1。
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}
数据传输与应答过程:
数据传输:遵从IIC协议,在SCL=0时SDA变化。一次传输8位数据,即传输一个字节会有八次SCL拉低拉高,SDA则随要传输的数据进行变化。
(1)主机发送数据:
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++){
if(byt&0x80){
SDA = 1;
}
else{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}
(2)主机接受数据:
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++){
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}
应答:
bit
IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
if(SDA){
SCL = 0;
IIC_Stop();
return 0;
}
else{
SCL = 0;
return 1;
}
}
至此,各个过程分析完毕。
四、数据的读写
(1)Write
根据上面的分析,我们可以很快得到:
void IIC_Write(char address,char data)
{
IIC_Start();
IIC_SendByte(0xa0); //AT24C02的器件地址为 1010 0000(假设只有一个AT24C02,因为是写操作,所以最后一位为0)
IIC_WaitAck();
IIC_SendByte(address); //AT24C02的寄存器位置
IIC_WaitAck();
IIC_SendByte(data);
IIC_WaitAck();
IIC_Stop();
}
(2)Read
同理:
unsigned char IIC_Read(unsigned char address)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(address); //AT24C02的寄存器位置
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);//最后一位为1表示主机要读数据了
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
return temp;
}