IIC协议解析


IIC协议解析

IIC 即Inter-Integrated Circuit(集成电路总线),这种总线类型是由飞利浦半导体公司在八十年代初设计出来的,主要是用来连接整体电路(ICS) ,IIC是一种多向控制总线,也就是说多个芯片可以连接到同一总线结构下,同时每个芯片都可以作为实时数据传输的控制源。这种方式简化了信号传输总线接口。


IIC的主要构成

两个双向的信号线

  1. 数据线SDA: Serial Data
  2. 时钟线SCL: Serial clock

IIC主要特点:

  1. 具有多机功能,该模块既可以做主设备也可以做为从设备
  2. IIC主设备功能:主要产生时钟,产生起始信号和停止信号
  3. IIC从设备功能:可编程的IIC地址检测,停止位检测
  4. 支持不同速率的通讯速度,标准速度(最高速度100kHZ),快速(最高400kHZ)

IIC通信过程:

  1. 主模式时,IIC的接口启动数据传输并且产生时钟信号。串行数据传输总是以起始条件开始并以停止条件结束。起始条件和停止条件都是在主模式下由软件产生控制的。
  2. 从模式时,IIC接口能识别它自己的地址(7位或者10位)和在数据总线广播的地址(好比每个人都有不同的身份ID,叫到哪个哪个就发生应答),同时软件能够控制开启或者禁止广播呼叫地址的识别。
  3. 数据和地址按照8位每个字节来传输,高位在前。跟在起始条件后的1或者2个字节是地址(7位模式为1个自己,10位模式为2个字节)。地址只能主模式发送。在一个字节传输的8个时钟后的第九个时钟期间,从模式接收后必须回一个ACK给发送器,这样才进行数据传输。

IIC几种信号:

  1. 空闲状态:在IIC空闲时候,SDA ,SCL 都是保持高电平。

  2. 起始信号:在时钟SCL保持高电平,然后SDA数据线是从高电平变为低电平表示起始信号;
    /*SDA下降沿*/
    void IIC_Start(void)
    {
        SDA = 1;
        SCL = 1;
        IIC_Delay(DELAY_TIME);
        SDA = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 0;	
    }
  3. 停止信号:在时钟SCL保持高电平,然后SDA数据线是从低电平变为高电平表示停止信号;
    void IIC_Stop(void)
    {
        SDA = 0;
        SCL = 1;
        IIC_Delay(DELAY_TIME);
        SDA = 1;
        IIC_Delay(DELAY_TIME);
    }
  4. 应答信号:主机发送完一个8位数据后,会从从机接收一个应答(acknowledge)信号,SDA将会拉低,这是接收应答;主机在接收完一个8位信号后,会向从机发送一个应答信号,这是发送应答
  5. 简单的理解就是:收到别人的信息要回复;你给别人信息别人也要回复你

    //发送应答
    void IIC_SendAck(bit ackbit)
    {
        SCL = 0;            //SCL=0时 SDA数据才能变
        SDA = ackbit;  		// 0表示应答,1表示非应答
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        IIC_Delay(DELAY_TIME);
        SCL = 0; 
        SDA = 1;
        IIC_Delay(DELAY_TIME);
    }
    
    //接受应答
    bit IIC_WaitAck(void)
    {
        bit ackbit;	
        SCL  = 1;
        IIC_Delay(DELAY_TIME);
        ackbit = SDA;
        SCL = 0;
        IIC_Delay(DELAY_TIME);
        return ackbit;
    }

最后列出所有的代码(十二届蓝桥杯资料包代码)

iic.h
//iic.h
#ifndef _IIC_H
#define _IIC_H

void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);

#endif
iic.c
//iic.c
/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include "reg52.h"
#include "intrins.h"

#define DELAY_TIME 5

#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */

void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}
//总线启动条件
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//总线停止条件
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//发送应答
void IIC_SendAck(bit ackbit)
{
    SCL = 0;
    SDA = ackbit;  					// 0:应答,1:非应答
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//等待应答
bit IIC_WaitAck(void)
{
    bit ackbit;
	
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;            //发送数据时,只有SCL为0时,才可以改变SDA值
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;   //SDA 获取 byt的最高位,通过与1000 0000 相与获得
        else SDA  = 0;             // 结果为1,if成立,SDA获取1
		                           //需要注意的是,if(*)内只要大于0就成立,
								   //而不一定非要为true或者1 	
		
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1; // byt 左移一位,右侧补0,比如 1011 0001变为  0110 0010
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for(i=0; i<8; i++)
    {   
    	SCL = 1;
	IIC_Delay(DELAY_TIME);
	da <<= 1;
	if(SDA) da |= 1;
	SCL = 0;
	IIC_Delay(DELAY_TIME);
    }
    return da;    
}
============================找指导老师布置任务吧==============================