STM32的IIC问题一直存在,在网上也被很多人吐槽,然而FAE告诉我,硬件IIC的问题在F1,F3,F4系列单片机存在,而在L0上已经解决了,然而这几天调试加密芯片和显示芯片,都是IIC芯片,却再一次证明,L0系列的IIC一样存在问题,

FAE告诉我是我的配置问题,故写这篇文章,如果是我配置问题,希望得到高人指点,再次感激不尽。

配置代码:

void MX_I2C1_Init(void)
{ hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x00707CBB;
hi2c1.Init.OwnAddress1 = ;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = ;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
} /**Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
} /**Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, ) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
} }
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
unsigned char i; GPIO_InitTypeDef GPIO_InitStruct;
if(i2cHandle->Instance==I2C1)
{
__HAL_RCC_I2C1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE(); /*I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = I2C_SCL_Pin|I2C_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
} void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{ if(i2cHandle->Instance==I2C1)
{
__HAL_RCC_I2C1_CLK_DISABLE();
/*I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
HAL_GPIO_DeInit(GPIOB, I2C_SCL_Pin|I2C_SDA_Pin);
}
}

现象:程序调用HAL_I2C_Master_Transmit(),如果代码中有其它中断,就很容易传输失败:

status = HAL_I2C_Master_Transmit(&hi2c1, SLAVE_IIC_ADDR, i2c_data, 2, 2)
error_status = HAL_I2C_GetState(&hi2c1);
printf("err1:%02x -- err2:%02x\r\n",status,error_status);

查看到的是status基本就是HAL_BUSY,error_status基本就是HAL_I2C_STATE_BUSY_TX,用逻辑分析仪查看I2C,即使重新调用HAL_I2C_Master_Transmit(),也没看到有波形出来,用万用表量出来SDA是高电平,SCL是低电平。

在网上搜索STM32硬件I2C锁死,能搜到几篇有参考性的文章,其中下面这篇参考性意义很大,在此非常感谢:

http://blog.csdn.net/dldw8816/article/details/51579781

由于芯片不一样,所以方法也不一样,但思路是一样的,我贴上我的解决方法:

查看datasheet上寄存器的描述,清零PE,就可以清除I2C的所有错误状态。

void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
unsigned char i; GPIO_InitTypeDef GPIO_InitStruct;
if(i2cHandle->Instance==I2C1)
{
__HAL_RCC_I2C1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitStruct.Pin = I2C_SCL_Pin|I2C_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(I2C_SCL_GPIO_Port, &GPIO_InitStruct); HAL_GPIO_WritePin(I2C_SCL_GPIO_Port, I2C_SCL_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(I2C_SDA_GPIO_Port, I2C_SDA_Pin, GPIO_PIN_SET); /*force to release I2C bus*/ __HAL_I2C_DISABLE(i2cHandle);
for(i=0;i<100;i++); /*delay awhile*/
__HAL_I2C_ENABLE(i2cHandle); /*I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = I2C_SCL_Pin|I2C_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
}
void I2C_Reset(void)
{
HAL_I2C_MspDeInit(&hi2c1);
HAL_I2C_MspInit(&hi2c1);
}

如果单单这么做,然后在I2C传输返回值不是HAL_OK的时候调用I2C_Reset,也不能解决问题,仍然返回HAL_BUSY,于是查看发送源码,发现STM32的库函数里面软件实现了一个状态机,需要将这个状态机恢复到初始状态,代码如下:

        do{
status = HAL_I2C_Master_Transmit(&hi2c1, SLAVE_IIC_ADDR, i2c_data, , );
if(status != HAL_OK)
{
I2C_Reset();
#if 1
error_status = HAL_I2C_GetState(&hi2c1);
printf("err1:%02x -- err2:%02x\r\n",status,error_status);
#endif
__HAL_I2C_CLEAR_FLAG(&hi2c1, I2C_FLAG_STOPF); /* Clear STOP Flag */
I2C_RESET_CR2(&hi2c1); /* Clear Configuration Register 2 */
hi2c1.State = HAL_I2C_STATE_READY;
hi2c1.Mode = HAL_I2C_MODE_NONE;
__HAL_UNLOCK(&hi2c1); /* Process Unlocked */
} }while(status != HAL_OK);

这样测下来I2C发生错误之后,就可以重新初始化总线了,测试了一上午,查看串口打印出来的log,能看到printf("err1:%02x -- err2:%02x\r\n",status,error_status);这条消息,但我的代码可以修复I2C。

下面两篇文章,一篇是ST官方的解决方案,一篇是网上没有署名的大神写的文档,再次非常感谢!

STM32-I2C-接口进入-Busy-状态不能退出.pdf

解决STM32-I2C接口死锁在BUSY状态的问题.pdf

浅谈STM32L071硬件I2C挂死的更多相关文章

  1. 浅谈 STM32 硬件I2C的使用 (中断方式 无DMA 无最高优先级)(转)

    引子 STM32的硬件I2C很多人都对它望而却步.因为很多电工都说,STM32 硬件 I2C有BUG.不稳定.死机等等……最后都使用GPIO模拟I2C. 的确,模拟I2C好用.但是在我看来在一个72M ...

  2. I2C 挂死,SDA一直为低问题分析【转】

    转自:https://blog.csdn.net/winitz/article/details/72460775 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csd ...

  3. 浅谈static其一之不死变量

    在学习汇编的过程中,小有所悟,遂把自己所思所想记下,以便日后查阅. 首先说说我对这个关键字的理解.static字面上就是静止的.静态的.不变的之类的意思,所以在被它修饰之后,应该也会带有这样的一些特点 ...

  4. 五分钟DBA:浅谈伪分布式数据库架构

    [IT168 技术]12月25日消息,2010互联网行业技术研讨峰会今日在上海华东理工大学召开.本次峰会以“互联网行业应用最佳实践”为主题,定位于互联网架构设计.应用开发.应用运维管理,同时,峰会邀请 ...

  5. 浅谈Nginx负载均衡和F5的区别

    前言 笔者最近在负责某集团网站时,同时用到了Nginx与F5,如图所示,负载均衡器F5作为处理外界请求的第一道"墙",将请求分发到web服务器后,web服务器上的Nginx再进行处 ...

  6. 浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树

    http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的 ...

  7. Linux的文本处理工具浅谈-awk sed grep

    Linux的文本处理工具浅谈 awk   老大 [功能说明] 用于文本处理的语言(取行,过滤),支持正则 NR代表行数,$n取某一列,$NF最后一列 NR==20,NR==30 从20行到30行 FS ...

  8. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理

    [微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...

  9. 浅谈 DDoS 攻击与防御

    浅谈 DDoS 攻击与防御 原创: iMike 运维之美  什么是 DDoS DDoS 是英文 Distributed Denial of Service 的缩写,中文译作分布式拒绝服务.那什么又是拒 ...

随机推荐

  1. 线性回归决定系数之Why SST=SSE+SSR

    线性最小二乘法的原则是使得误差的平方和最小,即 为了使S最小,令其对参数的偏导数为零: 即 即 根据方程1和方程2,得 又∵ ∴ 参考链接:https://math.stackexchange.com ...

  2. shell 多重条件判断

    多重条件判断 '判断1 -a 判断2' 逻辑与,判断1和判断2都成立,最终的结果才为真 '判断1 -o 判断2' 逻辑或,判断1和判断2有一个成立,最终的结果就为真 '!判断' 逻辑非,使原始的判断式 ...

  3. 跨域 jsonp 和 CORS 资料

    http://mp.weixin.qq.com/s/iAShnqvsOyV-Xd0Ft7Nl2Q HTML5安全:CORS(跨域资源共享)简介...ie67不要想了... http://www.cnb ...

  4. leetCode 典型回溯例子

    39题,翻译题目:给定一组候选集和一个目标值,在c的所有组合中,找出所有总和等于T的组合. 候选数组c中同一个数可以被选择多次(不限次数) 分析: 典型的回溯法应用 对数组里面的每个数,用递归的方式相 ...

  5. Python Django 之 直接执行自定义SQL语句(一)

    一.执行自定义SQL方法 1.Executing custom SQL directly      直接执行自定义SQL,这种方式可以完全避免数据模型,而是直接执行原始的SQL语句. 2.Manage ...

  6. SpringMVC @RequestParam和@RequestBody的区别

    问题:@Requestbody 用的时候遇到400和415错误,因为请求格式不对. @RequestBody @RequestBody能把简单json结构参数转换成实体类,如下代码: @Request ...

  7. DevExpress WPF v18.2新版亮点(七)

    行业领先的.NET界面控件2018年第二次重大更新——DevExpress v18.2日前正式发布,本站将以连载的形式为大家介绍新版本新功能.本文将介绍了DevExpress WPF v18.2的新功 ...

  8. 安装Android开发工具

    这两天开始学Android,首先要要解决的是安装编译器的问题,经过我这两天的探究,我把收获总结一下 最简单的编译器是ADT-bundle,它是一个集成的工具,里面有eclipse,也不需要下载SDK, ...

  9. codeforce949A(顺带vector详细使用介绍)

    A. Zebras time limit per test1 second memory limit per test512 megabytes inputstandard input outputs ...

  10. <Spark><Advanced Programming>

    Introduction 介绍两种共享变量的方式: accumulators:聚集信息 broadcast variables:高效地分布large values 介绍对高setup costs任务的 ...