2.STM32嵌入式学习(I2C通信)

您所在的位置:网站首页 ads1252u与stm32 2.STM32嵌入式学习(I2C通信)

2.STM32嵌入式学习(I2C通信)

2023-06-20 11:00| 来源: 网络整理| 查看: 265

I2C通信工作原理

I2C通信与USART通信硬件结构对比: USART结构: usart传输主要是通过两根线,一根RX用于接收,一根TX用于发送(注意两个设备RX和TX要交叉相连),是一种全双工,异步的通信方式。我们使用usart串口进行通信的化主要是设定好两个设备的参数,常用的参数是:波特率为115200,数据位长度为8位,无校验位,1位的停止位。在USART章节已经详细的讲解过,这里就不在详细解释 在这里插入图片描述 I2C通信模拟图: I2C通信,他是同步半双工通信。他由一根SCL控制时钟,SDA用来发送数据。他可以挂载多设备,通过主机实现对外部多个从设备的通信,而usart只能是两个设备之间的通信,所以这也是I2C通信优势所在。 在这里插入图片描述 下面我就详细说下I2C是如何进行通信的: 主机拥有对SCL的绝对控制权,以及在空闲时将SDA的控制权交给从机的权利。 1.主机发送/读取从机数据: 主机控制SCL产生时钟信号,在SCL低电平时,主机释放对SDA的控制权,从机可以在这个时候将自己的数据放到SDA线上发送,获得SDA线的暂时控制权。在SCL高电平时,主机重新获得SDA的控制权,这个时候不允许SDA的电平发生跳变,因为主机要读取SDA线上的数据。因为一个字节是8位的,所以上述过程重复8次我们就可以读取一个完整的字节。 2.从机发送/读取主机发送数据: 其实和主机读取从机数据是差不多的。主机控制SCL产生时钟信号,在SCL低电平时,主机将数据放到SDA线。控制SDA的高低电平。在SCL高电平时,从机读取SDA线上的数据。因为一个字节是8位的,所以上述过程重复8次我们就可以读取一个完整的字节。

软件模拟I2C通信协议

I2C协议可以使用硬件来实现,也可以利用软件来自己模拟,使用硬件的来实现的话就要查看数据手册,确定好使用对应的GPIO口,利用STM32官方提供的库函数来实现。使用软件来模拟I2C通信协议,选择任意I/O口就可以,但是需要自己从底层来书写协议。那么我们本章我们通过软件来实现I2C通信。 想要实现I2C通信,我们就需要知道I2C的通信时序,也就对应我们需要书写的6个底层函数。

I2C通信时序

I2C时序可以大致分为6个时序:起始时序,终止时序,发送应答,接收应答,发送一个字节,接收一个字节。 1.起始条件:SCL高电平期间,SDA从高电平变为低电平(下降沿) 在这里插入图片描述 2.终止条件 SCL高电平期间,SDA由低电平变为高电平(上升沿)

在这里插入图片描述 3.发送一个字节 发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次即可发送一个字节 在这里插入图片描述 4.接收一个字节 接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次即可接收一个字节 (主机在接收之前,需要释放SDA)(虚线表示从机控制SDA) 在这里插入图片描述 5.发送应答 发送应答:主机在接收完一个字节之后在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答在下一个时钟接收一位数 在这里插入图片描述

6.接收应答 接收应答:主机在发送完一个字节之后据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)(虚线表示从机控制SDA) 在这里插入图片描述

软件模拟I2C配置流程

1.初始化GPIO端口 2.书写六个基本时序函数

具体代码 //初始化GPIO端口,配置位开漏输出模式 void MyI2C_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11); //封装三个函数 void MyI2C_W_SCL(uint8_t BitValue) { GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue); Delay_us(10); } void MyI2C_W_SDA(uint8_t BitValue) { GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue); Delay_us(10); } uint8_t MyI2C_R_SDA(void) { uint8_t BitValue; BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11); Delay_us(10); return BitValue; } //六个时序 void MyI2C_Start(void) { MyI2C_W_SDA(1); MyI2C_W_SCL(1); MyI2C_W_SDA(0); MyI2C_W_SCL(0); } void MyI2C_Stop(void) { MyI2C_W_SDA(0); MyI2C_W_SCL(1); MyI2C_W_SDA(1); } void MyI2C_SendByte(uint8_t Byte) { uint8_t i; for (i = 0; i uint8_t i, Byte = 0x00; MyI2C_W_SDA(1); for (i = 0; i Byte |= (0x80 >> i);} MyI2C_W_SCL(0); } return Byte; } void MyI2C_SendAck(uint8_t AckBit) { MyI2C_W_SDA(AckBit); MyI2C_W_SCL(1); MyI2C_W_SCL(0); } uint8_t MyI2C_ReceiveAck(void) { uint8_t AckBit; MyI2C_W_SDA(1); MyI2C_W_SCL(1); AckBit = MyI2C_R_SDA(); MyI2C_W_SCL(0); return AckBit; } 结语


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3