浅谈IIC协议

IIC 简介


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

在 CPU 与被控 IC 之间、IC 与 IC 之间进行双向传送,高速 IIC 总线一般可达 400kbps 以上。

PS:1. 这里要注意IIC是为了与低速设备通信而发明的,所以IIC的传输速率比不上SPI

         2.IIC是一种半双工的通信方式

I2C 总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。
开始信号: SCL 为高电平时, SDA 由高电平向低电平跳变,开始传送数据。
结束信号: SCL 为高电平时, SDA 由低电平向高电平跳变,结束传送数据。
应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,表示已收到数据。

IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL,其时钟信号是由主控器件产生。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。对于并联在一条总线上的每个IC都有唯一的地址。

 一般情况下,数据线SDA和时钟线SCL都是处于上拉电阻状态。因为:在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。

 IIC的几种状态

1.空闲状态

浅谈IIC协议_第1张图片

 如图所示:IIC总线的SDA和SCL都处于高电平的时候就是总线的空闲状态,此时各个器件的输出级场效应管均处于截止状态,即释放总线,两条总线的上拉电阻将电平拉高。

2.起始信号和停止信号

如上图所示:

起始信号:SCL 为高电平时, SDA 由高电平向低电平跳变,开始传送数据。启动信号是一种电平跳变时序信号,而不是一个电平信号。

停止信号:SCL 为高电平时, SDA 由低电平向高电平跳变,结束传送数据。停止信号也是一种电平跳变时序信号,而不是一个电平信号

3.应答信号

在这里插入图片描述

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

  • 应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;
  • 应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。 
  • 在这里插入图片描述

 0表示应答,1表示非应答。

4.数据有效性

IIC总线进行数据传送时,时钟信号SCL为高电平期间,数据线SDA上的数据必须保持稳定,只有时钟信号SCL为低电平时,数据线上的数据才允许发生改变。

即:SDA在SCL上升沿来之前就必须准备好,而且在下降沿来之前都保持稳定。

在这里插入图片描述

 img

 5.数据的传达

在IIC总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。

从代码认识IIC

在原理图中找到我们的IIC的两根线

浅谈IIC协议_第2张图片

 1.初始化

//初始化IIC
void IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	//RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟 
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOC, ENABLE );	
	   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
 
	IIC_SCL=1;
	IIC_SDA=1;

}

2.起始信号

//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}

3.结束信号

//产生IIC停止信号
void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;//发送I2C总线结束信号
	delay_us(4);							   	
}

4.等待应答

u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;//时钟输出0 	   
	return 0;  
}

5.产生ack应答

void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;//一直为低
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}

6.不产生ack应答

void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;//一直为高
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}	

7.发送一个数据

void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)//一个字节8位
    {              
        IIC_SDA=(txd&0x80)>>7;//将txd逐个位发送   SDA先准备好
        txd<<=1; //取一位后左移一位	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		IIC_SCL=1;
		delay_us(2); 
		IIC_SCL=0;	
		delay_us(2);
    }	 
}

8.读取一个数据

u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL=0; 
        delay_us(2);
		IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

IIC发送数据

在这里插入图片描述

在这里插入图片描述1. 首先由主芯片发送一个start信号。

2.然后发出一个设备地址(用来确定往哪一个芯片写数据),后面接以为表示R/W的读写位。

3.从机将自己的地址与主机发出的地址进行对比,如果相同则认为自己正在被主机寻址,根据R/T位将自己确定为发送器和接收器

4.这个时候主机在等待从机的应答信号,接收到应答信号之后,继续发生访问从机的地址(比如说某个寄存器的地址,可能高八位、低八位这样发)

 5.从机在接收到主机的数据后,给一个应答,然后主机继续发送数据,从机继续n次应答

6.主机产生停止信号,结束传送过程。

IIC读取数据

在这里插入图片描述

 了解了IIC的发生数据,读取数据就变得简单多了

1.开始的时候主芯片要发送一个start信号(这个时候方向位为0,表示写),然后发送一个设备地址(用来判断是哪一个芯片读取数据)和R/W-------写

2.从机回应设备地址是否存在,然后主机再发送7位要读地址(某个寄存器)-------写

3.主机再次发送起始信号(方向位为1,表示读)这个时候才算正式读操作

3.从机会有一个应答信号,然后从机继续发送数据,进行n次数据的发送

5.当数据发送完成时,主机会发生一个nack表示不再接收数据或者然后发送一个停止信号

你可能感兴趣的:(STM32,stm32)