什么是IIC总线协议
I2C 总线是一种串行数据总线,只有二根信号线,一根是双向的数据线SDA,另一根是时钟线SCL,两条线可以挂多个设备。 IIC设备(绝大多数)里有个固化的地址,只有在两条线上传输的值等于IIC设备的固化地址时,其才会作出响应。
通常我们为了方便把IIC设备分为主设备和从设备,基本上谁控制时钟线(即控制SCL的电平高低变换)谁就是主设备。
以AT24C02为例子
芯片的寻址:AT24C02是的固定地址是1010A2A1A0R/W,A2A1A0这三位是由引脚确定的,一般都是000,
片内地址寻址:芯片寻址可对内部256B中的任一个进行读/写操作,其寻址范围为00~FF,共256个寻址单位。
IIC通信的时序图(通过模拟时序来实现)
初始化:(电平变化之后都要延时一段时间)
IIC的初始化就是SDA和SCL都是高电平
开始信号:
SCL保持高电平,SDA有高电平变为低电平后,延时,SCL变为低电平。
停止信号:SCL保持高电平。SDA由低电平变为高电平。
数据的传输和响应信号
数据的传输:
写:SDA要在SCL低电平的时候进行电平的翻转,在SCL高电平的时候必须保持稳,传输完成后要将SDA拉高SCL拉低。
应答:SCL拉高,读取SDA的电平,为低电平表示产生应答
读:将SCL拉低,SDA拉高。,改变SCL拉高,片段SDA是否等于1,以为或操作提取数据。
/*******************************************************************************
* º¯ Êý Ãû : SDA_OUT
* º¯Êý¹¦ÄÜ : SDAÊä³öÅäÖÃ
* Êä Èë : ÎÞ
* Êä ³ö : ÎÞ
*******************************************************************************/
void SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);
}
/*******************************************************************************
* º¯ Êý Ãû : SDA_IN
* º¯Êý¹¦ÄÜ : SDAÊäÈëÅäÖÃ
* Êä Èë : ÎÞ
* Êä ³ö : ÎÞ
*******************************************************************************/
void SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);
}
/*******************************************************************************
* º¯ Êý Ãû : IIC_Start
* º¯Êý¹¦ÄÜ : ²úÉúIICÆðʼÐźÅ
* Êä Èë : ÎÞ
* Êä ³ö : ÎÞ
*******************************************************************************/
void IIC_Start(void)
{
SDA_OUT(); //sdaÏßÊä³ö
IIC_SDA=1;
IIC_SCL=1;
delay_us(5);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(6);
IIC_SCL=0;//ǯסI2C×ÜÏߣ¬×¼±¸·¢ËÍ»ò½ÓÊÕÊý¾Ý
}
/*******************************************************************************
* º¯ Êý Ãû : IIC_Stop
* º¯Êý¹¦ÄÜ : ²úÉúIICÍ£Ö¹ÐźÅ
* Êä Èë : ÎÞ
* Êä ³ö : ÎÞ
*******************************************************************************/
void IIC_Stop(void)
{
SDA_OUT();//sdaÏßÊä³ö
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
IIC_SCL=1;
delay_us(6);
IIC_SDA=1;//·¢ËÍI2C×ÜÏß½áÊøÐźÅ
delay_us(6);
}
/*******************************************************************************
* º¯ Êý Ãû : IIC_Wait_Ack
* º¯Êý¹¦ÄÜ : µÈ´ýÓ¦´ðÐźŵ½À´
* Êä Èë : ÎÞ
* Êä ³ö : 1£¬½ÓÊÕÓ¦´ðʧ°Ü
0£¬½ÓÊÕÓ¦´ð³É¹¦
*******************************************************************************/
u8 IIC_Wait_Ack(void)
{
u8 tempTime=0;
IIC_SDA=1;
delay_us(1);
SDA_IN(); //SDAÉèÖÃΪÊäÈë
IIC_SCL=1;
delay_us(1);
while(READ_SDA)
{
tempTime++;
if(tempTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//ʱÖÓÊä³ö0
return 0;
}
/*******************************************************************************
* º¯ Êý Ãû : IIC_Ack
* º¯Êý¹¦ÄÜ : ²úÉúACKÓ¦´ð
* Êä Èë : ÎÞ
* Êä ³ö : ÎÞ
*******************************************************************************/
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(5);
IIC_SCL=0;
}
/*******************************************************************************
* º¯ Êý Ãû : IIC_NAck
* º¯Êý¹¦ÄÜ : ²úÉúNACK·ÇÓ¦´ð
* Êä Èë : ÎÞ
* Êä ³ö : ÎÞ
*******************************************************************************/
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(5);
IIC_SCL=0;
}
/*******************************************************************************
* º¯ Êý Ãû : IIC_Send_Byte
* º¯Êý¹¦ÄÜ : IIC·¢ËÍÒ»¸ö×Ö½Ú
* Êä Èë : txd£º·¢ËÍÒ»¸ö×Ö½Ú
* Êä ³ö : ÎÞ
*******************************************************************************/
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//ÀµÍʱÖÓ¿ªÊ¼Êý¾Ý´«Êä
for(t=0;t<8;t++)
{
if((txd&0x80)>0) //0x80 1000 0000
IIC_SDA=1;
else
IIC_SDA=0;
txd<<=1;
delay_us(2); //¶ÔTEA5767ÕâÈý¸öÑÓʱ¶¼ÊDZØÐëµÄ
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
/*******************************************************************************
* º¯ Êý Ãû : IIC_Read_Byte
* º¯Êý¹¦ÄÜ : IIC¶ÁÒ»¸ö×Ö½Ú
* Êä Èë : ack=1ʱ£¬·¢ËÍACK£¬ack=0£¬·¢ËÍnACK
* Êä ³ö : Ó¦´ð»ò·ÇÓ¦´ð
*******************************************************************************/
u8 IIC_Read_Byte(u8 ack)
{
u8 i,receive=0;
SDA_IN();//SDAÉèÖÃΪÊäÈë
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_NAck();//·¢ËÍnACK
else
IIC_Ack(); //·¢ËÍACK
return receive;
}