STM32的I2C通信

  STM32的两个GPIO引脚,分别用于SCL和SDA,按照I2C规约的时序,像控制LED灯那样控制引脚输出,若是接收数据时则读取SDA线上的电平,那就可以实现I2C通信了,这也是我们在51单片机上的“软件模拟协议”做法。但是STM32上还配有I2C控制器片上外设,只要配置好该外设,它就可以依据规约产生通讯信号。收/发数据置于缓存寄存器中,cpu只要检测该外设的状态和数据寄存器就能完成数据收发。但是利用该外设来实现I2C通讯,存在许多硬件Bug,下来还是简单讲解这种做法。

1. I2C通讯时序

  通俗来讲,IIC的时序就是主机向从设备发出一个数据后,要间隔多少时间从机才会回复,或者说SCL上的信号要维持多久的高电平、低电平才使得SDA的信号正确传输到从机等,这些是在I2C协议明确规约的,在51单片机软件模拟IIC时序时,编程中我们需要自己实现函数去延时。在STM32的I2C控制器下的IIC时序将不需要这么繁琐。如何实现?看下面摘自《STM32中文参考手册_V10.pdf》I2C章节的两图(STM32系统既可以当IIC主机也可以当IIC从机,以I2C主机模式为例)。

主机发送:
这里写图片描述
(1) 主机端代码控制IIC控制器产生起始信号(S),当发生起始信号后,控制器产生事件“EV5”,并会对S

STM32可以通过I2C总线与其他设备进行通信I2C总线是一种串行通信协议,允许多个设备在同一个总线上通信。下面是STM32 I2C通信的基本步骤: 1. 配置I2C总线的GPIO管脚和时钟。 2. 初始化I2C外设,并设置传输速率和数据格式。 3. 发送起始信号和从设备地址。 4. 发送数据或读取数据。 5. 发送停止信号。 以下是一个简单的STM32 I2C通信示例代码,用于向从设备发送数据: ``` #include "stm32f4xx.h" #include "stm32f4xx_i2c.h" #define I2C_SPEED 100000 // I2C传输速率 #define I2C_TIMEOUT 1000 // I2C超时时间 void I2C_Configuration(void) { GPIO_InitTypeDef GPIO_InitStruct; I2C_InitTypeDef I2C_InitStruct; // 使能I2C和GPIO时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // 配置GPIO管脚 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStruct); // 配置GPIO复用功能 GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1); GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1); // 配置I2C参数 I2C_InitStruct.I2C_Mode = I2C_Mode_I2C; I2C_InitStruct.I2C_OwnAddress1 = 0x00; I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStruct.I2C_ClockSpeed = I2C_SPEED; I2C_Init(I2C1, &I2C_InitStruct); // 使能I2C外设 I2C_Cmd(I2C1, ENABLE); } uint8_t I2C_SendData(uint8_t slaveAddr, uint8_t* buffer, uint8_t length) { uint32_t timeout = I2C_TIMEOUT; uint8_t status; // 发送起始信号 I2C_GenerateSTART(I2C1, ENABLE); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) { if (--timeout == 0) return I2C_ERROR_TIMEOUT; } // 发送从设备地址 I2C_Send7bitAddress(I2C1, slaveAddr, I2C_Direction_Transmitter); timeout = I2C_TIMEOUT; while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if (--timeout == 0) return I2C_ERROR_TIMEOUT; } // 发送数据 for (int i = 0; i < length; i++) { I2C_SendData(I2C1, buffer[i]); timeout = I2C_TIMEOUT; while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { if (--timeout == 0) return I2C_ERROR_TIMEOUT; } } // 发送停止信号 I2C_GenerateSTOP(I2C1, ENABLE); return I2C_ERROR_NONE; } int main(void) { uint8_t data[] = {0x01, 0x02, 0x03}; uint8_t result = I2C_SendData(0x50, data, sizeof(data)); while (1); } ``` 需要注意的是,I2C通信中的从设备地址需要根据实际情况修改。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值