stm32 I2C问题 I2C_CheckEvent()

STM32的IIC接口写的比较复杂,稍不注意,很多地方都会搞错,如果是用GPIO模拟的IIC,问题应该不大,无非应答不不应答的问题。

但是既然STM32自带IIC,并且有接口函数,干嘛不用呢

问题1:

I2C_CheckEvent() 检查时停在此处:

  /* Test on EV5 and clear it */

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

 

问题2:

第一次读写正确后再运行程序停在此处:

  /* Test on EV6 and clear it */

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

 

其他问题:

这基本上就是该应答时没有应答造成

 

解决方法:

针对问题1,多数是因为IIC接口没有配置好,RCC设置中只设置了如下

  /* I2C1 Periph clock enable */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);  

却没有设置:

/* GPIOB Periph clock enable */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

以上两者都是必须的


针对问题2,一般是由于从设备速度不够快造成的

一般在IIC各个读写操作中加入一定的延时即可:

   I2C_8601_ByteWrite(0x02,0x01);

    afxCounterMs=1;

    while(afxCounterMs);     

    I2C_8601_ByteWrite(0x03,0x02);

    afxCounterMs=1;

    while(afxCounterMs);  


STM32F407的I2C通信中,如果遇到错误状态卡住(如`I2C_CheckEvent`长时间等待某个事件未触发),通常涉及硬件或软件配置问题。以下是可能的原因及对应的解决方案: ### 1. **检查I2C引脚配置** 确保I2C的SCL和SDA引脚正确配置为复用开漏模式,并且连接了上拉电阻。如果使用外部上拉电阻,确保其阻值在合理范围内(通常为4.7kΩ)。如果未使用外部上拉电阻,可以启用STM32F407的内部上拉功能[^1]。 ### 2. **初始化配置** 确保I2C外设的初始化配置正确。以下是一个基本的I2C初始化代码示例: ```c void I2C_Init_Config(void) { I2C_InitTypeDef I2C_InitStruct; GPIO_InitTypeDef GPIO_InitStruct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // 配置I2C SCL和SDA引脚 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); // 连接I2C到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_DutyCycle = I2C_DutyCycle_2; I2C_InitStruct.I2C_OwnAddress1 = 0x00; I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStruct.I2C_ClockSpeed = 100000; // 100kHz I2C_Init(I2C1, &I2C_InitStruct); // 启动I2C I2C_Cmd(I2C1, ENABLE); } ``` ### 3. **检查I2C事件和错误标志** 在I2C通信过程中,如果`I2C_CheckEvent`长时间未返回预期事件,可能是由于I2C总线被其他设备占用或者发生了错误。可以通过以下方式检查和清除错误标志: ```c if (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) { // 总线繁忙,等待或复位 I2C_GenerateSTOP(I2C1, ENABLE); // 生成停止条件 I2C_ClearFlag(I2C1, I2C_FLAG_BUSY); // 清除BUSY标志 } ``` ### 4. **处理仲裁丢失和总线错误** 如果发生仲裁丢失或总线错误,需要清除相应的标志: ```c if (I2C_GetFlagStatus(I2C1, I2C_FLAG_ARLO)) { // 发生仲裁丢失 I2C_ClearFlag(I2C1, I2C_FLAG_ARLO); // 清除仲裁丢失标志 } if (I2C_GetFlagStatus(I2C1, I2C_FLAG_BERR)) { // 发生总线错误 I2C_ClearFlag(I2C1, I2C_FLAG_BERR); // 清除总线错误标志 } ``` ### 5. **使用超时机制** 为了避免无限等待某个事件,可以在`I2C_CheckEvent`中添加超时机制: ```c uint32_t timeout = 0xFFFF; while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) { if (timeout-- == 0) { // 超时处理 break; } } ``` ### 6. **检查硬件连接** 确保I2C设备的地址正确,并且设备处于正常工作状态。使用逻辑分析仪或示波器检查SCL和SDA信号是否正常。 ### 7. **调试建议** - 使用STM32的标准外设库或HAL库进行调试,确保库函数的版本兼容。 - 在调试过程中,启用I2C的中断并处理错误中断,以捕获和处理异常情况。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值