-
2017
年
6
月
30
日星期五
目的
:利用
TMS320F2801
芯片上外设
I2C
(
2
线串口)读写
EEPROM
数据(
24LC128
)
关键点
1
:
24LC
时钟频率
40
0KHz
,寄存器设置如下:
I2caRegs.
I2CPSC
.
all
=
9;
I2caRegs.
I2CCLKL
= 10;
I2caRegs.
I2CCLKH
= 5;
// Prescaler - need 7-12 Mhz on module
clk
// NOTE: must be non
zero
// NOTE: must be non
zero
时钟频率也可设为
200KHz,
< br>三个参数分别为
9
、
20
、
20
(
CPU
p>
时钟频率为
100MHz
)
(未测试
?
)
关键点
2
:波形分析
p>
问题:
I2C
模块是不是只有
I2CCNT
减到
0
才会
发出停止信号
I2C
模块是硬件的,
当检测到发送完了就会发结束自动发信号,不需要人为干预
问
题
1
:字节写操作正常,但是字节读函数出错
< br>
原因:
写
EEPROM
是在七位器件地址后添加
写标志
,而
读
EEPROM
需要在七位器件地址后
添加写标志。
关键点:
读
EEPROM
数据需要发送两次命令。第一次为写地址(此
地址会被赋值给
EEPROM
内的地址指针)
< br>,因此需要添加写标志;第二次为读数据,将写标志改为读标志。
问题
2
:主机接收时,
SD
A
数据线上有数据传输,且
I2CDRR
接收数据寄存器有数据更新,
但寄存器显示不可读,即
CPU
认为一直没接收到数据,
一直停在下面语句
while
关键点:
初始化设置时采用的是
FIFO
接收方式,因此
无效,应查询
FIFO
接收中断位
wh
ile
方式查询位。
此位只有在非<
/p>
FIFO
中断接收方式时才有效。
p>
问题
3
:断续单字节读写正常,但是采用连
续的单字节读写出错。
原因:
EEP
ROM
写过程的结束并不是
I2C
总线
写结束就结束,实际上
I2C
总线的写入数据先
被保存到了
EEPROM
内部的缓冲区,当遇到
I2C
结束条件后,
EEPROM
才启动内部写过程,
这个过程才是保存数据的过程。
非常悲哀的是这个过程比较长,
官方文档标注为
5ms
。
如果
在这
5ms<
/p>
以内对
EEPROM
芯片访问将被忽略。
关键点:读写
EEPROM
应延时至少
5ms
,软件延时
< br>10ms
do{}while(EEPROM_Timer <= 10);
//
10ms
问题
< br>4
:查询
EEPROM
写过程是
否结束造成死机,只能查询
EEPROM
读过程。
官方文档说
EEPROM
内部写周期最长为
5ms
,在很多情况下是远远低于
5ms
的,为了节约
时间,
官方给出一个解决办法。
当写周期完毕后就开始进行应答查询,
来确定
EEPROM
写周
期何时结束
。
所谓应答查询官方解释为:
就是向
E
EPROM
发送一个
I2C
起始条件后
发送器件
地址和一个读写标志位,当
EEPROM
完成内部写周期会回应一个
ACK
,这时
MCU
就可以进
行正常的其他读写过程了。官方原
文如下:
杯具就是始于我画红线的那句话,
< br>它说可以在器件地址后任意填写读写标志。
我就填了读标
志,事实证明在
EEPROM
写入过程采用读查询将导致系统死
机,
I2C
总线不能被正常拉高,
可能
是
EEPROM
内部已经把总线拉到了地!不管怎样,反正就是
死机了
。经过多次尝试最
终发现应答查询只能采用写应答查询可
以正常确定
EEPROM
内部写周期的结束。
< br>
——
by
数据传输过程:
从机发送数据
?
SDA
总线
?
p>
I2CRSR
缓冲寄存器
?
I2CDRR
接收数据寄存器
?
中间变量
?
内存。
问题
5
:
CPU
以字(双字节)为单位读写
EEPROM
数据有误<
/p>
;
原因:
CP
U
中的内存单元以字(
word-16bit
< br>)为单位,而
EEPROM
中的内存单元是字节
(
byte-8bit
)为单位,因此将
CPU
内存地址转化为
EEPROM
指针地址时,因乘以
2
(左移一
位)
问题
6
:使用读数据函数式,收到的数据都是
1
。
原因:
EEPROM
初
次读取未写过的内存单元时,默认为高电平,即收到的字节为
0xFF
< br>。
如果已经写过内存单元,则代表数据未成功写入;
写入与读数据的内存地址不一样。
问
题
7
:写入
EEPROM
的数据与随后读出来的数据不一致,但读出来的数据又没有规律性。
可能原因:
数据未成功写入;数据读写字节数超过
EEPROM
的页内字节数(跨页)
;读写地
址不一致;读写
EEPROM
之间应有一定的延时时
间。
解决办法:
若连续读多字节数据
,则读取数据之间应加延时,因为数据从
I2CRSR
数据接收
缓冲寄存器(多字节)复制到
I2CCDRR
< br>数据接收寄存器(一字节)需要时间。
单字节延时
p>
25us
,双字节(字)延时
50us
p>
——
测试通过
问
题
8
:
使用示波器观测
SDA
数据线上的波形时,
发现每次应答信号之前都有
一个毛刺
(尖
峰)
,是什么原因导致的
(不影响数据的正常读写)
类似问题:
使用
F28335
模拟
I2C
时序读取惯导器件的数据时,发现在更改
SDA
的传输方向
时,
Gpio
中数据寄存
器会发生变化,导致
SDA
上有毛刺产生。
问题
9
:
<
/p>
I2C
在跟
EEPROM
通讯的时候,第一次写入数据,一个一个读取的话,能知道写入
EEPROM<
/p>
的值是没有错的,但是在连续读取数据的时候,就会出现,
上电第
一次读取数据串
的时候,是全部读取正确,然后再读取一遍数据串的时候,只有第一个读
取的数据是正确
的
,后面的数据会全部变成
FF FF
这是怎么回事
办法
1
:大家都说
STM32
的
IIC
有点
bug
,所以很少人用其自带的
IIC
,一般都是用
IO
口
模拟
I
IC
,模拟很简单而且不会出错。
逻
辑分析仪抓取
I2C
总线数据,
?
p>
改为转接板抓取数据,即
I2C
转
USB
通讯。
问题<
/p>
10
:
I2C
给
EEPROM
写数据时,
两字节地址需
不需要算进去吗
答案:需要,
且地址
字节数与
EEPROM
的型号(容量)相关,有些为
1
字节地址,有些为
2
字
节地址。
24LC128
需要两字节地址来区分内存单元,其内
存最小单元为
1
字节,
地址从
0x00
开始,一页
64
字节,因此地址指针范围为:
0x00~0x3F
。
I2caRegs.I2CCNT =
(<
/p>
n<<1
)
+2;
问题
11
:一次读写数据字节数最好不超过
16
字节。
原因:
其一
I2C
深度寄存
器范围限定,
其二,
读写数据字节太多会导致
< br>I2C
总线出错的概率
加大。
ST_5bit
(
0x0000~0
x10000
)
_5bit
_5bit
(
0x0000~0x10000
)
_5bit
I2caRegs.I2CCNT_32bit
问题
12
:总是提示总线繁忙
= 1
总线繁忙,
BB = 0
总线空闲
关键:总线繁忙这个位只读。
猜想解
决办法:
如果是上电第一次读写就出现总线繁忙,就对
I2C<
/p>
模块进行复位;
如果不是第一次,且<
/p>
I2C
总线上只有一主,则等待一定时间(
5ms
)
;
如果是多主,则返回,等待总线空闲吧。
问题
13
:
CPU
写数据给
EEPROM
时,如果设置断点,就能成功写
入数据,但没有断点,数
据写不成功。什么原因呀
原因:写保护
WP
引脚的电平应在接收到停止信号
后,应保持低电平一段时间才使能写保