IIC通信协议总结

 

通信协议中常用术语介绍:

 

通信类型:如串行异步全双工

异步:没有时钟线,一般配置相同的波特率(不发送数据块,而是一个一个字符发送)

同步:有相同的时钟线,不用考虑传输周期(要是协议最大范围之内的速率)(发送数据块给到另一端称之为同步,要求发送和接收方的时钟必须一致。)

全双工:同时可以收发(类似于电话)

半双工:可以收发,不能同时(类似于对讲机)

单工:只能收或只能发

串行:一次在一根线上发数据

并行:一次可以在很多线上同时发送数据

物理接口:物理上接线方式,如串口的RX,TX引脚

通信协议:如RS232,ModBus

(Modbus协议,从字面理解它包括Mod和Bus两部分,首先它是一种bus,即总线协议,和I2C、SPI类似,总线就意味着有主机,有从机,这些设备在同一条总线上。)

(总线(Bus)是计算机各种功能部件之间传送信息的公共通信干线,它是由导线组成的传输线束, 按照计算机所传输的信息种类,计算机的总线可以划分为数据总线、地址总线和控制总线,分别用来传输数据、数据地址和控制信号。总线是一种内部结构,它是cpu、内存、输入、输出设备传递信息的公用通道,主机的各个部件通过总线相连接,外部设备通过相应的接口电路再与总线相连接,从而形成了计算机硬件系统。在计算机系统中,各个部件之间传送信息的公共通路叫总线,微型计算机是以总线结构来连接各个功能部件的。)->通信用的通道,如古代驿站,可以划分为不同的功能,,数据总线,地址总线,控制总线。

 IIC简介

  IIC是IIC Bus简称,所以中文应该叫 集成电路总线

通信协议简介:IIC(Inter-Integrated Ciruit)是由PHILIPS(飞利浦)公司开发的两线式串行总线,用来连接微控制器(MCU)及外围设备了,它是由数据线SDA和时钟线SCL构成的串行总线,优点:简单性,有效性。由于接口直接在组件上,因此IIC总线占用的空间非常小,所用引脚少,降低了互联成本。总线长度可达25英尺(1英尺0.3米),并且能够以10Kbps的最大传输速率支持40个组件。根据器件的不同,可利用 DMA 功能来减轻 CPU 的工作量。多主模式功能:同一接口既可用作主模式也可用作从模式。除了接收和发送数据之外,此接口还可以从串行格式转换为并行格式,反之亦然。

通信方式:串行同步半双工通信

物理接口:一根SDA,一根SCL

 

java 使用 tcp 异步半双工通信方式 异步全双工通信协议_数据

 

通信速度:

 

java 使用 tcp 异步半双工通信方式 异步全双工通信协议_通信协议_02

 

发送字节格式:

java 使用 tcp 异步半双工通信方式 异步全双工通信协议_读取数据_03

 

 

通信时序:

起始、终止、应答、信号时序图:

 

java 使用 tcp 异步半双工通信方式 异步全双工通信协议_通信协议_04

 

 

IIC总线应答时序图:  

 

java 使用 tcp 异步半双工通信方式 异步全双工通信协议_通信协议_05

 

起始信号(SCL为高电平时,SDA由高到低)产生后,每个周期的上升沿采样,下降沿允许数据改变。每次发完八个位(1字节)的数据之后,等待应答信号(接收端控制SDA为低电平)。

数据帧格式为:开始条件+设备地址+W/R+应答+数据+应答+ ...+停止位

 

程序示例代码

IIC初始化
//IIC初始化
void IIC3_Pin_Init(void)
{
    //PA8----SCL---推挽输出
    //PC9----SDA---开漏输出
    RCC->AHB1ENR |=0x01<<0|0x01<<2;//端口时钟使能
 
    GPIOA->MODER &=~(0x03<<16);
    GPIOC->MODER &=~(0x03<<18);
    GPIOA->MODER |=(0x01<<16);
    GPIOC->MODER |=(0x01<<18);
 
    GPIOA->OTYPER &=~(0x03<<8);//PB8推挽输出
    GPIOC->OTYPER |=(0x01<<9);//PB9开漏输出
 
 
    //总线在空闲状态
    IIC3_SCL=1;
    IIC3_SDA_OUT=1;
}

起始条件

void IIC3_Start(void)
{
    IIC3_SCL=1;
    IIC3_SDA_OUT=1;
    Delay_us(1);//延时---起始条件的建立时间
    IIC3_SDA_OUT=0;//---产生起始条件
    Delay_us(1);//延时---起始条件的保持时间
    IIC3_SCL=0; //---结束起始条件
}

停止条件

void IIC3_Stop(void)
{
    IIC3_SDA_OUT=0;
    IIC3_SCL=1;
    Delay_us(1);//延时---停止条件的建立时间
    IIC3_SDA_OUT=1; //---产生了停止条件
    Delay_us(1);//延时---本次通信结束到下次通信开始的时间
}
主机发送应答信号
void IIC3_Send_Ack(uint8_t ack)
{
 
 
    IIC3_SCL=0;
    if(ack)//(主机准备数据)
        IIC3_SDA_OUT=1;
    else
        IIC3_SDA_OUT=0;
    Delay_us(2);//延时(数据稳定在数据线上)
    IIC3_SCL=1;//(从机在时钟线上升沿从SDA上采集数据)
    Delay_us(1);//延时(给时间从机读取数据)
 
 
    IIC3_SCL=0;//方便后续的操作;防止意外产生了停止条件
}
主机读取应答信号
uint8_t IIC3_Revice_Ack(void)
{
    uint8_t ack=0;
    IIC3_SCL=0;//(从机准备数据)
    IIC3_SDA_OUT=1;//读模式-----让输出电路与管脚断开!!!!!!!!!!
    Delay_us(2);//延时(给时间从机准备数据并且数据稳定在数据线上)
    IIC3_SCL=1;
    Delay_us(1);//延时 (给时间主机读取数据)
    if(IIC3_SDA_IN)//主机读取SDA线上的数据
        ack=1;
    IIC3_SCL=0;//方便后续的操作;防止意外产生了停止条件
    return ack;
}

 

 

主机发送一个字节并读取一次应答信号

uint8_t IIC3_Send_Byte(uint8_t data)
{
    uint8_t i=0;
    for(i=0; i<8; i++)
    {
        IIC3_SCL=0;
        if((data<<i)&0x80)//(主机准备数据)
            IIC3_SDA_OUT=1;
        else
            IIC3_SDA_OUT=0;
        Delay_us(2);//延时(数据稳定在数据线上)
        IIC3_SCL=1;//(从机在时钟线上升沿从SDA上采集数据)
        Delay_us(1);//延时(给时间从机读取数据)
    }
    IIC3_SCL=0;//方便后续的操作;防止意外产生了停止条件
    return IIC3_Revice_Ack( );
}

主机读取一个字节并读取一次应答信号

uint8_t IIC3_Revice_Byte(uint8_t ack)
{
    uint8_t i=0;
    uint8_t data=0;
    for(i=0; i<8; i++)
    {
        IIC3_SCL=0;//(从机准备数据)
        IIC3_SDA_OUT=1;//读模式-----让输出电路与管脚断开!!!!!!!!!!
        Delay_us(2);//延时(给时间从机准备数据并且数据稳定在数据线上)
        IIC3_SCL=1;
        data<<=1;//空出最低位来存储本次读取的
        if(IIC3_SDA_IN)//主机读取SDA线上的数据
            data |=1;//数据线上电平为高
        Delay_us(1);//延时 (给时间主机读取数据)
    }
    IIC3_SCL=0;//方便后续的操作;防止意外产生了停止条件
    IIC3_Send_Ack(ack);
    return data;
}

头文件声明与宏定义

#define IIC3_SCL      PAout(8)//PA8输出,使用了地址映射
#define IIC3_SDA_OUT  PCout(9)//PC9输出
#define IIC3_SDA_IN   PCin(9)//PC9输入
 
void IIC3_Pin_Init(void);
void IIC3_Start(void);
void IIC3_Stop(void);
uint8_t IIC3_Send_Byte(uint8_t data);
uint8_t IIC3_Revice_Byte(uint8_t ack);