IIC通讯接口、协议格式、时序、软件模拟详解

通讯协议2-IIC通讯协议

 

注意:本文章需要配合无际单片机编程-硬件基础2.0教程视频学习。

注意:本文章需要配合无际单片机编程-硬件基础2.0教程视频学习。

 

用途:在单片机电路中,IIC一般用于同一个电路板上,不同芯片之间的数据交互,或不同线路板之间的数据交互(短距离,1-2米内),是最常用的协议之一;

一、硬件接口

1.硬件接口1:

IIC硬件接口一般有2两根信号线,一根是数据线SDA,另一根是时钟线SCL。

SDA: 数据线,负责数据的发送或接收

SCL: 时钟线,提供数据交互的时钟

GND: 2芯片通讯需要共地

 

2.硬件连接2:

IIC总线支持,一个总线上挂多个IIC通讯设备(或芯片),所有接到I2C总线上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上

 

3.IIC通讯说明

  • IIC硬件支持在由多个IIC芯片串联连接,其中的一个是主机,其他的都是从机(和RS485比较类似)。
    • 主机:  启动数据的发送和接收。
    • 从机:被主机寻访操作的设备称为从机,为了进行通讯,每个从设备要有唯一的设备地址,以便于主机寻访
  • 为了避免总线信号的混乱,连接到总线的输出端必须是开漏输出(和IO口的开漏模式一样),所以在IIC电路中,我们必须设计外部上拉电阻;
  • SDA数据线 连接的IO口必须支持双向通讯,(数据的发送和接收)
  • 通讯的时钟由主机的SCL脚 提供
  • 同一时刻,主机只能和某一个从机通讯

 

二、通讯协议

1.  IIC通讯协议格式

IIC通讯由 空闲状态+起始位+有效数据帧+应答(非应答)+停止位 组成

① 空闲状态:SDA  SCL 高电平

② 起始位:

③ 有效数据帧

时钟线SCL 低电平的时候,SDA的数据可以更改,SCL是高电平的时候,是数据检测状态,SDA的电平不能更改; 高位在前

④ 应答位 

 

⑤ 没有应答

 

⑥ 停止位

 

2.  数据通讯举例:

①假如主机发送数据0x65(有应答);  0110 0101  

空闲状态+起始位+有效数据帧+应答(非应答)+停止位

②假如主机发送数据0x65(无应答)

 

3.  IIC通讯时间:

这里以AT24C128芯片为例(下图截自芯片规格书)。

 

三、举例:IO模拟实现IIC通讯(以24C128为例)

1.  硬件电路

 

2.  AT24C128从机地址&读写操作

①AT24C128从机地址

 

②AT24C128写操作

设备地址(含写操作指令)+内存地址(2Bytes)+ 数据

例如对AT24C128芯片内部的地址0x01 写数据0x03:

设备地址(含写操作指令):  0xA0        1010 0000b

内存地址:    0x00 0x01

数据:  0x03

 

③AT24C128读操作

设备地址(含写操作指令)+内存地址(2Bytes)+ 设备地址(含读操作指令)+返回数据

例如对AT24C128芯片内部的地址0x01 :

设备地址(含写操作指令):  0xA0        1010 0000b

内存地址:    0x00 0x01

设备地址(含读操作指令):  0xA1         1010 0001b

返回数据: 返回24C128保存的数据

 

3.  程序:

注意:这里主要的任务是结合代码来进一步理解IIC通讯,没有提供完整的代码(包括:GPIO口的初始化 等)

①起始位

static void I2C_Start(void)
{
     hal_I2C_SDA(1);
     I2C_delay(1);
     hal_I2C_SCL(1);
     I2C_delay(1);
     hal_I2C_SDA(0);
     I2C_delay(1);
}

 

②停止位

static void I2C_Stop(void)
{
     hal_I2C_SDA(0);
     I2C_delay(1);
     hal_I2C_SCL(1);
     I2C_delay(1);
     hal_I2C_SDA(1);
     I2C_delay(1); 
}

 

③应答信号

static void I2C_Ack(void)
{
     hal_I2C_SCL(0);
     I2C_delay(1);
     hal_I2C_SDA(0);
     I2C_delay(1);
     hal_I2C_SCL(1);
     I2C_delay(1);
     hal_I2C_SCL(0);
     I2C_delay(1);
}

 

④无应答

static void I2C_NoAck(void)
{
     hal_I2C_SCL(0);
     I2C_delay(1);
     hal_I2C_SDA(1);
     I2C_delay(1);
     hal_I2C_SCL(1);
     I2C_delay(1);
     hal_I2C_SCL(0);
     I2C_delay(1);
}

⑤等待应答

static unsigned char I2C_WaitAck(void) 
{
     hal_I2C_SDA(1);
     hal_I2C_SDA_IO_Set(1); ///配置为输入模式  
     hal_I2C_SCL(1);
     I2C_delay(1);
     if(hal_I2C_SDA_INPUT())
     {//读到的是高电平
         return 0;  //没有收到应答信号
     }
     hal_I2C_SCL(0);
     hal_I2C_SDA_IO_Set(0);  
     I2C_delay(1); 
     return 1;  ///表示收到了应答信号
}

 

⑥数据发送

static void I2C_SendByte(unsigned char SendByte) 
{
     unsigned char i=0;
     unsigned char temp;
     temp = SendByte;
     for(i=0;i<8;i++)
     {
         hal_I2C_SCL(0);
         I2C_delay(1);
         if(temp&0x80)
         {
             hal_I2C_SDA(1);
         }
         else 
         {
             hal_I2C_SDA(0);
         }
         I2C_delay(1);
         hal_I2C_SCL(1);
         I2C_delay(1);
         temp<<=1;
     }
     hal_I2C_SCL(0);
     I2C_delay(1);
     hal_I2C_SDA(1);
     I2C_delay(1);
}

⑦数据接收

static unsigned char I2C_ReceiveByte(void)  

     unsigned char i;
     unsigned char ReceiveByte=0;
     hal_I2C_SCL(0);
     I2C_delay(1);
     hal_I2C_SDA(1);
     hal_I2C_SDA_IO_Set(1);  //SDA设置成输入
        /// 1010 0111
     for(i=0; i<8; i++)
     { /// 0000 0000
         ReceiveByte <<= 1;
         I2C_delay(1);
         hal_I2C_SCL(1);
         I2C_delay(1);
          if(hal_I2C_SDA_INPUT())
          {   /// 00000100 |=0x01 1010 0111

             ReceiveByte|=0x01;
         }
         hal_I2C_SCL(0);
     }
     hal_I2C_SDA_IO_Set(0); //SDA设置成输出
     I2C_delay(1);
     return ReceiveByte;
}

 

⑧读操作函数:

  • AT24C128读操作时序图:
  • 对应函数

//unsigned short address  读操作地址
//unsigned char *pBuffer  读取的数据通过指针保存获取
//unsigned short len      读取数据的长度
void I2C_Read(unsigned short address,unsigned char *pBuffer, unsigned short len)
{
     unsigned short length;
     length = len;
     I2C_Start();
     I2C_SendByte(0xA0);
     I2C_WaitAck();

     /// AT24C128的地址长度是2个字节;
     I2C_SendByte((address>>8)&0xFF);
     I2C_WaitAck();

     I2C_SendByte(address&0xFF);
     I2C_WaitAck();

     I2C_Start();
     I2C_SendByte(0xA1);
     I2C_WaitAck();

     //dat = I2C_ReceiveByte();
     while(length)
     {
          *pBuffer = I2C_ReceiveByte();
          if(length == 1)
               I2C_NoAck();
          else 
              I2C_Ack(); 
         pBuffer++;
         length–;
     }
     I2C_Stop(); 
}

关于EEPROM的写程序比较复杂,在这里就给大家不介绍了。本节课的任务是大家要能理解EEPROM的底层通讯协议,关于程序代码,大家需要通过实际的项目来实践;

给TA买糖
共{{data.count}}人
人已赞赏
单片机百科单片机自学指南

UART、RS232、RS485通讯协议、工作原理、驱动详解

2023-5-23 20:07:19

单片机百科单片机自学指南

SPI通讯硬件接口、原理、时序、程序详解

2023-5-24 9:24:46

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧