IIC通信协议

本文详细介绍了IIC总线,包括其物理层构成、主要特点(同步通信、主从设备角色)、高阻态、地址分配(主机地址、从机地址及寻址规则),以及软件模拟实现。重点阐述了数据传输、寻址模式和协议时序,对IIC通信进行了全面解析。
摘要由CSDN通过智能技术生成

IIC

目录

IIC

IIC简介

IIC的物理层

IIC主要特点

IIC的高阻态

IIC地址

主机地址

从机地址

从机地址规定

IIC器件地址

IIC协议

软件模拟IIC

IIC数据发送


IIC简介

IIC总线是一种由NXP公司开发的两线式串行总线,用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机。

在CPU与被控IC之间、IC与IC之间进行双向传送,通信速率一般在100kHZ-400kHZ(48.8kb/s),高速IIC总线一般可达400kbps以上。IIC是为了与低速设备通信而发明的,所以IIC的传输速率比不上SPI。

 

IIC的物理层

IIC一共只有两个总线,一条是双向的串行数据线SDA,一条是串行时钟线SCL。

SDA数据线:用来传输数据的

SCL时钟线:用来控制数据发送的时序的

所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的SCL都接到总线的SCL上。IIC总线上的每个设备都有自己唯一的地址,来确保不同设备间访问的准确性。

IIC主要特点

通信方式有异步和同步通信,IIC是同步通信。

异步:发送方要等接收方响应才继续通信,阻塞的通信方式

同步:不用管接收方是否有回应,是非阻塞的通信方式

通常为了方便把IIC设备分为主设备和从设备,基本上谁控制时钟线(即控制SCL时钟线的电平高低转换)谁就是主设备

IIC主设备功能:主要产生时钟,产生起始信号和停止信号

IIC从设备功能:可编程的IIC地址检测,停止位检测

IIC的一个优点是它支持多主控,其中任何一个能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。在任何时间点只能有一个主控。

SCL和SDA都需要接上拉电阻保证数据的稳定性,减少干扰

IIC是半双工通信,同一时间只可以单向通信

为了避免总线信号的混乱,要求各设备连接到总线的输出端时必须是漏极电路(OD)输出或集电极开路输出(OC)。

IIC的高阻态

漏极电路(Open Drain)即高阻状态,适用于输入/输出,其可独立输入/输出低电平和高阻状态,若需要产生高电平,则需使用外部上拉电阻。

高阻状态:高阻状态是三态门电路的一种状态,逻辑门的输出有高低电平两种状态外,还有高阻状态的门电路。高阻态相当于隔断状态。三态门都有一个EN控制使能端来控制门电路的通断。处于高阻态的三态门是与总线隔离开的,这样总线可以同时被其他电路占用。EN=0时,Y为高阻状态。

IIC的所有设备是连接在一根总线上的,那么进行通信的时候往往只是几个设备进行通信,那这时候其余空闲的设备可能会受到总线干扰,或者干扰到总线。

为了避免总线信号的混乱,IIC的空闲状态只能有外部上拉,而此时空闲设备被拉到了高阻态,也就是相当于断路,整个IIC总线只有开启了的设备才会正常进行通信,而不会干扰到其他设备。

IIC地址

主机地址

可随意设置,从设备必须配置地址

从机地址

IIC从地址有三种类型,7位、8位和10位,厂商采用不同的地址约定。

7位寻址,如下图oled写入模式的从机地址

IIC总线规范规定,标准模式从机地址为7位长,其次是读写位。

在7位寻址过程中,从机地址在启动信号后的第一个字节开始传输,该字节的前7位为从机地址,第8位为读写位,0表示写,1表示读,它决定了传输的方向,第一个字节的第8位是0,表示主机会写信息到被选中的从机。

从机地址规定

任何IIC设备都必须遵循这个标准,USB2xxx传输的从机地址即为这7bit地址,不含读写位,读写位会根据不同的函数自动添加进去。

保留地址:IIC规范保留了两组和8个地址,1111xxx和0000xxx。

这些地址用于特殊用途。

8位地址

一些厂商在提供从机地址的时候说的是包含了读写位的8bit地址,比如他说写地址为0x92,读地址为0x93,8位寻址的情况下需要将这个地址的前7bit提取出来,然后传入USB2xxx的接口函数,如图

判断厂商提供的地址是7bit模式地址还是8bit地址的方式:7bit地址模式下,地址的取值范围是0x07-0x78,超过了可能就是8bit。

10位寻址

IIC总线的10bit寻址和7bit寻址是兼容的,这样就可以在同一个总线上同时使用7bit地址和10bit地址模式的设备,在10bit寻址模式中,从机地址由7个有效位和3个可选位组成。有效位用于指定从机的地址,而可选位则用于扩展寻址范围。

在IIC总线上,主机发送起始位和读/写位后,紧接着发送7个有效位来指定从机地址。如果需要使用10位寻址模式,则在发送完7个有效位后,再发送3个可选位。

通过10位寻址模式,可以支持更多的从机地址,扩展了总线上可连接的设备数量。不过不是所有的设备都支持10位寻址模式,所以在使用时需要查看设备的规格说明书来确定支持的寻址模式。

IIC器件地址

每一个IIC器件都有一个器件地址,有的器件地址在出厂时地址就设定好了,用户不可以更改。有的器件例如EEPROM,前四个地址已经确定为1010,后三个地址由硬件链接确定的,所以IIC总线最多能连8个EEPROM芯片。

IIC总线最多可以挂多少个设备:有IIC地址决定,8位地址,减去一位广播地址,2^7=128,0x00不用,所以理论上可以挂127个从器件。

但是  IIC协议虽然没有规定总线设备最大数目,但是规定了总线电容不能超过400pF。管脚都是有输入电容的,PCB上也会有寄生电容,所以会有一个限制,有人测验大概是不超过8个器件。

IIC协议

总线时序图

初始(空闲)状态:SCL和SDA都保持高电平

起始信号:SCL为高电平,SDA由高电平变为低电平,数据开始发送

结束信号:SCL为高电平,SDA由低电平变为高电平,数据传送结束

有效的数据位传输:在IIC总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,数据在SDA上从高位向低位依次串行传送每一位数据。

应答信号:发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。

应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节。

应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。

软件模拟IIC

初始(空闲)状态

void IIC_Init()

{  

    scl = 1;

    delay_us(5);

    sda = 1;

    delay_us(5);

}

起始信号:SCL保持高电平,SDA由高电平(>4.7us)变为低电平(>4us),SCL变为低电平。

//起始信号

void IIC_Start()

{

    scl = 1;

    sda = 1;

    delay_us(5);

    sda = 0;

    delay_us(5);

    scl = 0;

}

结束信号:SCL保持高电平(>4us),SDA由低电平变为高电平(>4.7us),SDA变为低电平

//结束信号

void IIC_Stop()

{

    scl = 1;

    sda = 0;

    delay_us(5);

    sda = 1;

    delay_us(5);

    sda = 0;

}

数据有效性

IIC信号在数据传输中,当SCL=1高电平时,数据线SDA必须保持稳定状态,不允许有电平跳变,只有在时钟线上的信号为低电平期间,数据线上的电平状态才允许变化。

SCL=1时,数据线任何的电平状态变换会看做是总线的起始信号或者终止信号。所以在传输数据的过程中,SCL时钟线会频繁的转换电平以保证数据的稳定传输。

应答信号:主机SCL拉高,读取从机SDA的电平,为低电平表示产生应答

每发送一个字节(8个bit),在一个字节传输的8个时钟后的第九个时钟期间,接收器接收数据后必须返回一个ACK应答信号给发送器,这样才能进行数据传输。

//应答

void IIC_ACK()

{

    scl = 0;

    sda = 0;

    delay_us(1);

    scl = 1;

    delay_us(5);

    scl = 0;

}
//非应答

void IIC_NACK()

{

    scl = 0;

    sda = 1;

    delay_us(1);

    scl = 1;

    delay_us(5);

    scl = 0;

}

//应答信号sda为低电平,非应答为高电平

//所以读取SDA的状态来判断是什么信号

void IIC_read_ACK()

{

    char flag;//标志位,记录sda的状态

    sda = 1;//在时钟脉冲9期间释放数据线

    delay_us(2);

    scl = 1;

    delay_us(5);

    flag = sda;//在这个期间记录下sda的电平状态

    delay_us(5);

    scl = 0;

return flag;

}

IIC数据发送

数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。

当一个字节按数据位从高到低的顺序传输完成后,紧接着从设备将拉低SDA线,回传给主设备一个应答位ACK,此时才认为一个字节真正的被传输完成,如果一段时间内没有收到从机的应答信号,则自动认为从机已正确接收到数据。

IIC写数据

IIC的每一帧数据由9bit组成

如果是发送数据,则包含8bit数据+1bitACK

如果是设备地址数据,则包含7bit设备地址+1bit方向位+1bitACK

IIC总线数据格式:

IIC写数据:

//在SCL为高电平期间,发送数据,发送8次,,数据从高到低

//传输期间保持传输稳定,数据线仅可以在SCL为低电平时改变

void IIC_Write_Byte(chra dataSend)

{

    int i;

    for(i = 0;i < 8;i++){

        //拉低时钟开始数据传输

        scl = 0;

        //获取最高位给sda

        sda = dataSend & 0x80;//与1000 0000获得dataSend最高位

        delay_us(5);//发送数据建立时间

        scl = 1;//拉高时钟开始数据发送

        delay_us(5);

        scl = 0;//发送完毕拉低

        delay_us(5);//准备下一个数据位

        dataSend = dataSend << 1;//从高到低发送,左移获得下一位数据

    }

}

主机向从机发送数据时:

  1. 主机产生start信号
  2. 发送从机地址,第8位数据方向位为0,表明主机要发送数据
  3. 主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,若相同,则认为自己正在被主机寻址,根据R/T位将自己确定为接收器
  4. 这时主机就等待从机的应答信号
  5. 当主机接收到应答信号后,发送要访问的从机的寄存器地址,然后等待从机的应答信号
  6. 当主机收到应答信号,发送n个字节的数据,继续等待从机的n次应答信号
  7. 主机产生停止信号,结束传送过程

IIC读数据

//读数据

void IIC_Read_Byte()

{

    int i,value = 0;

    delay_us(1);

    for(i = 0;i < 8;i++){

        value <<= 1;

        scl = 1;

        delay_us(1);

        if(sda = 1){

            value++;

        }

        delay_us(1);

        scl = 0;

        delay_us(1);

    }

    return value;

}

主机从 从机读数据时:

  1. 主机产生start信号
  2. 发送从机地址,此时该地址第8位为0,表示向从机写命令
  3. 主机等待从机的应答信号ACK
  4. 主机收到应答信号时,发送要访问的地址,继续等待从机的应答信号
  5. 当主机收到应答信号后,主机要改变通信模式。(主机由发送变为接收,从机由接收变为传送)所以主机重新发送一个开始start信号,然后发送从机地址,这时该地址的第8位为1,表明将主机设置为接收模式开始读数据。
  6. 然后主机等待从机的应答信号,当主机收到应答信号时,就可以接收1个字节的数据,当接收完成后,主机发送非应答信号,表示不再接收数据。
  7. 主机进而产生停止信号,结束传送过程。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
IIC(Inter-Integrated Circuit)通信协议是一种串行通信协议,也被称为I2C(Inter-IC)协议。它是由飞利浦(Philips)公司在1982年开发的,用于在集成电路之间进行通信。 在Keil软件中,可以使用C语言编写IIC通信协议的代码。下面是一个简单的示例代码,用于在Keil中实现IIC通信协议: ```c #include <reg51.h> // 定义IIC通信相关的引脚 sbit SDA = P1^0; sbit SCL = P1^1; // IIC起始信号 void IIC_Start() { SDA = 1; SCL = 1; delay(); // 延时一段时间 SDA = 0; delay(); SCL = 0; } // IIC停止信号 void IIC_Stop() { SDA = 0; SCL = 1; delay(); SDA = 1; delay(); } // IIC发送一个字节的数据 void IIC_SendByte(unsigned char dat) { unsigned char i; for (i = 0; i < 8; i++) { SDA = (dat & 0x80) >> 7; // 发送数据的最高位 dat <<= 1; SCL = 1; delay(); SCL = 0; delay(); } } // IIC接收一个字节的数据 unsigned char IIC_ReceiveByte() { unsigned char i, dat = 0; SDA = 1; for (i = 0; i < 8; i++) { dat <<= 1; SCL = 1; delay(); dat |= SDA; // 接收数据的最高位 SCL = 0; delay(); } return dat; } // 延时函数 void delay() { unsigned int i, j; for (i = 0; i < 100; i++) for (j = 0; j < 100; j++); } int main() { // 主控制器初始化 SDA = 1; SCL = 1; // 发送数据 IIC_Start(); IIC_SendByte(0x50); // 发送设备地址 IIC_SendByte(0x01); // 发送数据 IIC_Stop(); // 接收数据 IIC_Start(); IIC_SendByte(0x51); // 发送设备地址 unsigned char data = IIC_ReceiveByte(); // 接收数据 IIC_Stop(); while (1); } ``` 这段代码实现了IIC通信协议的基本功能,包括发送起始信号、停止信号、发送数据和接收数据等操作。你可以根据具体的需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

◣星河◢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值