当前位置: 首页 > news >正文

APM32芯得 EP.34 | 告别I2C“假死”——APM32F103硬件IIC防锁死设计

  如遇开发技术问题,欢迎前往开发者社区,极海技术团队将在线为您解答~
极海官方开发者社区​https://community.geehy.cn/

《APM32芯得》系列内容为用户使用APM32系列产品的经验总结,均转载自21ic论坛极海半导体专区,全文未作任何修改,未经原文作者授权禁止转载。

目录

一、 引言

二、 APM32F103硬件IIC基础与错误寄存器分析

三、 硬件IIC错误恢复的核心思想

四、 详细的错误恢复步骤与代码实现

五、 预防优于治疗:IIC通信的稳定性设计建议

六、 总结


一、 引言

  1. 背景介绍

    • APM32F103系列MCU作为一款高度兼容的国产芯片,具有应用广泛性。
    • 硬件IIC外设的优势(效率高、节省CPU资源)与常见痛点(易锁死、抗干扰能力弱)。
  2. 问题阐述

    • 描述硬件IIC在通信过程中可能出现的错误场景:总线忙(BUSY)、仲裁丢失、地址无应答(ACK Failure)、数据无应答、总线错误等。
    • 这些错误如何导致IIC控制器进入“挂起”或“锁死”状态,表现为SDA或SCL线被拉低,整个通信瘫痪。
  3. 本文目标

    • 提供一套针对APM32F103硬件IIC的、系统性的错误检测、诊断和恢复方案,帮助开发者构建鲁棒的IIC通信程序。
  4. 软硬件IIC对比

    5.png

二、 APM32F103硬件IIC基础与错误寄存器分析

  1. 硬件IIC主要寄存器概览
    • 控制寄存器(IIC_CTLR1, IIC_CTLR2):配置使能、中断、ACK等。

      1.png

      3.png

    • 状态寄存器(IIC_STAR1, IIC_STAR2):核心重点,包含各种错误和事件状态标志。

  2. 关键错误状态标志详解
    • BUSY** (IIC_STAR2[1]):总线忙标志,指示IIC总线是否正处于通信状态。

    • BERR** (IIC_STAR1[8]):总线错误,检测到非法的起始或停止条件。

    • AL** (IIC_STAR1[9]):仲裁丢失,多主模式下失去总线控制权。

    • AE** (IIC_STAR1[10]):应答失败,发送地址或数据后未收到ACK。

    • OVRUR** (IIC_STAR1[11]):超载/溢出错误,数据寄存器读写过快。

    • TTE** (IIC_STAR1[14]):超时错误。

      4.png

三、 硬件IIC错误恢复的核心思想

  1. 根本原因:时钟线(SCL)或被错误拉低的数据线(SDA)导致总线死锁。
  2. 恢复核心模拟时钟脉冲。通过软件控制GPIO,产生一定数量的时钟信号(SCL),迫使从设备释放SDA线,从而解除总线锁死状态。
  3. 恢复流程三步走
    • 第1步:检测与诊断 - 通过状态寄存器判断错误类型。
    • 第2步:尝试软复位 - 操作IIC外设的SWRST位,尝试软件复位IIC控制器。
    • 第3步:硬件恢复(最后手段) - 如果软复位无效,则切换到GPIO模式,模拟时钟序列“撬开”总线。

四、 详细的错误恢复步骤与代码实现

  1. 错误检测
    • 在IIC中断服务程序(ISR)或状态查询中,检测上述错误标志位(BERR, AL, AE等)。
  2. 初步处理与软件复位
    • 清除错误标志。

    • 关闭IIC外设(I2CEN=0)。

    • 置位软件复位位(IIC_CTLR1中的SWRST位)。

    • 延时片刻后,清除SWRST位,重新配置并使能IIC外设(I2CEN=1)。

    • 代码示例

      void  I2C_Isr(void)
      {uint8_t det;char dat;if ( I2C_ReadIntFlag(I2C1,I2C_INT_FLAG_BERR) == SET){//清除错误标志。I2C_ClearIntFlag(I2C1,I2C_INT_FLAG_BERR);//关闭IIC外设(I2CEN=0)I2C_Disable(I2C1);//置位软件复位位(IIC_CTLR1中的SWRST位)I2C_EnableSoftwareReset(I2C1);Delay(5);//清除SWRST位I2C_DisableSoftwareReset(I2C1);//重新配置并使能IIC外设(I2CEN=1)I2C_Enable(I2C1);}if ( I2C_ReadIntFlag(I2C1,I2C_INT_FLAG_AE) == SET){//清除错误标志。I2C_ClearIntFlag(I2C1,I2C_INT_FLAG_AE);//关闭IIC外设(I2CEN=0)I2C_Disable(I2C1);//置位软件复位位(IIC_CTLR1中的SWRST位)I2C_EnableSoftwareReset(I2C1);Delay(5);//清除SWRST位I2C_DisableSoftwareReset(I2C1);//重新配置并使能IIC外设(I2CEN=1)I2C_Enable(I2C1);}if ( I2C_ReadIntFlag(I2C1,I2C_INT_FLAG_AL) == SET){//清除错误标志。I2C_ClearIntFlag(I2C1,I2C_INT_FLAG_AL);//关闭IIC外设(I2CEN=0)I2C_Disable(I2C1);//置位软件复位位(IIC_CTLR1中的SWRST位)I2C_EnableSoftwareReset(I2C1);Delay(5);//清除SWRST位I2C_DisableSoftwareReset(I2C1);//重新配置并使能IIC外设(I2CEN=1)I2C_Enable(I2C1);}
      }
  3. 终极硬件恢复(GPIO模拟时钟)
    • 前提:如果软复位后总线BUSY标志仍无法清除。

    • 步骤

      • a. 将IIC的SCL和SDA引脚配置为开漏输出模式的GPIO。
      • b. 确保初始状态:SCL输出高,SDA输出高(释放)。
      • c. 如果SDA被拉低(总线仍锁死),则开始模拟时钟:
        • 将SCL拉低,延时。
        • 将SCL释放(拉高),延时。
        • 重复以上过程若干次(如9-16次),同时监测SDA是否变为高电平。
      • d. 一旦SDA变高,立即发送一个“停止条件”(先拉低SDA->拉低SCL->释放SCL->释放SDA)。
      • e. 将GPIO重新映射回IIC外设。
      • f. 重新初始化IIC外设。
    • 代码示例

      void IIC_Recovery() {GPIO_Config_T gpioConfigStruct = {0};// 1. 配置SCL为开漏输出gpioConfigStruct.pin = GPIO_PIN_6;gpioConfigStruct.mode = GPIO_MODE_AF_OD;GPIO_Config(GPIOB, &gpioConfigStruct);// 2. 发生9个时钟脉冲for(int i=0; i<9; i++) {GPIO_SetBit(GPIOB, GPIO_PIN_6);Delay(5);GPIO_ResetBit(GPIOB, GPIO_PIN_6);Delay(5);}// 3. 发送停止条件GPIO_SetBit(GPIOB, GPIO_PIN_6);Delay(5);GPIO_SetBit(GPIOB, GPIO_PIN_7);// 4. 重新初始化I2CI2C_Init();
      } 

五、 预防优于治疗:IIC通信的稳定性设计建议

  1. 硬件设计
    • 确保上拉电阻阻值合适(通常4.7kΩ)。
    • 布线时注意远离干扰源,必要时添加屏蔽,走线距离不应该过长。
    • 在SCL和SDA线上添加适当的RC滤波或ESD保护器件。
  2. 软件设计
    • 添加超时机制:在任何等待标志位(如EV5, EV6)的地方加入超时判断,避免无限等待。

      uint8_t I2C_Write(char * pBuffer)
      {uint16_t I2CTimeout = I2CT_LONG_TIMEOUT;while(I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY)){I2C_Init();if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(4);}I2C_DisableInterrupt(I2C1, I2C_INT_EVT);/* Send START condition */I2C_EnableGenerateStart(I2C1);I2CTimeout = I2CT_FLAG_TIMEOUT;/* EV5 */while(!I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT)){if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(5);}/* Send address for write */I2C_Tx7BitAddress(I2C1, 0xB0, I2C_DIRECTION_TX);I2CTimeout = I2CT_FLAG_TIMEOUT;/* EV6 */while(!I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(6);}/* While there is data to be written */while(*pBuffer != '\0'){/* Send the current byte */I2C_TxData(I2C1, *pBuffer);/* Point to the next byte to be written */pBuffer++;I2CTimeout = I2CT_LONG_TIMEOUT;/* EV8 */while (!I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)){if((I2CTimeout--) == 0){return I2C_TIMEOUT_UserCallback(8);}}}return 1;
      }
      
    • 错误重试机制:在发生非致命错误(如AF)时,进行有限次数的重试。

    • 定期监控:在多主系统中,定期检查总线状态。

六、 总结

硬件IIC高效但配置复杂,软件模拟灵活却消耗CPU资源。同时使用介绍硬件IIC错误的常见类型、核心恢复原理(模拟时钟)和分层恢复策略(软复位->硬件恢复)。因此建议必须添加总线锁死保护机制。同时如果处理数据量大,建议使用DMA处理。


文章转载自:

http://qNwwlg5L.mwkwg.cn
http://ttFpXRk9.mwkwg.cn
http://AJk0gZQf.mwkwg.cn
http://3cZmGqiZ.mwkwg.cn
http://Sc0tfJmU.mwkwg.cn
http://fDFWcKCU.mwkwg.cn
http://OsnKG3ot.mwkwg.cn
http://bE7Pz9CI.mwkwg.cn
http://Y0iUBLRm.mwkwg.cn
http://zMR207GO.mwkwg.cn
http://reICNB8Q.mwkwg.cn
http://ETfumezb.mwkwg.cn
http://kipgXYly.mwkwg.cn
http://XzfczBUM.mwkwg.cn
http://ew259kgq.mwkwg.cn
http://imIlLXOj.mwkwg.cn
http://L8ATuzCx.mwkwg.cn
http://WMVuTO5G.mwkwg.cn
http://QsZbTAVt.mwkwg.cn
http://qfU3Uqd7.mwkwg.cn
http://Ot2wUVBV.mwkwg.cn
http://QM0Nfrqj.mwkwg.cn
http://QxH3NQKV.mwkwg.cn
http://aTK6q18h.mwkwg.cn
http://CHrIbkO9.mwkwg.cn
http://a495uoWZ.mwkwg.cn
http://2GpXx2C0.mwkwg.cn
http://NybBmLLY.mwkwg.cn
http://G1oiSr5i.mwkwg.cn
http://rur40WPr.mwkwg.cn
http://www.dtcms.com/a/374048.html

相关文章:

  • n8n入门
  • 静态住宅IP的特点
  • 数智之光燃盛景 共同富裕创丰饶
  • colmap+pycolmap带cuda编译
  • Nano-Bananary 搭建 使用 nano banana
  • 前端性能监控与优化:从 Lighthouse 到 APM
  • 浅聊一下微服务的网关模块
  • 硬件开发2-ARM基本概要
  • C++11第二弹(右值引用与移动语义)
  • 数电实验二连线
  • MQTT+WebSocket工业协议实战:高并发SCADA系统通信架构设计
  • Claude-Flow AI协同开发:基础入门之 AI编排
  • Android面试指南(七)
  • 西嘎嘎学习 - C++修饰符类型 - Day 5
  • 明远智睿RK3568核心板:199元解锁多行业智能新可能
  • LeetCode算法日记 - Day 36: 基本计算器II、字符串解码
  • linux系统address already in use问题解决
  • ArcGIS学习-17 实战-密度分析
  • 08 修改自己的Centos的软件源
  • 柯美bizhub 206复印机报 警告 维修召唤(M2) 维修召唤如何解决 如何维修
  • Vue3 页面切换白屏问题解决方案
  • [硬件电路-168]:Multisim - Multisim提供的用于学习参考电路有哪些?存放位置?
  • 使用kettle批量调用大模型
  • 【系统分析师】第1章-基础知识:绪论(核心总结)
  • docker-容器
  • ARM架构详解:从内核到异常处理
  • Redis缓存击穿、雪崩、穿透
  • Go正则表达式实战指南
  • 保持元素可见但不可访问的方法: `inert`
  • ClaudeCode稳定备用方案:API接入详解