关于stm32IIC通信协议的简单总结(小白总结文系列二)

IIC 通信协议详解

IIC(Inter-Integrated Circuit BUS) 集成电路总线。

1,物理层:

设备之间连接方式

关于stm32IIC通信协议的简单总结(小白总结文系列二)_第1张图片

IIC的物理特性:

1)IIC通信在控制上是一主多从的模式。

2)IIC由sda/scl两条通信线构成。

scl是串行时钟线,用来控制通讯的时钟频率实现数据收发同步;sda是双向串行数据线,用来控制协议中数据的传输。

3) 总线上拉电阻接到电源。I2C 设备空闲时,输出高阻态,当所有设备都空闲,总线呈现高电平状态。

 

4)总线上每个设备都有自己的地址,设备的地址可以进行重置。根据地址不同,可以实现选择不同设备进行通信。

6)当多个主机同时使用总线时,利用仲裁方式决定由哪个设备占用。

5)根据IIC传输数据的速度,分为三种传输模式:

标准模式传输速率为 100kbit/s

快速模式为 400kbit/s

高速模式  3.4Mbit/s(但目前大多 I2C 设备尚不支持高速模式)

2,IIC的功能框图解析:

逻辑控制接收dma请求,应答信号以及中断的响应处理。对应相关状态控制寄存器,控制寄存器;

时钟控制寄存器控制scl时钟线的频率;

sda线实现数据 的接收和发送:

接收:数据通过数据移位寄存器转移到数据寄存器,如果接收的数据是地址,需要与设备本身存储的地址进行对比。

发送:数据从数据寄存器转移到数据移位寄存器,发送到sda总线上。

3,协议层(重点):

起始信号:scl高电平时,sda由高电平变低电平产生一个起始信号;

终止信号:scl高电平时,sda由高低平变高电平产生一个终止信号;

数据信号:scl为高电平的时候,sda低电平是数据0,sda为高电平的时候是数据1;

关于stm32IIC通信协议的简单总结(小白总结文系列二)_第2张图片

IIC通信的4种模式:

● 从发送器模式

● 从接收器模式

● 主发送器模式

● 主接收器模式

iic四种模式时序图分析(都以七位地址为例)

从发送模式时序图:

关于stm32IIC通信协议的简单总结(小白总结文系列二)_第3张图片

主start->主发送写地址->从ack->等待ev1/ev3-1/ev3->从发送数据1->主ack->等待ev3->………->从发送数据n->主nack->等待ev3-2->主stop

关于stm32IIC通信协议的简单总结(小白总结文系列二)_第4张图片

主start->主发送读地址->从ack->等待ev1->主发送数据1->从ack->等待ev2->………->主发送数据n->从ack->等待ev2->主stop->等待ev4

关于stm32IIC通信协议的简单总结(小白总结文系列二)_第5张图片

主start->等待ev5->主发送写地址->从ack->等待ev6/ev8-1->主发送数据1->从ack->等待ev8->………->主发送数据n->从ack->等待ev8-2->主stop

关于stm32IIC通信协议的简单总结(小白总结文系列二)_第6张图片

主start->等待ev5->主发送读地址->从ack->等待ev6->从发送数据1->主ack->等待ev7->…从发送数据n-1->主ack->等待ev7-1->从发送数据n->主nack->等待ev7->主stop

 

注意:始和终止信号都是由主机发出的,连接到I2C总线上的器件,若具有I2C总线的硬件接口,则很容易检测到起始和终止信号。

4,IIC结构体和常用函数:

typedef struct

{

  uint32_t I2C_ClockSpeed;          /*!< Specifies the clock frequency.

                                         This parameter must be set to a value lower than 400kHz */

  uint16_t I2C_Mode;                /*!< Specifies the I2C mode.

                                         This parameter can be a value of @ref I2C_mode */

  uint16_t I2C_DutyCycle;           /*!< Specifies the I2C fast mode duty cycle.

                                         This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */

  uint16_t I2C_OwnAddress1;         /*!< Specifies the first device own address.

                                         This parameter can be a 7-bit or 10-bit address. */

  uint16_t I2C_Ack;                 /*!< Enables or disables the acknowledgement.

                                         This parameter can be a value of @ref I2C_acknowledgement */

  uint16_t I2C_AcknowledgedAddress; /*!< Specifies if 7-bit or 10-bit address is acknowledged.

                                         This parameter can be a value of @ref I2C_acknowledged_address */

}I2C_InitTypeDef;

 

5,IIC常用寄存器

关于stm32IIC通信协议的简单总结(小白总结文系列二)_第7张图片

位11:0 CCR[11:0]快速/标准模式下的时钟控制分频系数(主模式)

该分频系数用于设置主模式下的SCL时钟。

Thigh = CCR ×TPCLK1

Tlow = CCR ×TPCLK1

在I2C快速模式下:

如果DUTY = 0:

Thigh = CCR ×TPCLK1

Tlow = 2 × CCR × TPCLK1

如果DUTY = 1: (速度达到400kHz)

Thigh = 9 × CCR ×TPCLK1

Tlow = 16 × CCR ×TPCLK1

不知道Thigh和Tlow分成这样有什么好处。

 

位14 DUTY快速模式时的占空比

0:快速模式下:Tlow/Thigh = 2;

1: 快速模式下:Tlow/Thigh = 16/9(见CCR)。

关于stm32IIC通信协议的简单总结(小白总结文系列二)_第8张图片

 

位1 SMBUS:选择iic工作模式

位10 ACK应答使能

关于stm32IIC通信协议的简单总结(小白总结文系列二)_第9张图片

 

位15 ADDMODE:寻址模式(从模式)

0:7位从地址(不响应10位地址);

1:10位从地址(不响应7位地址)。

 

位7:1 ADD[7:1]:接口地址 地址的7~1位。

 

6,IIC 通信历程(硬件配置的code 软件配置好烦,不想贴)

 

 

//硬件实现iic向外设写入一个字节

 

uint32_t I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr

{

 

  I2C_GenerateSTART(I2C1, ENABLE);

 

  I2CTimeout = I2CT_FLAG_TIMEOUT;  

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))  

  {

    if((I2CTimeout--) == 0return I2C_TIMEOUT_UserCallback(0);

  } 

  

  

  I2CTimeout = I2CT_FLAG_TIMEOUT;

 

  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);

 

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))

  {

    if((I2CTimeout--) == 0return I2C_TIMEOUT_UserCallback(1);

  }  

 

 

  I2C_SendData(I2C1, WriteAddr);

  

  I2CTimeout = I2CT_FLAG_TIMEOUT;

 

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))

  {

    if((I2CTimeout--) == 0return I2C_TIMEOUT_UserCallback(2);

  } 

 

  I2C_SendData(I2C1, *pBuffer); 

  

  I2CTimeout = I2CT_FLAG_TIMEOUT;  

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))

  {

    if((I2CTimeout--) == 0return I2C_TIMEOUT_UserCallback(3);

  } 

 

  I2C_GenerateSTOP(I2C1, ENABLE);  //发送停止位

  

  return 1;  //返回的结果表示状态

}

 

 

//硬件实现iic从外设读出多个字节

 

uint32_t I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)

{  

 

  I2CTimeout = I2CT_LONG_TIMEOUT;

  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY))

  {

    if((I2CTimeout--) == 0return I2C_TIMEOUT_UserCallback(9);

   }

 

  I2C_GenerateSTART(I2C1, ENABLE);

 

  I2CTimeout = I2CT_FLAG_TIMEOUT;

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))

  {

    if((I2CTimeout--) == 0return I2C_TIMEOUT_UserCallback(10);//这里有问题

   }

 

  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);

 

  I2CTimeout = I2CT_FLAG_TIMEOUT;

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))

  {

    if((I2CTimeout--) == 0return I2C_TIMEOUT_UserCallback(11);

   }

 

  I2C_Cmd(I2C1, ENABLE);

 

  I2C_SendData(I2C1, ReadAddr);  

 

  I2CTimeout = I2CT_FLAG_TIMEOUT;

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))

  {

    if((I2CTimeout--) == 0return I2C_TIMEOUT_UserCallback(12);

   } 

 

  I2C_GenerateSTART(I2C1, ENABLE);

 

  I2CTimeout = I2CT_FLAG_TIMEOUT;

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))

  {

    if((I2CTimeout--) == 0return I2C_TIMEOUT_UserCallback(13);

   }

 

  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);

  

  I2CTimeout = I2CT_FLAG_TIMEOUT;

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))

  {

    if((I2CTimeout--) == 0return I2C_TIMEOUT_UserCallback(14);

   }

 

  while(NumByteToRead)  

  {

    if(NumByteToRead == 1)

    {

      I2C_AcknowledgeConfig(I2C1, DISABLE);//不应答

      I2C_GenerateSTOP(I2C1, ENABLE);//停止位

    }

    I2CTimeout = I2CT_LONG_TIMEOUT;

 

    

while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)==0)  

    {

      if((I2CTimeout--) == 0return I2C_TIMEOUT_UserCallback(3);

    } 

    

{      

      *pBuffer = I2C_ReceiveData(I2C1);//存放到数组

      pBuffer++; //位加

      NumByteToRead--; //量减       

    }   

  }

  I2C_AcknowledgeConfig(I2C1, ENABLE);

  

    return 1;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(关于stm32IIC通信协议的简单总结(小白总结文系列二))