打印
[STM32F1]

血的经历告诉大家,慎用stm32的硬件iic

[复制链接]
楼主: 摩天轮1111
手机看帖
扫描二维码
随时随地手机跟帖
41
摩天轮1111|  楼主 | 2016-2-26 15:12 | 只看该作者 回帖奖励 |倒序浏览
码客_Mark 发表于 2016-2-25 19:12
换MPU6500吧,SPI速度爽死,还没bug

你说的很有道理,我后面是要考虑换mpu6500,这样留给我运算和控制等等的实时性要好很多,控制频率可以做到很高,

使用特权

评论回复
42
371924221| | 2016-2-26 20:44 | 只看该作者
nametony 发表于 2016-2-20 22:01
自己遇到问题, 自己解决不了, 就劝人家慎用, 实在好讨厌!
如果你摆出了事实证明STM32硬件I2C有问题, 那是立 ...

把你的代码贴出来看看有什么不同

使用特权

评论回复
43
摩天轮1111|  楼主 | 2016-2-29 14:37 | 只看该作者
371924221 发表于 2016-2-26 20:44
把你的代码贴出来看看有什么不同

很抱歉代码不能公开,讨论问题不一定非要停留在代码层面的,我感觉,对于这个问题我描述的也很仔细的,代码这里没有多大用处的,真的有做过硬件iic,可以解释出在我描述的情况下,有哪些因素可以导致的一些结果和我的现象一样,,如何的解决思路,这些是很好的讨论方向

使用特权

评论回复
44
摩天轮1111|  楼主 | 2016-2-29 14:48 | 只看该作者
IversonCar 发表于 2016-2-21 09:34
我用的时候驱动mpu6050是没有问题的,但是问题是速度快了就不行了

你的现象我有遇到,我最开始的时候是硬件iic,写dmp固件的时候,居然速度快了之后写不进去,你说奇葩吧,当时是超过200khz就写不进去固件,然后读数可以360khz,硬件上有说要400khz,apb1还是哪个时钟要10M倍数,我不是,所以是360khz,再后来我用来dma的iic,居然发现写固件可以360khz的速度写进入了,再后来我也控制逻辑越来越复杂,加了一些中断,还有等等的,有时候我切换一下dma的iic,有时候就是硬件的iic,它居然硬件iic可以360khz往里写,我想想都奇葩,实在费解是哪里导致的,st的硬件iic应该说单独去用真的没问题,他官方的例子也是单独用的,但是多任务一起时候,就会慢慢搞死你了

使用特权

评论回复
45
摩天轮1111|  楼主 | 2016-2-29 14:51 | 只看该作者
Mancherstun 发表于 2016-2-21 13:23
那iic有这些bug,该如何解决呢
如果用模拟的话如何提高速度呢

你的问题我一开始也是疑惑的,解决我不清楚是不是bug导致的,不敢乱说,每次不同的情况导致了故障,都慢慢尝试有能解决的时候,甚至有时候的解决办法只是换下配置函数的顺序,至于模拟的iic,提高速度可以用那个while循环延时的那个,改变那个延时函数里面的数大小,改的越小延时越小,这样速度就越快了,基本就是这么调速度,速度可以做到接近400k,因为是while循环做的延时,准确的通讯速率要示波器或者逻辑分析仪看吧,

使用特权

评论回复
46
摩天轮1111|  楼主 | 2016-2-29 14:54 | 只看该作者
LguoFu 发表于 2016-2-22 09:33
你的意思是I2C操作放中断里?

是的,如果你iic读取数据,可以作为最高优先级的事情,别的事情没有比他更重要的,就是一般实时控制中,有些事情是间隔个时间就要做,一点不能被打断的,那种事情里面,iic不能作为最高优先级,你这里如果没有这样的,iic可以放在一个中断里面,中断优先级最高,这样就不会被打断iic了,那么你肯定不会出问题了

使用特权

评论回复
47
摩天轮1111|  楼主 | 2016-2-29 14:55 | 只看该作者
Bermanrep 发表于 2016-2-26 09:10
st公司不是有这个bug的解决方案了吗

所谓 的bug解决方案,然并没什么暖用,我就是那么用的,

使用特权

评论回复
48
xijiele| | 2016-2-29 17:51 | 只看该作者
貌似F7的I2C外设做了比较大的改进,连寄存器都改了,不知道还会不会出问题

使用特权

评论回复
49
aerwa| | 2016-3-1 08:18 | 只看该作者
我很奇怪的是你完全可以将硬件iic的操作代码贴出来我们一起分析,又不是什么秘密。

使用特权

评论回复
50
gowow| | 2016-3-1 09:39 | 只看该作者
aerwa 发表于 2016-3-1 08:18
我很奇怪的是你完全可以将硬件iic的操作代码贴出来我们一起分析,又不是什么秘密。 ...

你让他发iic代码的人又不是楼主,楼主也搞差了。。。

我用了好几年STM32,I2C也听了很久了,一堆人喊不好用。
只有偶尔几个人说没问题是你们自己不会用,又不来点干货,只知道吹。
我曾经试着用CPAL库断断续续搞了个把月,放弃了,这尼玛实在太难debug了

使用特权

评论回复
51
crazybee| | 2016-3-1 10:26 | 只看该作者
STM32 勘误表里不是说明了,IIC问题了,,,官方都说有问题了,  F0F4 估计好多了,听说更改了设计。

使用特权

评论回复
52
gowow| | 2016-3-1 17:08 | 只看该作者
crazybee 发表于 2016-3-1 10:26
STM32 勘误表里不是说明了,IIC问题了,,,官方都说有问题了,  F0F4 估计好多了,听说更改了设计。 ...

我就是调的F4。
应该是F0和F3吧,用的新版iic

使用特权

评论回复
53
金融小数| | 2016-3-2 17:18 | 只看该作者
什么时候有空开个帖子,单独来聊聊STM32F10x系列的I2C的那些事。

使用特权

评论回复
54
摩天轮1111|  楼主 | 2016-3-7 21:57 | 只看该作者
gowow 发表于 2016-3-1 09:39
你让他发iic代码的人又不是楼主,楼主也搞差了。。。

我用了好几年STM32,I2C也听了很久了,一堆人喊不 ...

好吧,我也是那个喊你们不会用的人之一,只是确实喊不好用的人分两种啊,一种没有实际操作过,或者没看明白去操作的,弄不出来,这种呢,是正常的单独使用iic都可能出问题的,而另一种是曾经调好了也能十分正常的工作的,但是没有试过在大的系统工程里面也使用低优先级的iic,而在这之前喊的没问题,而进入大系统工程之后,总是出现奇奇怪怪的问题,喊不好用的,我算是后者吧,这里也为曾经喊说不会用是没用好道歉,至于干货翻我的帖子我有发过怎么使用硬件iic的帖子,只是引了个头的,这里的后面自己写的一些高阶的硬件iic代码是真的不方便公开,只能这里再说一句,我经历了这个,感受就是要用他要有思想准备,在大系统的工程里面会有一堆堆的意想不到的问题,大家要有心理准备,f3和f0的我看了,重新设计了,应该没有这个问题了

使用特权

评论回复
55
uouo00| | 2017-1-18 16:25 | 只看该作者
本帖最后由 uouo00 于 2017-1-18 16:26 编辑

在 I2C 的规范中定义了时钟延展协议。通过这一协议,SLAVE 设备在没有条件接收或发送下一个数据时,可以拉低 SCL 信号,通知 MASTER 设备暂停数据的传输,直到 SLAVE设备释放 SCL 信号。对于 STM32 的I2C接口来说,如果 CR1 寄存器中的 NO STRETCH 位为‘0’则开启时钟延展协议,而该位为‘1’时关闭时钟延展协议。在开启了时钟延展协议的情况下,STM32 的I2C接口作为 SLAVE 设备接收数据时,如果 SR1 中的 RxNE 不为‘0’,也就是接收缓冲区不空,则会送出时钟延展信号,将 SCL 信号拉低。同样情况下,作为 SLAVE 设备发送数据时,如果发送缓冲区为空,即 SR1 中的 TxE 为‘1’时,也会送出时钟延展信号。在关闭了该协议的情况下,STM32 的I2C接口不会向外发送时钟延展信号。而此时,软件必须检测 SR1 寄存器中的 OVR 位,来判断是不发生了接收数据覆盖或重复发送问题。
建议:
在 I2C 的规范中定义了时钟延展协议。通过这一协议,SLAVE 设备在没有条件接收或发送下一个数据时,可以拉低 SCL 信号,通知 MASTER 设备暂停数据的传输,直到 SLAVE设备释放 SCL 信号。对于 STM32 的I2C接口来说,如果 CR1 寄存器中的 NO STRETCH 位为‘0’则开启时钟延展协议,而该位为
‘1’时关闭时钟延展协议。在开启了时钟延展协议的情况下,STM32 的I2C接口作为 SLAVE 设备接收数据时,如果 SR1 中的 RxNE 不为‘0’,也就是接收缓冲区不空,则会送出时钟延展信号,将 SCL 信号拉低。同样情况下,作为 SLAVE 设备发送数据时,如果发送缓冲区为空,即 SR1 中的 TxE 为‘1’时,也会送出时钟延展信号。在关闭了该协议的情况下,STM32 的I2C接口不会向外发送时钟延展信号。而此时,软件必须检测 SR1 寄存器中的 OVR 位,来判断是不发生了接收数据覆盖或重复发送问题。

使用特权

评论回复
56
xcs101| | 2017-4-30 10:09 | 只看该作者
关于楼主说的把IIC放在中断里读取的问题,我认为没把握好各个信号和任务间的时序关系。如果IIC不能被打断,那么可以把优先级调高,如果可以被打断,没有发送成功应该设置相应得标志位,以达到在其他工作完成,在判断是否传输失败和是否再次触发。其次,单纯用IIC做通信是不过的,还需要结合协议来完成对数据的校验,我认为:只要能成功用IIC读取一次,其他问题都可以在这个基础上,对程序流程进行优化。
程序设计最难的不是如何驱动外设,而是如何优化流程,也就是算法。虽然st公司的IIC有问题,但我们有时也可以牺牲点时间和资源来解决。

使用特权

评论回复
57
woshizhengjie89| | 2017-5-16 15:39 | 只看该作者
有空实测下

使用特权

评论回复
58
xuannin| | 2017-5-18 08:53 | 只看该作者
I2C死了的时候,系统复位都不能活过来,除非你断电重启,你不要说你没碰到,爱用不用,个人所好,不必再无谓争执

使用特权

评论回复
59
l4157| | 2017-10-1 17:21 | 只看该作者
我也碰到了这个BUG,经过网上一个大神的提示,这样修改初始化后修复了...
/* USER CODE BEGIN I2C1_MspInit 0 */
//For STM32 IIC BUG
//    __HAL_AFIO_REMAP_I2C1_ENABLE();
               
    __HAL_RCC_I2C1_CLK_ENABLE();
               
                GPIO_InitStruct.Pin = SCL_Pin|SDA_Pin;
                GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
                HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
               
                HAL_GPIO_WritePin( GPIOB, SCL_Pin, GPIO_PIN_SET);
                HAL_GPIO_WritePin( GPIOB, SDA_Pin, GPIO_PIN_SET);
               
                hi2c->Instance->CR1 = I2C_CR1_SWRST_Msk;
                hi2c->Instance->CR1 = 0;
               
  /* USER CODE END I2C1_MspInit 0 */
    /**I2C1 GPIO Configuration   
    PB8     ------> I2C1_SCL
    PB9     ------> I2C1_SDA
    */
    GPIO_InitStruct.Pin = SCL_Pin|SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    __HAL_AFIO_REMAP_I2C1_ENABLE();

    /* Peripheral clock enable */
    __HAL_RCC_I2C1_CLK_ENABLE();

使用特权

评论回复
60
ljc16888888| | 2017-11-3 15:19 | 只看该作者
mark

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则