一、IIC总线有两根双向信号线,一根是数据线SDA,一根是时钟线SCL

 

 

 

每根接到IIC总线上的器件都有唯一的地址

 

二、IIC通信协议的函数写法

1、  起始信号

2、  终止信号

3、  写数据

4、  读数据

5、  发送应答信号

6、  发送非应答信号

7、  等待应答

8、  检测IIC总线设备

三、函数解析

1、  起始信号和终止信号

SCL为高电平期间,SDA线由高电平向低电平变化表示起始信号

SCL为高电平期间,SDA线由低电平向高电平变化表示终止信号

 

 

void i2c_Start(void)
{
    /* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
    SDA = 1;
    SCL = 1;
    i2c_Delay();
    SDA = 0;
    i2c_Delay();
    SCL = 0;
    i2c_Delay();
}

void i2c_Stop(void)
{
    /* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
    SDA = 0;
    SCL = 1;
    i2c_Delay();
    SDA = 1;
    i2c_Delay();
}

2、  应答和非应答

IIC总线规定,每传送一字节的数据后都要有一个应答信号以确定数据传送是否被对方接收。

 

应答信号由接收设备产生,在SCL为高电平期间,接收设备将SDA拉低为低电平,表示数据传输正确,产生应答。

unsigned char i2c_WaitAck(void)
{
     unsigned char re; //应答信号等于0则应答正确,等于1则没有应答
     SDA = 1;          //释放总线,能让对方拉低
     i2c_Delay();
     SCL = 1;          //此时刻开始,数据保持应答状态稳定
     i2c_Delay();
     re = SDA;         //0表示应答,1表示没有应答
     i2c_Delay(); 
     SCL = 0;
     i2c_Delay();

     return re;
}

3、  IIC数据的传送

数据位的有效性规定:IIC总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平时期,数据线上的高电平或低电平状态才允许变化。

 

 

 

void i2c_SendByte(unsigned char _ucByte)
{
     unsigned char i;     //其实信号开始后SCL是被拉低的
     for(i = 0; i < 8; i++)
     {
        if((_ucByte<<i) & 0x80)
            SDA = 1;
        else
            SDA = 0;
        SCL = 1; 
        i2c_Delay();
        SCL = 0;      //SCL等于0的时候写数据
        if(i == 7)    //最后一次时释放总线
        {
            SDA = 1;
        }
        i2c_Delay();
     }
}

unsigned char i2c_ReadByte(void)
{
     unsigned char i;
     unsigned char value = 0;
     for(i = 0; i < 8; i++)
     {
        value<<=1;    //循环左移,
        SCL = 1;  //稳定状态的时候读数据
        if(SDA == 1)
            value |= 0x01;//value++;  //最低位置0
    else
        value &= 0xfe;  //最低位置0
        SCL = 0;  //允许数据变化
        i2c_Delay();
     }

     return value;
}

4、产生一个应答信号和一个非应答信号

 

/*
*********************************************************************************************************
*   函 数 名: i2c_Ack
*   功能说明: CPU产生一个ACK信号
*   形    参:  无
*   返 回 值: 无
*********************************************************************************************************
*/
void i2c_Ack(void)
{
    SDA = 0;//响应
    i2c_Delay();
    SCL = 1;
    i2c_Delay();
    SCL = 0;
    i2c_Delay();   //在SCL为高电平期间SDA都为0即产生一个应答信号
    SDA = 1;       //释放总线
    i2c_Delay();
}

/*
*********************************************************************************************************
*   函 数 名: i2c_NAck
*   功能说明: CPU产生1个NACK信号
*   形    参:  无
*   返 回 值: 无
*********************************************************************************************************
*/
void i2c_NAck(void)
{
     SDA = 1;
     i2c_Delay();
     SCL = 1;
     i2c_Delay();
     SCL = 0;
     i2c_Delay();   //在SCL为高电平期间SDA都为1即产生一个非应答信号
}

5、延时函数

/*
*********************************************************************************************************
*   函 数 名: i2c_Delay
*   功能说明: I2C总线位延迟,最快400KHz
*   形    参:  无
*   返 回 值: 无
*********************************************************************************************************
*/
static void i2c_Delay(void)
{
    unsigned char i;

    /* 
        实际应用选择小于400KHz左右的速率即可
    */
    for (i = 0; i < 10; i++);
}