ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

【嵌入式外设精学】Day13|I2C 进阶:ACK/NACK、失败与总线恢复

【嵌入式外设精学】Day13|I2C 进阶:ACK/NACK、失败与总线恢复 【嵌入式外设精学】Day13I2C 进阶ACK/NACK、失败与总线恢复今天解决没应答怎么办SDA 卡在低电平怎么救目录问题 2. 原理 3. 代码 4. 误区 5. 自测 6. 答案1. 问题读写偶发失败拔线一次后整个 I2C 就挂了2. 原理2.1 ACK / NACK每传 1 字节后的第 9 个时钟谁含义从机 ACK低收到了主机读完 NACK高再不读了准备结束2.2 常见失败现象可能原因地址就没应答地址错注意 7 位 vs 含 R/W 的写法、没接好、没上拉传一半 NACK从机忙、数据不对SDA 一直为低从机当时正在发数据被强行打断卡住总线2.3 总线恢复从机把 SDA 拉死时主机可以转成 GPIO手动发 9 个 SCL 脉冲逼它吐出剩下的数据再发一个 STOP重新初始化 I2C 外设3. 代码示例#includestm32f4xx.h#includestdbool.h/* 简化手动 SCL 时钟 恢复脚位按板子改 */staticvoidscl_pulse(void){GPIO_SetBits(GPIOB,GPIO_Pin_6);for(volatileinti0;i50;i){}GPIO_ResetBits(GPIOB,GPIO_Pin_6);for(volatileinti0;i50;i){}}voidi2c_bus_recover(void){inti;/* 假设已把 SDA/SCL 切到 GPIO 开漏输出 */for(i0;i9;i){scl_pulse();}/* 再造一个 STOPSCL 高时 SDA 上升示意 */GPIO_ResetBits(GPIOB,GPIO_Pin_7);for(volatileintk0;k50;k){}GPIO_SetBits(GPIOB,GPIO_Pin_6);for(volatileintk0;k50;k){}GPIO_SetBits(GPIOB,GPIO_Pin_7);/* STOP */}带超时的“等待应答”思路boolwait_flag_timeout(volatileuint32_t*flag,uint32_tms_max){uint32_tnms_max*1000u;while(n--){if(*flag){returntrue;}}returnfalse;/* 超时走恢复/报错 */}4. 常见误区误区正解读完还发 ACK应 NACK 再 STOP失败就 while 死等必须超时恢复只重新 init 不拉时钟从机可能仍占着 SDA地址 8 位当 7 位用写法混用会找不到设备5. 自测主机读多字节最后一字节后发什么SDA 卡低时恢复步骤6. 答案NACK然后 STOP。9 个 SCL 脉冲 STOP再初始化 I2C必要时复位从机电源。作者shuifanyu标签I2CACK总线恢复
返回列表