一、简介

IIC(Inter-integerted Circuit)集成电路总线,该通信协议由NXP(原PHILIPS)公司设计,多用于主控制器和从器件间的主从通信,在小数据量场景下使用,传输距离短,任意时刻只能有一个主机的特性。

二、物理层

  1. IIC通信要求需要两条线路完成数据传输,一条是串行时钟线SCL和一条串行数据线SDA

使用线路:
时钟线 – SCL
数据线 – SDA
(IIC为半双工通信)

  1. 每个连接到总线上的设备都可以通过唯一的地址和其他器件通信,主机/从机角色和地址可以配置,主机可以作为主机发送器和主机接收器

三、协议内容

IIC通信协议把信息分为两种类型的帧

  1. 地址帧:用于Master指明信息该发往哪个Slave。(从设备地址)

  2. 数据帧:由Master发往Slave的数据或是Master接收到来自于Slave的数据(一次读写单位为8bit,高位先发)

四、数据传输状态

(1)数据为有效性规定

  1. 时钟信号为高电平(High)期间,数据线上的数据必须保持稳定

  2. 时钟信号为低电平(Low)期间,数据线上方才允许变化

即:数据在时钟线SCL的上升沿到来之前就需准备好,并在下降沿到来之前必须保持稳定

(2)空闲状态

逻辑解析:当IIC总线的数据线SDA和时钟信号当IIC总线的数据线SDA和时钟线SCL同时处于高电平(High)时,规定总线为空闲状态

此时各个器件输出及场效均处在截至状态

即:由两条信号线的上拉电阻把电平拉高

(3)起始信号

逻辑解析:时钟线SCL为高电平期间(High),数据线SDA由高电平向低电平变化(下降沿)表示起始信号
(在时钟线SCL为高电平时,拉低数据线SDA)
在这里插入图片描述

程序逻辑实现:

void IIC_Start(void)
{
	IIC_SDA_OUT();
	IIC_SDA = 1;
	IIC_SCL = 1;
	delay_us(5);
	IIC_SDA = 0;	// Start:在SCL为高电平时拉低SDA
	delay_us(5);
	IIC_SCL = 0;
}

(4)终止信号

逻辑解析:时钟线SCL为高电平期间(High),数据线SDA由低电平向高电平变化(上升沿) 表示终止信号
(在时钟线SCL为高电平时,拉高数据线SDA)
在这里插入图片描述

程序逻辑实现:

void IIC_Stop(void)
{
	IIC_SDA_OUT();
	SCL = 0;
	SDA = 0;
	delay_us(5);
	SCL = 1;
	delay_us(5);
	SDA = 1;	// Stop:在SCL为高电平时,拉高SDA
	delay_us(5);
}

(5)应答信号

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

  1. 应答位为低电平(Low Level)时,规定为有效应答位(ACK,简称应答位)

表示接收器已经成功接收了该字节数据

  1. 应答位为高电平(High Level)时,规定为无效应答位(nACK)

一般表示接收器没有接收成功该字节数据

对反馈有效应答信号的ACK的要求是:

  1. 接收器在第9个时钟脉冲之前的时钟线SCL低电平期间将数据线SDA拉低(Low),并且确保在该时钟的高电平期间为稳定的低电平(Low Level)

  2. 如果接收器是Master,则在它收到最后一个字节后发送一个nACK信号,以通知被控发送器结束数据发送,并释放数据线SDA,以便主控制器发送一个停止信号

程序逻辑实现:

// 1、Master接收ACK信号
uint8_t IIC_MasterWaitACK(void)
{
	uint8_t uErrTime = 0;
	IIC_SDA_OUT();
	IIC_SDA = 1;
	delay_us(2);
	IIC_SCL = 1;
	delay_us(2);
	IIC_SDA_IN();
	while(IIC_SDAin)
	{
		uErrTime++;
		if(uErrTime > 300)
		{
			IIC_SDA_OUT();
			IIC_Stop();
			return 1;	// 应答失败
		}
	}
	IIC_SDA_OUT();
	IIC_SCL = 0;
	return 0;	// 应答成功
}

// 2、Master发送ACK信号
void Master_SendAck(void)
{
	IIC_SCL=0;
	IIC_SDA_OUT();
	IIC_SDA=0;
    delay_us(2);
	IIC_SCL=1;
    delay_us(2);
	IIC_SCL=0;
}

// 3、Master不发送ACK信号
void Master_SendnAck(void)
{
	IIC_SCL = 0;
	IIC_SDA_OUT();
	IIC_SDA = 1;
    delay_us(2);
	IIC_SCL = 1;
    delay_us(2);
	IIC_SCL = 0;
}			

(6)数据传输格式

字节传输与应答

  1. 每一个字节必须保证是8bit长度

  2. 数据传送时先传最高位(MSB)

  3. 每一个被传送的字节后面都必须跟随1bit的应答位(即每一帧数据共9bit)

在IIC总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制)

即:在时钟线SCL串行时钟的配合下,在数据线SDA上逐位的串行传送每一位数据

数据位传输是边沿触发

(7)总线寻址

IIC协议采用7bit的寻址字节(寻址字节是起始信号的第一个字节)

数据位定义:

| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |

D7 ~ D1位:从机地址
D0位:数据传输方向(读写位)

  0:表示主机向从机写数据
  1:表示主机向从机读数据

主机向从设备中写寄存器(数据格式)

在这里插入图片描述

主机向从设备中读寄存器值(数据格式)

在这里插入图片描述

(8)数据收发

使用IIC通讯协议进行数据的接收与发送逻辑(单字节实现)

程序逻辑实现

void IIC_SendByte(uint8_t Data)
{
	uint8_t i;
	IIC_SDA_OUT();
	IIC_SCL = 0;
	for(i=0; i<8; i++)
	{
		IIC_SDA = ((Data&0x80)==0x80)?1:0;
		Data <<= 1;
		delay_us(2);
		IIC_SCL = 1;
		delay_us(5);
		IIC_SCL = 0;
		delay_us(2);
	}
}

uint8_t IIC_ReadByte(uint8_t ack)
{
	uint8_t i,receive=0;

	IIC_SDA_IN();
	
	for(i=0; i<8; i++)
	{ 
		IIC_SCL = 0; 
		delay_us(2);        
		IIC_SCL   = 1;	 
		receive <<= 1;
		if(IIC_SDAin)
          receive |= 0x01; 
		delay_us(2);		
	}	  
  
	if(!ack)
		Master_nAckCTP();
	else
		Master_AckCTP();

	IIC_SDA_OUT();
	
	return receive;
}
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐