历史上的今天
返回首页

历史上的今天

今天是:2025年04月08日(星期二)

正在发生

2019年04月08日 | STM32之I2C_FLAG_BUSY置位解决办法

2019-04-08 来源:eefocus

stm32f429-disco上的触摸屏IC是STMPE811,使用I2C通信,该ic的使用还不算难,里面包括8通道12bit AD,8个GPIO口,加128set FIFO以及几个寄存器。


问题是出在STM32 的I2C IP核上,网上大家也吐槽了不少,最主要的就是各种当机,当当当当,哈哈。


我第一次出现当机的地方是在


if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)

    {

      return HAL_BUSY;

    }


返回的BUSY值是一直置H的,这就奇怪了,用的是官方的STM32CubeMX生成的初始化代码,刚初始完就BUSY,太坑了吧。


查看datasheet,有两点可以参考



这渣渣IP核的BUSY位是判断sda,scl两线的stop位,没检测到就置H;而不是判断I2C的状态及超时,置位BUSY,坑!


解决的办法是有的:



可以通过CR1位的rst位,手动将其清零。


网上不少童鞋也是通过该位清BUSY


hi2c->Instance->CR1 |= 0x8000;

hi2c->Instance->CR1 &= ~0x8000;


要注意的是,此复位操作要放置于,所有I2C寄存器配置之前!!!以上是方法一


方法二:


查看了例程,例程的I2C是这样初始化的


I2Cx_MspInit(&I2cHandle);

HAL_I2C_Init(&I2cHandle);


其中

static void I2Cx_MspInit(I2C_HandleTypeDef *hi2c)

{

  GPIO_InitTypeDef  GPIO_InitStruct;  

 

  if (hi2c->Instance == DISCOVERY_I2Cx)

  {

    /* Configure the GPIOs ---------------------------------------------------*/ 

    /* Enable GPIO clock */

    DISCOVERY_I2Cx_SDA_GPIO_CLK_ENABLE();

    DISCOVERY_I2Cx_SCL_GPIO_CLK_ENABLE();

      

    /* Configure I2C Tx as alternate function  */

    GPIO_InitStruct.Pin       = DISCOVERY_I2Cx_SCL_PIN;

    GPIO_InitStruct.Mode      = GPIO_MODE_AF_OD;

    GPIO_InitStruct.Pull      = GPIO_NOPULL;

    GPIO_InitStruct.Speed     = GPIO_SPEED_FAST;

    GPIO_InitStruct.Alternate = DISCOVERY_I2Cx_SCL_SDA_AF;

    HAL_GPIO_Init(DISCOVERY_I2Cx_SCL_GPIO_PORT, &GPIO_InitStruct);

      

    /* Configure I2C Rx as alternate function  */

    GPIO_InitStruct.Pin = DISCOVERY_I2Cx_SDA_PIN;

    HAL_GPIO_Init(DISCOVERY_I2Cx_SDA_GPIO_PORT, &GPIO_InitStruct);

    

    

    /* Configure the Discovery I2Cx peripheral -------------------------------*/ 

    /* Enable I2C3 clock */

    DISCOVERY_I2Cx_CLOCK_ENABLE();

    

    /* Force the I2C Periheral Clock Reset */  

    DISCOVERY_I2Cx_FORCE_RESET();//########## look here #############

      

    /* Release the I2C Periheral Clock Reset */  

    DISCOVERY_I2Cx_RELEASE_RESET(); //########## look here #############

   }

}

STM自己也受不鸟这I2C,手动复位了,那么解决办法就变得很明显了,在我们自己的i2c初始化函数中加入:

void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)

{

    GPIO_InitTypeDef GPIO_InitStruct;

    if(hi2c->Instance==I2C3)

    {

        __I2C3_CLK_ENABLE();

        

        /**I2C3 GPIO Configuration    

        PC9     ------> I2C3_SDA

        PA8     ------> I2C3_SCL 

        */

        GPIO_InitStruct.Pin = GPIO_PIN_9;

        GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

        GPIO_InitStruct.Pull = GPIO_NOPULL;

        GPIO_InitStruct.Speed = GPIO_SPEED_FAST;

        GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;

        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

        

        GPIO_InitStruct.Pin = GPIO_PIN_8;

        GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

        GPIO_InitStruct.Pull = GPIO_NOPULL;

        GPIO_InitStruct.Speed = GPIO_SPEED_FAST;

        GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;

        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        

        __I2C3_FORCE_RESET();//######## look here #########

        __I2C3_RELEASE_RESET();//######## look here #########

        

        

        HAL_NVIC_SetPriority(I2C3_EV_IRQn, 13, 0);

        HAL_NVIC_EnableIRQ(I2C3_EV_IRQn);

        HAL_NVIC_SetPriority(I2C3_ER_IRQn, 13, 0);

        HAL_NVIC_EnableIRQ(I2C3_ER_IRQn);

    }

}

说实话,i2c3_force_reset()是STM32的RCC(时钟与复位)模块的功能函数,并不是I2C模块的函数,即不是操作I2C的CR1位,而是通过总复位模块对I2C来了一次复位操作




总结一下i2c的初始化方式:


1.配置GPIO口 HAL_I2C_MspInit();


2.复位一下(CR1位复位)或(RCC对i2c模块复位)


3.配置i2c寄存器 MX_I2C3_Init();






至此,初始化后的I2C就不会将BUSY位置位了。

后期,假如I2C通信出错,该IP核有可能也会将BUSY置位,且不自动复位,此步骤也可作为除错的参考。


推荐阅读

史海拾趣

Dynastream公司的发展小趣事

Dynastream公司成立于1998年,当时正值科技飞速发展的年代。创始人凭借其敏锐的市场洞察力和对技术的深厚理解,决定专注于个人监视传感器和运动分析领域的研究与开发。在创业初期,公司面临资金短缺、人才匮乏等种种困难,但团队凭借着对技术的热情和不懈的努力,成功研发出了第一代产品,并在市场上引起了广泛关注。

Eurofarad公司的发展小趣事

Eurofarad始终将技术创新作为公司发展的核心动力。随着科技的不断进步,Eurofarad不断投入研发资源,推动电子元件技术的创新。公司成功研发出了一系列具有创新性的产品,如陶瓷电容器、塑料薄膜电容器、云母电容器等。这些产品不仅具有更高的性能和更长的使用寿命,而且更符合市场的需求,为Eurofarad赢得了更多的市场份额。

Falco Electronics公司的发展小趣事

随着公司的发展,Falco Electronics开始积极拓展市场。公司不仅在国内市场取得了显著成绩,还积极开拓国际市场。同时,Falco Electronics还与其他行业领军企业开展战略合作,共同开发新产品、拓展新市场。这些合作不仅为公司带来了更多的商机,也提升了公司在行业内的地位和影响力。

CITIZEN公司的发展小趣事

随着技术的不断进步和产品的不断创新,西铁城公司开始积极拓展全球市场。公司的产品以其高品质、精确度和创新技术而闻名,逐渐赢得了全球消费者的青睐。同时,公司也积极参与国际性的钟表展会和活动,通过展示最新产品和技术成果,进一步提升品牌知名度和影响力。这一系列的举措使得西铁城在全球市场上的地位日益稳固。

ABOV(现代单片机)公司的发展小趣事

随着技术的不断进步和产品的不断创新,西铁城公司开始积极拓展全球市场。公司的产品以其高品质、精确度和创新技术而闻名,逐渐赢得了全球消费者的青睐。同时,公司也积极参与国际性的钟表展会和活动,通过展示最新产品和技术成果,进一步提升品牌知名度和影响力。这一系列的举措使得西铁城在全球市场上的地位日益稳固。

Analog Power公司的发展小趣事

品质是Analog Power公司的生命线。他们深知只有提供高质量的产品和服务,才能赢得客户的信任和忠诚。因此,公司建立了严格的质量管理体系,从原材料采购到产品出厂的每一个环节都进行严格把控。同时,公司还注重客户反馈和需求,不断优化产品和服务,以满足客户的期望和需求。

问答坊 | AI 解惑

光电耦合器的应用电路

光电耦合器的应用电路…

查看全部问答>

arm及其外扩芯片的,不知道是哪部分出现了问题的问题总结

首先 arm软件开发环境rvds,arm7或9+jtag(14针),arm外扩nandflash ,norflash,ram,ad 以下情况都能检测到芯片id 第一种,进入axd中准备下程序时出现对话框,can\'t halt target and make it enter DEBUG state   网上有种说法是ar ...…

查看全部问答>

usb主从设备通信速率问题

从设备是HID设备,每次传输最大字节数为256。使用libusb-1.0.6库开发,异步IO方式。通信主要用传信令数据,每个信令包大概10字节左右。由于传输速率只与USB提交报告次数有关,故每次发送字节数越少比特率越低。现回环测试,1000个包,每个包10字节 ...…

查看全部问答>

请教如何提高SD卡的读写速度?

我们的掌上产品用到了SD卡,但是速度很慢:读1MB/Sec,写300KB/Sec 产品芯片使用DM320,内置SD控制器,平台是嵌入式Linux。我们查询了许多资料,提高速度的方法如下: 1.使SD卡工作在MMC模式,而非SPI模式 2.使用多块读写方式 我们想知道的是,一 ...…

查看全部问答>

菜鸟提问 :直接修改PCB中的net的信号属性?

在allrego PCB editor 是否可越过修改电路原理图,不再导入网表而直接修改PCB中的net的信号属性?     有空请回答下这个问题。谢谢。…

查看全部问答>

【学习Sitara™ AM335x】-PhyCORE-AM335X Linux Quickstart

http://www.phytec.com/wiki/index.php?title=PhyCORE-AM335X_Linux_Quickstart-PD12.1.0 1 About this QuickstartThis document describes how to install and work with the Linux Board Support Package (BSP) for the phyCORE-AM335X platfor ...…

查看全部问答>

双节特惠 全场九折

双节特惠 全场九折 各种stm32 开发板 欢迎大家选购 cyanfeel.taobao.com…

查看全部问答>

只想吐槽2812的引脚设计

2812 LQFP封装的引脚真变态,想扩展个SRAM发现地址数据线到处都是,太乱了,不知道要打多少过孔了。相比之下28335的引脚要整齐多了,真想换个28335来做。…

查看全部问答>

神经控制

如何编写神经控制的串级控制模块 …

查看全部问答>