打印

STM32 I2C 问题

[复制链接]
12155|43
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 shizaigaole 于 2010-7-14 16:13 编辑

最近调stm32 的 I2C 程序。
采用中断方式,
顺便监控了一下I2C中断事件,
读EEPROM的时候,数据如下:
0x00030001 I2C_EVENT_MASTER_MODE_SELECT
0x00070082 I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED
0x00070080 I2C_EVENT_MASTER_BYTE_TRANSMITTING
0x00070084 I2C_EVENT_MASTER_BYTE_TRANSMITTED
0x00070084
0x00070084
0x00070084
0x00070084
0x00070084
0x00070084
0x00070084
0x00070084
0x00070084
0x00070084
0x00070084
0x00070084
0x00070084
0x00070084
0x00030001
0x00030002  I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED
0x00030040(30个) I2C_EVENT_MASTER_BYTE_RECEIVED


非常奇怪的是当写完eeprom内存地址,restart以后,
stm32还连续产生了15次 I2C_EVENT_MASTER_BYTE_TRANSMITTED事件,
才能进入从模式选择,

进了14次中断重复
I2C_GenerateSTART(I2C1, ENABLE);

好像不大应该啊
沙发
lut1lut| | 2010-7-14 17:27 | 只看该作者
本帖最后由 lut1lut 于 2010-7-14 17:47 编辑

这就要看你每个case下,如何处理的咯。

我是在0x70080这个case中,就判断,如果是读数据,则发送restart。

这样,退出0x70080后,会进一个0x70084,然后就0x30001了。

LZ得到这样的flag sequence,我估计你是在0x70084的case中才发送restart。

如果果真如此,你要是把I2C时钟,以及系统主频时钟再降低些,你的到的0x70084会更多,不止15个了。;P

使用特权

评论回复
板凳
shizaigaole|  楼主 | 2010-7-14 18:06 | 只看该作者
LS,
果然高手,
实在0x70084的case中才发送restart,

但是按说也应该会立即进入 0x00030001 I2C_EVENT_MASTER_MODE_SELECT

不知两者到底有何差别?

使用特权

评论回复
地板
lut1lut| | 2010-7-15 10:10 | 只看该作者
在0x70084(TRA,BUSY,MSL,TXE,BTF)的case中执行发送restart的操作,退出ISR后,一方面I2C硬件开始在I2C总线上发出这个Start信号,注意这个过程相对于MCU运行速度来说,要持续一段时间。另一方面,在这段时间内,STM32一直在运行着,以上5个flag一直被置位着,所以退出ISR后,又进去,又退出,又进去,你这里进去了14次多余的0x70084。

直到Restart信号出现在I2C总线上了,h/w将TXE,BTF,TRA清零,同时置位SB,于是此时在进入中断,就走到0x30001的case了。

使用特权

评论回复
5
shizaigaole|  楼主 | 2010-7-15 10:27 | 只看该作者
本帖最后由 shizaigaole 于 2010-7-15 10:41 编辑

但是 ,我写eeprom,
写完第一页,开始写第二页,
如果写完成时直接在I2C_EVENT_MASTER_BYTE_TRANSMITTED处,
发I2C_GenerateSTOP(I2C1, ENABLE);
则第二页不能写,
中断事件如下:

使用特权

评论回复
6
shizaigaole|  楼主 | 2010-7-15 10:44 | 只看该作者
如果写完成时直接在I2C_EVENT_MASTER_BYTE_TRANSMITTED处,发I2C_GenerateSTOP(I2C1, ENABLE);          while(I2C_GetLastEvent(I2C1) != 0)            ;等一下,则只产生一个0x70084,以后各页可以写入,事件监控如下:

使用特权

评论回复
7
shizaigaole|  楼主 | 2010-7-15 10:49 | 只看该作者
说明产生多个0x70084和stm32的工作错乱有一定的关系。

但是我直接在I2C_EVENT_MASTER_BYTE_TRANSMITTING中,
最后一个字节发送完成后处理I2C_GenerateSTOP(I2C1, ENABLE);

程序不能正常工作

使用特权

评论回复
8
shizaigaole|  楼主 | 2010-7-15 11:00 | 只看该作者
更正:
有调了一下,
以上现象可能eeprom写入时间间隔有关系,
和0x70084不一定有关

使用特权

评论回复
9
shizaigaole|  楼主 | 2010-7-15 11:27 | 只看该作者
又调试一下,
看来多个0x70084对程序还是有影响,
如果发
I2C_GenerateSTOP(I2C1, ENABLE);         
while(I2C_GetLastEvent(I2C1) != 0)
  ;
等一下,只产生一个0x70084,

则再第二次页写之前,延时一会等待EEPROM可写,
则程序正常,

否则不管第二次页写之前,延时多长时间,
都不能第二次写。


看来STM32发停止位以后,不能立即停止总线,对EEPROM还是产生了影响。

使用特权

评论回复
10
香水城| | 2010-7-15 11:41 | 只看该作者
停止位的作用不是停止总线。

使用特权

评论回复
11
shizaigaole|  楼主 | 2010-7-15 11:43 | 只看该作者
可能我概念理解不对。
但是中断直接发送停止位,不等待,导致多个0x70084事件进入中断,
确实会对EEPROM第二次写产生影响。

使用特权

评论回复
12
lut1lut| | 2010-7-15 14:13 | 只看该作者
哇哇哇!

为什么你6楼的能够正确运行呢。因为:

当代码进入,0x70084(transmitted,i2cEventGroup[10])时,总线上已经被要写的数据全部发送出去了。在这个case里,你的代码执行发送STOP的操作,然后通过你的while(I2C_GetLastEvent(I2C1) != 0),把eeprom它内部的写逻辑周期(写第一页)等待完成了。SR1/SR2都为0,可见此时总线已经处于idle状态了,接着你发送Start信号也是在这个while()之后吧。由此再进入0x30001(i2cEventGroup[11]),继续通信。。。

使用特权

评论回复
13
lut1lut| | 2010-7-15 14:27 | 只看该作者
为什么你5楼“会对EEPROM第二次写产生影响”呢,要看你在每次0x70084的case中都作了什么操作了。

贴那个case的代码吧。

使用特权

评论回复
14
shizaigaole|  楼主 | 2010-7-15 14:32 | 只看该作者
case I2C_EVENT_MASTER_BYTE_TRANSMITTED: /* With BTF EV8-2 */         
          I2C_GenerateSTOP(I2C1, ENABLE);
          //while(I2C_GetLastEvent(I2C1) == I2C_EVENT_MASTER_BYTE_TRANSMITTED)
           // ;
          wrTaskState = 3;  //一帧写完毕标志

使用特权

评论回复
15
shizaigaole|  楼主 | 2010-7-15 14:35 | 只看该作者
如果不加
while(I2C_GetLastEvent(I2C1) == I2C_EVENT_MASTER_BYTE_TRANSMITTED)
       ;

再下一次写数据,不论延时多少时间,I2C中断I2C_EVENT_MASTER_MODE_SELECT以后,
再也不能进入中断了!

使用特权

评论回复
16
shizaigaole|  楼主 | 2010-7-15 14:35 | 只看该作者
加了这句以后,
读写一切OK

使用特权

评论回复
17
lut1lut| | 2010-7-15 14:38 | 只看该作者
哇哇哇,你在哪里发送Start的?

使用特权

评论回复
18
shizaigaole|  楼主 | 2010-7-15 14:40 | 只看该作者
下一页数据写,
在主程序里面判断
wrTaskState =  =3,
延时一会写start

使用特权

评论回复
19
shizaigaole|  楼主 | 2010-7-15 14:42 | 只看该作者
其实现在程序读写都OK了,
就是不明白需要屏蔽多个I2C_EVENT_MASTER_BYTE_TRANSMITTED中断的道理

使用特权

评论回复
20
shizaigaole|  楼主 | 2010-7-15 14:56 | 只看该作者
手册上说:
EV8_2(I2C_EVENT_MASTER_BYTE_TRANSMITTED):TxE=1,BTF=1,请求设置停止位。TxE和BTF位由硬件在产生停止条件时清除。

看来设置停止操作以后,STM32确实就撒手不管了(导致多次检测到EV8_2事件,多次进入中断),
经过很长时间以后硬件检测到停止条件以后,TxE=1,BTF=1,才被清除。

使用特权

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

本版积分规则

146

主题

3735

帖子

11

粉丝