stm32 I2C问题 I2C_CheckEvent()

本文探讨了STM32 IIC接口使用中常见的两个问题:一是I2C_CheckEvent函数在特定条件下的阻塞;二是重复读写过程中出现的停滞。问题主要由IIC配置不当和从设备响应速度不足引起。文中提供了具体的解决方案,包括正确的时钟配置和增加适当的延时。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);


STM32F103ZE I2C1调试手记近日因项目需要,使用100PIN的STM32带FSMC功能驱动3.2"TFTLCD;在使用EEPROM发现原来的I2C程序居然无法使用,郁闷了! 先说一下我这个I2C的驱动程序是经过STM32的官方库函数整理而成,API支持全系列EEPROM以及8BIT地址的其它I2C设备,一直用的很爽。 赶紧查找问题原因,发现连STA信号都无法启动完成,一直循环在等待状态while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); 真是见鬼了,居然连STA信号都无法建立,首先怀疑是硬件问题,于是赶紧查找硬件问题,换EEPROM,无果。奇了怪了,其它项目用的好好的程序,问百度吧?百度一下,这个问题还真多啊,而且还一模一样,问题都没结果,基本的认识是说ST芯片的问题,只能用模拟总线解决。 难道真是芯片问题?这可能吗?这可是ST啊,放眼全球有几家公司能与之抗衡啊。我首先觉得不可能,理由是为什么我其它项目用的好好的,虽说不是同PIN的芯片,可是同系列啊。于是我用其它项目的程序稍做修改,只开放IIC功能把程序下载到103ZE,运行一切正常。这就验证了我的判断,芯片不可能有问题。可为什么不行呢?难道是底层库函数的问题,于是升级库函数,移植到3.0版本的,这样捣鼓一下,一上午间就这样没了,郁闷啊郁闷到差点绝望啊!!!先吃完中午饭,准备下午再战。再问百度吧,找来找去还是没结果,都说是芯片问题。纠结,难不成真的要用模拟I2C总线解决。不甘心啊,土法炼钢吧,把所有初始化程序一个一个注释掉,下载测试,当注释掉LCD初始化程序,奇迹出现了,I2C总线OK了,天啦难道是LCD造成的?查看LCD初始化程序,FSMC初始化程序,没发现问题啊,再加上LCD初始化程序,I2C又不能工作了,看来确实是LCD的功能造成,先把FSMC注释掉,运行I2C又OK了,终于找到你了,就是FSMC造成的,看程序没有任何错误,还是查手册吧,在手册中看到I2C1的SDA脚与FSMC_NADV脚是共用一个端口,难道是这个引起的,查看手册《STM32F101xC/D/E 和 STM32F103xC/D/E勘误表》终于发现问题的根源。原文描述:2.7.15 FSMC和 I2C1以及TIM4_CH2问题描述如果要使用FSMC功能,NADV被配置成复用输出,该信号会被默认地置位。这样就和TIM4_CH2和I2C1的SDA信号发生冲突。暂解决办法当使用FSMC的同,不要使用TIM4_CH2。如果要使用I2C1并且封装允许,就把该功能重映射到PB8/PB9。2.7.13 SDIO 和经过重映射的I2C1配置条件当SDIO配置成1位或者4位模式,会和被重映射到PB8/9引脚上的I2C1发生冲突。冲突发生在以下信号之间:● I2C1_SCL和SDIO_D4● I2C1_SDA和SDIO_D5暂解决办法当使用SDIO的同,不要重映射I2C1的功能到PB8/PB9。问题找到了,就是这个原因啊,天杀的ST,映射功能只能到PB8 PB9端口上,不能映射到任意商品上,可我的PB8 PB9端口被SDIO功能占用了。I2C2端口也被USART3功能占用了。问题是找到了,可最后结果只能模拟总线来实现了。调试结论:1. ST的芯片不会有问题。ST官方的库函数是非常好用的,用的很爽的!2. 当使用大容量芯片具有FSMC功能与I2C1功能同使用, 需要把I2C1映射到PB9 PB9端口上去。3. 如果要同使用FSMC I2C1 SDIO功能I2C1只能用模拟总线方式实现。因为SDIO功能会占用PB8 PB9端口。以下是I2C模拟总线程序源代码
### STM32 I2C 中 `I2C_CheckEvent` 和 `I2C_GetFlagStatus` 的用法与区别 #### 函数定义与功能描述 在 STM32 的标准外设库中,`I2C_CheckEvent` 和 `I2C_GetFlagStatus` 是两个用于处理 I2C 通信状态的函数。 - **`I2C_CheckEvent`**: 此函数通过组合多个标志位的状态来判断当前发生的事件是否匹配指定条件。它主要用于简化复杂的多标志检测逻辑,使得开发者可以更方便地验证特定的 I2C 事件是否发生[^1]。 ```c ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT); ``` - **`I2C_GetFlagStatus`**: 该函数专门用来读取某个具体的硬件标志位的状态(设置或清除)。这允许开发人员单独检查某一个标志位的情况,而不涉及其他标志位的综合分析[^2]。 ```c FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG); ``` #### 使用场景对比 当需要确认一系列复杂条件下触发的具体事件,通常会优先考虑使用 `I2C_CheckEvent`,因为它已经封装好了常见的 I2C 事件模式识别逻辑。而如果只是单纯关心某一具体标志位的变化情况,则更适合调用更为底层的 `I2C_GetFlagStatus` 来获取精确的信息。 例如,在主设备发送地址之后等待从机响应的过程中,可以通过如下方式分别利用这两个API实现相同目的: 对于 `I2C_CheckEvent` 方法: ```c while (I2C_CheckEvent(I2Cx, I2C_EV_MASTER_MODE_SELECT) != SUCCESS); // 等待直到进入主机模式选择阶段成功完成为止 ``` 而对于 `I2C_GetFlagStatus` 则需手动组合不同flags来进行同样的判定操作: ```c while (!(I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB)) || !(I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR))); // 同样等到SB(set bus)以及ADDR(address sent/received)都置位才继续执行下一步动作 ``` 上述例子展示了如何基于各自特性选用合适的工具去达成目标效果的同也体现了两者的差异所在——前者更加高层抽象化易于理解应用;后者则提供了更大的灵活性供定制需求下的深入控制[^3]. #### 总结 综上所述,虽然两者最终都可以达到监控并反应I2C总线活动的目的,但是它们侧重点各有侧重:一个是针对预定义好的典型事务流程提供便捷接口(`I2C_CheckEvent`);另一个则是给予程序员直接访问内部寄存器的能力以便于实施个性化策略(`I2C_GetFlagStatus`)。 ```python # Python 示例仅作结构展示用途,实际为 C 语言环境讨论 def check_event(i2cx, event): return i2cx.check_event(event) def get_flag_status(i2cx, flag): return i2cx.get_flag_status(flag) ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值