STM32 I2C总线锁死原因及解决方法

本文介绍STM32 I2C总线锁死原因及解决方法。

在使用STM32 I2C总线操作外设时,有时会遇到I2C总线锁死(I2C总线为Busy状态)的问题,即便复位MCU也无法解决,本文介绍其锁死的原因和解决方法,并给出相应的参考代码。

1.故障现象

在I2C总线锁死时,使用示波器测量发现,SCL为高电平,SDA为低电平。

1)MCU操作I2C总线(读/写)时复位MCU(通过复位按键操作)比较容易再现。

2)MCU操作I2C总线(读/写)时,强制将SDA拉低(用金属摄子夹到地,并持续一段时间)会再现。

3)设想,MCU操作I2C总线过程中,SDA受外界干扰(毛刺)被拉低,也可能导致I2C总线锁死。

2.原因

1)I2C总线被设计成多主机可共享总线,这会导致总线竞争,主设备判断当前总线被占用是根据SDA线为低来判断的。当主设备检测到总线被占用,则指示总线忙,并无法操作总线。

2)主设备操作从设备(读/写)时,复位主设备,如果恰好从设备处于ACK状态(SDA拉低)或回复主设备数据位0,那么在复位完成,主设备重新接管总线时,会错误的认为总线忙,因为此时从设备并未复位,SDA仍然被拉低。从设备等待主设备拉低SCL取走ACK或者数据位0,而主设备等待从设备释放SDA。主设备和从设备互相等待,进入死锁状态。值的注意的时,对于故障现象2),STM32 I2C内部似乎有超时机制,如果SDA被拉低持续一段时间,则无法恢复。

3.解决方法

1)硬件复位

直接硬件复位外部从设备,比如通过MOS管软开关从设备电源,或通过外部设备硬件复位脚(从设备有才行)复位。

2)软件复位

情况1:

出现I2C总线锁死时正好外设回复数据位0,则需经历小于9个SCL时钟,从设备会释放SDA。

情况2:

出现I2C总线锁死时正好外设ACK,则经历9个SCL时钟,从设备会释放SDA。

综合情况1,2可知,通过软件复位解决时,当检测到总线锁死(BUSY状态),可以生成9个SCL时钟,并不断检测SDA引脚电平状态,若SDA被释放(为高)则退出,主机重新初始化I2C总线。Software Rest如下图。

3)某些I2C缓冲器提供I2C总线错误恢复功能。

4.参考代码

参考代码如下(这里以STM32F4xx平台为例,其它平台类似):

DrvI2C1.h:

#ifndef __DRV_I2C1_H
#define __DRV_I2C1_H#ifdef __cplusplusextern "C" {
#endif #include "datatype.h"
#include "stm32f4xx_hal.h"#define I2C1_SCL_GPIO_PORT     (GPIOB)
#define I2C1_SCL_PIN           (GPIO_PIN_6)#define I2C1_SDA_GPIO_PORT     (GPIOB)
#define I2C1_SDA_PIN           (GPIO_PIN_7)extern I2C_HandleTypeDef hi2c1;extern int32_t I2C1_Init(void);#ifdef __cplusplus
}
#endif#endif

DrvI2C1.c:

#include "DrvI2C1.h"I2C_HandleTypeDef hi2c1;static void I2C1_MspInit(I2C_HandleTypeDef* i2cHandle);
static void I2C1_MspDeInit(I2C_HandleTypeDef* i2cHandle);
static BOOL I2C1_Unlock(void);
static void I2C1_SetPortODOutput(void);int32_t I2C1_Init(void)
{if (!I2C1_Unlock()){DbgPrint("I2C1 unlock failed!\r\n");}if (HAL_I2C_RegisterCallback(&hi2c1, HAL_I2C_MSPINIT_CB_ID, I2C1_MspInit) != HAL_OK){Error_Handler();}hi2c1.Instance = I2C1;hi2c1.Init.ClockSpeed = 200000;hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;hi2c1.Init.OwnAddress1 = 0;hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;hi2c1.Init.OwnAddress2 = 0;hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;if (HAL_I2C_Init(&hi2c1) != HAL_OK){Error_Handler();}if (HAL_I2C_RegisterCallback(&hi2c1, HAL_I2C_MSPDEINIT_CB_ID, I2C1_MspDeInit) != HAL_OK){Error_Handler();}return 0;
}static void I2C1_MspInit(I2C_HandleTypeDef* i2cHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOB_CLK_ENABLE();/**I2C1 GPIO ConfigurationPB6     ------> I2C1_SCLPB7     ------> I2C1_SDA*/GPIO_InitStruct.Pin = I2C1_SCL_PIN;GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;HAL_GPIO_Init(I2C1_SCL_GPIO_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin = I2C1_SDA_PIN;GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;HAL_GPIO_Init(I2C1_SDA_GPIO_PORT, &GPIO_InitStruct);/* I2C1 clock enable */__HAL_RCC_I2C1_CLK_ENABLE();
}static void I2C1_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{/* Peripheral clock disable */__HAL_RCC_I2C1_CLK_DISABLE();/**I2C1 GPIO ConfigurationPB6     ------> I2C1_SCLPB7     ------> I2C1_SDA*/HAL_GPIO_DeInit(I2C1_SCL_GPIO_PORT, I2C1_SCL_PIN);HAL_GPIO_DeInit(I2C1_SDA_GPIO_PORT, I2C1_SDA_PIN);
}static BOOL I2C1_Unlock(void)
{uint8_t i = 0;I2C1_SetPortODOutput();HAL_GPIO_WritePin(I2C1_SCL_GPIO_PORT, I2C1_SCL_PIN, GPIO_PIN_SET);  //Release busHAL_GPIO_WritePin(I2C1_SDA_GPIO_PORT, I2C1_SDA_PIN, GPIO_PIN_SET);if (HAL_GPIO_ReadPin(I2C1_SDA_GPIO_PORT, I2C1_SDA_PIN) == GPIO_PIN_RESET){for (i = 0; i < 9; i++){HAL_GPIO_WritePin(I2C1_SCL_GPIO_PORT, I2C1_SCL_PIN, GPIO_PIN_RESET);DelayUS(5);  //HAL_GPIO_WritePin(I2C1_SCL_GPIO_PORT, I2C1_SCL_PIN, GPIO_PIN_SET);DelayUS(5);  //if (HAL_GPIO_ReadPin(I2C1_SDA_GPIO_PORT, I2C1_SDA_PIN) == GPIO_PIN_SET){break;}}if (i >= 9){return FALSE;}}return TRUE;
}static void I2C1_SetPortODOutput(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOB_CLK_ENABLE();GPIO_InitStruct.Pin = I2C1_SCL_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;HAL_GPIO_Init(I2C1_SCL_GPIO_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin = I2C1_SDA_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;HAL_GPIO_Init(I2C1_SDA_GPIO_PORT, &GPIO_InitStruct);
}

注意:

1)上电即对I2C总线作检测,并执行解锁操作,见初始化的开头部分。

2)“HAL_I2C_Init()”函数内部包含对I2C总线的复位操作,因此,“I2C1_Unlock()”函数里未对I2C总线作复位操作。若HAL库里未对I2C总线作复位操作,则需添加如下代码:

static void I2C1_Reset(void)
{/*Reset I2C*/I2C1->CR1 |= I2C_CR1_SWRST;I2C1->CR1 &= ~I2C_CR1_SWRST;
}

3)在操作I2C外设出错时,若需要添加解锁操作,可按如下进行:

if (HAL_I2C_Master_Transmit(&hi2c1, SlaveAddr, &Value, 1, 1000) != HAL_OK)
{HAL_I2C_DeInit(&hi2c1);I2C1_Init();
}

先取消初始化I2C,再对I2C进行初始化(包含解锁操作)。

总结,本文介绍了STM32 I2C总线锁死原因及解决方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/31326.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pdf转图片转换器,pdf转图片的工具

在日常的工作和学习中&#xff0c;我们经常会遇到需要将PDF文件转换为图片格式的情况。那么&#xff0c;如何才能将PDF格式转换为图片格式呢&#xff1f;今天&#xff0c;我将为大家介绍几种简单易用的方法&#xff0c;帮助大家轻松实现PDF转图片。 打开“轻云pdf处理官网网站”…

deepin 加入甲辰计划,共建 RISC-V 繁荣生态

内容来源&#xff1a;deepin&#xff08;深度&#xff09;社区 今日&#xff0c;deepin(深度)社区宣布正式加入甲辰计划&#xff0c;致力于在下一个丙辰年&#xff08;2036龙年&#xff09;之前&#xff0c;基于RISC-V实现从数据中心到桌面办公、从移动穿戴到智能物联网全信息产…

【廉颇老矣,尚能饭否】传统的数据仓库是否还能发挥作用?

引言&#xff1a;随着数字化转型的深入和大数据技术的发展&#xff0c;大数据平台、数据中台和和数据湖技术不断涌现&#xff0c;给人感觉传统的数据仓库技术已经过时&#xff0c;廉颇老矣&#xff0c;不能应对新的挑战&#xff0c;在数字化转型中&#xff0c;不能发挥重要作用…

网络与协议安全复习 - 电子邮件安全

文章目录 PGP(Pretty Good Privacy)功能 S/MIME(Secure/Multipurpose Internet Mail Extensions)DKIM(Domain Keys Identified Mail) PGP(Pretty Good Privacy) 使用符号&#xff1a; Ks&#xff1a;会话密钥、KRa&#xff1a;A 的私钥、KUa&#xff1a;A 的公钥、EP&#xff…

JAVAWeb---- 数据库的简单了解

目录 1.什么是数据库 2.什么是数据库管理系统 3.什么是SQL 4.什么是关系型数据库 1.什么是数据库 用来存储和管理数据的“仓库”&#xff0c;简称DB(Database)&#xff1b; 2.什么是数据库管理系统 对数据库的一切操作都是在数据库管理系统进行的&#xff0c;比如MySQL&a…

软件测试之解构单元测试

软件单元测试是对软件中的最小可测试单元进行检查和验证的过程。这些单元可以是函数、方法、类实例&#xff0c;或者是任何具有明确功能、规格定义和接口定义的程序代码模块。单元测试是软件开发过程中的最低级别的测试活动&#xff0c;它确保软件的独立单元在与程序的其他部分…

eclipse中没有SERVER的解决办法(超详细)

将 Tomcat 和 Eclipse 相关联时&#xff0c;Eclipse有的版本发现 发现eclipse->【Window】->【Preferences】里没有【server】从而配置不了Runtime Environment。所以需要通过eclipse进行安装。 通过我个人的经验下面给出解决办法&#xff1a; 一、获取 Eclipse版本 点击…

Kafka中的时间轮算法

1. Kafka与时间轮&#xff1a; Kafka的定时器底层使用时间轮算法。Kafka时间轮是层次时间轮&#xff0c;并且支持时间轮复用。 优点&#xff1a; 高效的插入操作&#xff1a; 时间轮底层数据结构&#xff08;桶&#xff09;&#xff0c;使用双向链表的设计使得插入操作的时间…

若电路板上的二极管损坏后怎么确定型号呢?

若电路板上的二极管损坏后&#xff0c;还可以看清原来管子的型号&#xff0c;换用一个同型号的二极管即可。若看不清型号或管子未标注型号&#xff0c;一般可以根据该二极管在电路中的作用来代换。电路板上的二极管坏了&#xff0c;如何确定它的型号&#xff1f;。 一般来说看…

气象数据NC、grb2解析成矢量json、CMIS、MICPS及图片应用到webgis

一、基础概念 气象数据通常以多种格式存储和交换&#xff0c;以适应不同的应用需求和处理工具。以下是一些常见的气象数据格式及其转换方法的概述&#xff1a; 常见气象数据格式 1. NetCDF&#xff08;Network Common Data Form&#xff09;&#xff1a;一种自描述、自包含的…

如何在MATLAB中创建各种常用的图形

本文将介绍如何在MATLAB中创建各种常用的图形。将涵盖以下内容&#xff1a; 基本的二维图形 折线图&#xff08;Line Plot&#xff09;散点图&#xff08;Scatter Plot&#xff09;条形图&#xff08;Bar Plot&#xff09;面积图&#xff08;Area Plot&#xff09; 三维图形 三…

WACV2024论文3D相关速览48篇

WACV2024 3D相关论文阅读 Paper1 Self-Supervised Edge Detection Reconstruction for Topology-Informed 3D Axon Segmentation and Centerline Detection 摘要小结: 许多基于机器学习的轴突追踪方法依赖于带有分割标签的图像数据集。这需要领域专家的手动标注&#xff0c;既…

R语言——绘图与数据可视化

1、练习将25个点的符号绘制出来&#xff0c;然后用rainbow()返回25个颜色&#xff0c;后5个符号形状的背景颜色用蓝色填充&#xff0c;图的标题为"符号图"&#xff0c;x轴标题为符号索引&#xff0c;y轴标题为符号形状。 2、根据员工的销售业绩画饼状图&#xff0c;添…

[保姆级教程]在uniapp中使用vant框架

文章目录 导文安装 Vant在uniapp项目中的pages.json中配置easycom&#xff0c;实现组件的自动按需引入&#xff1a;在页面中使用Vant Weapp组件&#xff0c;例如使用按钮组件&#xff08;Button&#xff09;&#xff1a;其他安装报错官网地址 导文 在 uni-app 中使用 Vant 框架…

关于OS中逻辑地址与物理地址转换

首先将逻辑地址134D从十六进制转为2进制 0001 0011 0100 1101 1&#xff09;1K的时候对应2的10次方 页面大小占10位 从后往前数 0001 00 || 11 0100 1101 前面的转为十进制为4 对应页号4内容1A转为2进制01 1010将这个替换原来的前六位数字 即0110 1011 0100 1101 再转换为…

智慧工厂监控可视化解决方案(160页WORD)

方案介绍&#xff1a; 本智慧工厂监控可视化解决方案通过集成先进的物联网和大数据技术&#xff0c;为制造业企业提供了全面的数字化转型支持。通过实时监控、数据分析、可视化展示等功能&#xff0c;帮助企业提升生产效率、降低运营成本、优化产品质量和能源利用率&#xff0…

C# 语言在AGI 赛道上能做什么

自从2022年11月OpenAI正式对外发布ChatGPT依赖&#xff0c;AGI 这条赛道上就挤满了重量级的选手&#xff0c;各大头部公司纷纷下场布局。原本就在机器学习、深度学习领域占据No.1的Python语言更是继续稳固了自己AI一哥的位置。凭借着Microsoft 和 OpenAI 长期以来一直是紧密相连…

【CT】LeetCode手撕—300. 最长递增子序列

目录 题目1- 思路2- 实现⭐300. 最长递增子序列——题解思路 3- ACM 实现 题目 原题连接&#xff1a;300. 最长递增子序列 1- 思路 模式识别&#xff1a;最长递增子序列——> 利用动规五部曲 解决 ——> 借助 i 和 j 指针&#xff0c;其中 j < i 动规五部曲 1.定义…

【功能详解】银河麒麟操作系统“安全启动”是如何发挥作用的?

2023年12月&#xff0c;财政部、工信部发布了7项信息类产品《政府采购需求标准》&#xff0c;为包括操作系统在内多项产品的政府集中采购提供政策支撑。其中&#xff0c;安全、可信作为国产操作系统的基本要求备受关注。 安全体系的构建离不开操作系统本身的硬实力&#xff0c…

LabVIEW项目管理中如何平衡成本、时间和质量

在LabVIEW项目管理中&#xff0c;平衡成本、时间和质量是实现项目成功的关键。通过制定详细的项目计划、合理分配资源、严格控制进度、进行质量保证和灵活应对变化&#xff0c;项目管理者可以有效地协调这三者的关系&#xff0c;确保项目按时、按质、按预算完成。 1. 制定详细…