IIC协议以及STM32IIC的特性和架构

发布于:2025-03-31 ⋅ 阅读:(14) ⋅ 点赞:(0)

IIC简介

IIC引脚少,硬件实现简单,可拓展性强,不需要UASRT,CAN通讯协议的外部收发设备,被广泛使用在系统内多个集成电路IC(芯片)间的通讯,采用半双工的通讯方式。

IIC一个支持多设备的总线。”总线”指多个设备共用的信号线,在一个IIC通讯总线中,可连接多个IIC通讯设备,支持多个通讯主机及多个通讯从机。

一个IIC总线只使用两条总线线路,一条双向串行数据线(SDA),一条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。 每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备直接的访问。 

          总线通过上拉电阻接到电源。当IIC设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态,由上拉电阻把总线拉成高电平 多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定哪个设备占用总线。具有三种传输模式:标准模式传输速率为100kbit/s,快速模式为400kbit/s,高速模式下可达3.4M/s,但目前大多IIC设备尚不支持高速模式。

软件IIC和硬件IIC

硬件IIC:对应芯片上的IIC外设,有相对应的IIC驱动电路,其所使用的IIC管教也是专用的;        软件IIC:一般是用GPIO管教,用软件控制管脚状态以及模拟IIC通信波形;

区别:

硬件IIC的效率要远高于软件的,而软件IIC不受引脚限制,接口比较灵活。硬件IIC用法复杂,模拟IIC流程更加清楚 。硬件IIC速度比模拟快,并且可以用DMA 

软件IIC是通过GPIO,软件模拟寄存器的工作方式,而硬件IIC是直接调用内部寄存器进行配置。如果要从具体硬件上来看,可参考芯片手册。因为固件IIC的端口是固定的,所以会有所区别。模拟IIC可以在任何管脚上,硬件IIC在固定管脚上  

IIC总线协议

1.  主机写数据到从机

 S:数据由主机传输至从机

 SLAVE ADDRESS : 从机地址                 

 P:数据传输结束 

起始信号产生后,所有从机就开始紧接下来广播的从机地址信号。IIC总线,每个设备的地址都是唯一的,当主机广播的地址与某个设备的地址相同时,这个设备就被选中了,没被选中的设备讲会忽略之后的数据信号。根据IIC协议,这个从机地址可以是7位或10位。

地址位之后,传输方向选择位,为0:表示数据传输方向是由主机传输至从机,即主机向从机写数据。为1:则相反。从机接收传输方向选择位后,主机或从机会返回一个应答(ACK)或非应答(NACK)信号,只有接收到应答信号后,主机才能继续发送或接收数据。

2.主机读数据到从机

       配置方向传输位为”读数据”方向。广播完地址后,接收到应答信号后,从机开始向主机返回数据(DATA),数据包大小也为8位,从机每发送完一个数,都会等待主机的应答信号(ACK),重复这个过程,可以返回N个数据,N没有限制大小。当主机希望停止接收数据时,就向从机返回一个非应答信号(NCAK),则从机自动停止数据传输

3.复合通讯 

该传输过程有两次起始信号(S),在第一次传输过程中,主机通过SLAVE_ADDRESS寻找到从设备后,发送一段”数据”,这段数据通常用于表示从设备内部的寄存器或存储器地址;第二次传输中,对该地址的内容进行读或写。也就是说,第一次通讯是告诉从机读写地址,第二次则是读写的实际内容。

IIC通信

1.空闲状态    

IIC总线的SDA和SCL两条信号线同时处于高电平时,规定位总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。

2.开始信号和停止信号    

起始信号:当SCL为高电平期间,SDA有高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。     停止信号:当SCL为高电平期间,SDA由低到高的跳变;停止信号也是一种高电平跳变时序信号,而不是一个电平信号      起始信号和停止信号一般由主机产生

3.应答信号

   

 发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位) 表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。      

对于反馈有效应答位ACK的要求是,接收器在第九个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。      

如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。

4.数据的有效性

   

IIC总线进行数据传输时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。SDA数据线在SCL的每个时钟周期传输一位数据。     即:数据在SCL的上升沿到来之前就需准备好。并在下降沿到来之前必须稳定   

5.数据传输      

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

STM32的IIC特性及架构

1.软件模拟协议:

使用CPU直接控制通讯引脚的电平,产生出符合通讯协议标准的逻辑。

2.硬件实现协议:

由STM32的IIC片上外设专门负责实现IIC通讯协议,只要配置好该外设,它就会自动根据协议要求产生通讯信号,收发数据并缓存起来,CPU只要检测该外设的状态和访问数据寄存器,就能完成数据收发。这种由硬件外设处理IIC协议的方式减轻了CPU的工作,且使软件设计更加简单。     STM32的IIC外设可用作通讯的主机及从机,支持100Kbit/s和400Kbits/s的速率,支持7位、10位设备地址,支持DMA数据传输,并具有数据校验功能。

架构图:

时钟控制逻辑        

 SCL线的时钟信号,由IIC接口根据时钟控制寄存器(CCR)控制,控制的参数主要位时钟频率。

可选择IIC通讯的“标准/快速”模式,这两个模式分别对应100/400Kbits/s的通讯速率。    ·

在快速模式下可选择SCL时钟的占空比,可选T(low)/T(high) = 2或T(low)/T(high)=16/9模式。

CCR寄存器中12位的配置因子CCR,它与IIC外设的输入时钟源共用作用,产生SCL时钟。STM32的IIC外设输入时钟源位PCKL1.

计算时钟频率    

标准模式    T high = CCR *T pckl1  T low= CCR*Tpclk1    

快速模式中 Tlow/Tlow =2时:Thigh = CCR*Tpckl1    T low = 2*low*Tpckl1      

快速模式中 Tlow/Tlow =16/9时:Thigh = 9*CCR*Tpckl1    T low = 16*low*Tpckl1

PCLK1 = 36MHz,想要配置400Kbits/s 方法:

PCLK时钟周期: TPCLK1 = 1/36 000 000

目标SCL时钟周期:  TSCL = 1/400 000

SCL时钟周期内的高电平时间: Thigh = TSCL/3

SCL时钟周期内的低电平时间: Tlow  = 2*TSCL/3 计算CCR的值 :  

CCR = THIGH/TPCLK1 = 30 计算出来的值写入到寄存器即可          

数据控制逻辑    

IIC的SDA信号主要连接到数据移位寄存器上,数据移位寄存器的数据来源及目标是数据寄存器(DR)、地址寄存器(OAR)、PEC寄存器以及SDA数据线。

·当向外发送数据的时候,数据移位寄存器以“数据寄存器”为数据源,把数据一位一位地通过SDA信号线发送出去。

·当从外部接收数据的时候,数据移位寄存器把SDA信号线采样到的数据一位一位地存储到”数据寄存器”中。

STM32的IIC的通讯过程

使用IIC外设通讯时,在通讯的不同阶段它会对”状态寄存器(SR1和SR2)”的不同数据位写入参数,通过读取这些寄存器标志来了解通讯状态。

1.主发送器

·控制产生起始信号(S),当发生起始信号后,它产生事件”EV5”,并会对SR1寄存器的 SB 位置1,表示起始信号已经发生。      

·发生设备地址并等待应答信号,若有从机应答,则产生时间 EV6 及 EV8 ,这时SR1寄存器的 ADDR位及 TXE位被置1,ADDR位1 表示地址已经发送,TEX表示数据寄存器为空。(可参STM32中文参考手册)

主发送器通讯过程

·往IIC的数据寄存器DR写入要发送的数据,这时TXE位会被充值0,表示数据寄存器非空,IIC外设通过SDA信号线一位位把数据发送出去后,又会产生EV8事件,即TXE被置1,重复这个过程,可发送多个字节。      

·发送数据完成后,控制IIC设备产生一个停止信号P,这个时候产生EV2事件,SR1的TEX位及BTF位被置1,表示通讯结束。

以硬件IIC为例(主机向从机发送字节IIC通讯配置):

void I2C_WriteByte(uint8_t addr,uint8_t data)
{

    while (I2C_GetFlagStatus(I2C1,  I2C_FLAG_BUSY));  //检查总线是否繁忙
	
    I2C_GenerateSTART(I2C1,  ENABLE);                //开启IIC1
    while( !I2C_CheckEvent(I2C1,  I2C_EVENT_MASTER_MODE_SELECT)); //EV5,主模式
	
	 I2C_Send7bitAddress(I2C1,OLED_ADDRESS, I2C_Direction_Transmitter); //发送器件地址
	 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

	 I2C_SendData(I2C1,  addr);   //发送寄存器地址
   while(!I2C_CheckEvent(I2C1,  I2C_EVENT_MASTER_BYTE_TRANSMITTING));

	I2C_SendData(I2C1,  data);   //发送数据
	 while(!I2C_CheckEvent(I2C1,  I2C_EVENT_MASTER_BYTE_TRANSMITTING));

  I2C_GenerateSTOP( I2C1,  ENABLE); //关闭IIC1


}
IIC结构体

以IIC1为例:

void I2C_Configuration(void)
{

    I2C_InitTypeDef   I2C_InitStructure;
    GPIO_InitTypeDef   GPIO_InitStructure;
	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB ,  ENABLE);
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE );
	
	//PB6 --SCL ;PB7 --SDA
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_OD;
	GPIO_InitStructure.GPIO_Pin   =  GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed =  GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

	
    I2C_DeInit(I2C1);                                    //使用IIC1
    I2C_InitStructure.I2C_Ack  =  I2C_Ack_Enable;        //选择使能或者关闭响应
	I2C_InitStructure.I2C_AcknowledgedAddress =  I2C_AcknowledgedAddress_7bit;//指定地址长度(7或10)
	I2C_InitStructure.I2C_ClockSpeed = 400000 ;          //配置SCL时钟频率
	I2C_InitStructure.I2C_DutyCycle  = I2C_DutyCycle_2 ; //选择占空比
	I2C_InitStructure.I2C_Mode =  I2C_Mode_I2C;          //选择IIC模式
	I2C_InitStructure.I2C_OwnAddress1 = 0X30 ;           //配置IIC设备地址
	I2C_Init(I2C1,&I2C_InitStructure );                  //初始化IIC结构体
    I2C_Cmd(I2C1,ENABLE);                                //使能IIC1

}