中科因仑“3+1”工程特种兵精英论坛
标题:
采用CSL调试C5509A的I2C小结
[打印本页]
作者:
惨淡的人生
时间:
2016-4-3 21:59
标题:
采用CSL调试C5509A的I2C小结
这两天在用CSL调试I2C总线接口的EEPROM,型号为24LC01。但是始终读写总是失败。以前在配置AIC23的时候,曾用过I2C。那时是根据瑞泰的程序修改的,但是程序运行不稳定,有时会出现无法配置的情况。这次比较有时间,对这个问题仔细研究了一下。
现在已经解决了,写了篇总结,以供参考。
由于我是从主板上引线到EEPROM板子的,所以开始怀疑是信号频率过高。测试波形,发现根本没有波形输出。降低5509A的主频,降低I2C总线的频率。经过N次尝试,终于能够正确读取数据了。测试波形,发现上升沿不是很陡峭,把I2C总线的上拉电阻由10k修改为了2.2k。这样上升沿足够陡峭了(至少确定该上升沿足够满足400k的频率了)。
恢复5509A的主频,提高I2C总线频率,读写还是失败。测试波形,仍然没有输出。在网上找到了一篇C5509A的I2C模块的应用文档(见参考文献),里面有读写EEPROM的例子。根据那个例子修改,读写仍然失败,现象依旧。
进一步搜索,发现有不少人碰到了类似的问题。最后,在TI的e2e社区找到了问题的所在(网址见参考文献)。原来是CSL中的I2C_setup函数有问题。摘取其中的解决方法如下:
I2C_FSET(I2CSTR,BB,0x1); /* Writing a 1 to BB Bus busy bit is supposed to clear it*/
/* Initializes I2C registers using initialization structure */
I2C_setup(&Init);
/* Need to calcualte I2CCLKL & I2CCLKH manually has functionnality not fully miplmented in CSL*/
I2C_RSET(I2CCLKL,220); /* Clock Divider Low register */
I2C_RSET(I2CCLKH,220); /* Clock Divider High register */
也就是在配置I2C模块之前,需要把I2CSTR寄存器中的BB位置1。同时,在待用完毕I2C_setup函数后,再重新配置一下I2CCLKL和I2CCLKH寄存器。
顺藤摸瓜,找到了CSL中的源文件,看到其中I2C_setup函数的代码如下:
void I2C_setup(I2C_Setup *Init) {
int old_intm;
Uint16 IPSC_calc;
old_intm = IRQ_globalDisable();
I2C_RSET(I2CMDR,I2C_I2CMDR_RMK(Init->free,0,0,0,1,1,Init->addrmode,0,Init->dlb,1,0,0,Init->bitbyte));
/* set own address */
I2C_RSET(I2COAR,Init->ownaddr); /* if slave, need to specify own address */
/* calculating the IPSC value */
IPSC_calc = (Init->sysinclock)/12; /* must correct rounding issue */
I2C_RSET(I2CPSC,IPSC_calc);
/* calculating the ICCLKL and ICCLKH register values */
I2C_RSET(I2CCLKL,15);
I2C_RSET(I2CCLKH,15);
IRQ_globalRestore(old_intm);
} /* end of init */
分析上面的程序,在计算I2C总线的频率时,出现了错误:因为I2C总线的频率主要由I2CPSC、I2CCLKL和I2CCLKH寄存器共同决定的。在程序中,根本就没有去查询I2C_Setup结构体中rate变量,只是查询了系统时钟,然后给I2CPSC寄存器赋值,而给I2CCLKL和I2CCLKH寄存器赋了固定值15。这无法正确完成I2C时钟的配置。
打算重新编写这个函数。假设,input频率单位为MHz,I2C总线频率为kHz,则I2C总线频率的计算公式为:
module clock * 1000
master clock=-------------------------------------------------
[( ICCL+d )+( ICCH+d )]* (IPSC+1)
令ICCL = ICCH,则得到公式为:
input clock * 1000
master clock=------------------------------------------
2 * ( ICC+d ) *(IPSC+1)
根据上面的分析,重新编写了I2C_setup函数,如下:
void myI2C_setup(I2C_Setup * Init)
{
int old_intm;
Uint16 ICC_calc;
old_intm = IRQ_globalDisable();
I2C_RSET(I2CMDR,0); // reset I2C
// Set prescaler to generate module clock
// I2C input clock
// module clock=-------------------- , d=5
// ( IPSC+1 )
//
I2C_FSET(I2CSTR,BB,0x1); /* Writing a 1 to BB Bus busy bit is supposed to clear it*/
/* calculating the IPSC value */
I2C_RSET(I2CPSC,11);
// Set I2CCLKL & I2CCLKH to generate master clock
ICC_calc = (Init->sysinclock)/12;
ICC_calc = ICC_calc * 1000/2/(Init->rate);
ICC_calc = ICC_calc - 5;
I2C_RSET(I2CCLKL,ICC_calc); // 100kHz
I2C_RSET(I2CCLKH,ICC_calc);
/* set own address */
I2C_RSET(I2COAR,Init->ownaddr); /* if slave, need to specify own address */
//I2C模块复位,设置为主设备发送模式
I2C_RSET(I2CMDR,I2C_I2CMDR_RMK(Init->free,0,0,0,1,1,Init->addrmode,0,Init->dlb,1,0,0,Init->bitbyte));
}
通过测试,该函数能够成功用于EEPROM和AIC23的读写测试中。
此外,在采用byte write方式向EEPROM中连续写入数据时,注意在两次写入之间添加一个延时程序,否则会造成写入失败。
备注:总结的一些知识点也放在这里,供参考。
1、关于24LC01知识点
24LC01共有128x8 bits=1k bits存储空间。关于24LC01、24LC02、24LC04、24LC08、24LC16的命名规则:其中,01、02、04、08、16表示存储空间为1k、2k、4k、8k、16k。
24LC01的写有两种方式:byte write和page write。前者只能写入一个字节数据,后者最多可以写入8个字节数据。读有三种方式:Current Address Read、Random Read、Sequential Read。第一种读取当前地址数据,第二种读取某个地址数据,第三种可以连续读取多个数据。在每次读写操作后,24LC01内部的地址会自动加一,连续读取写入多个数据就是基于这个原理。
关于slave address,包括control code和block select bits两部分。对于24LC01来讲,block select bits可以忽略。其slave address为0x50。
2、关于CSL中I2C模块函数
主要用到的函数包括:I2C_setup、I2C_read和I2C_write。
1) 关于I2C_setup,下面代码为I2C模块的相应配置信息。
I2C_Setup Setup = {
0, /* 7 bit address mode */
0x0000, /* own address */
144, /* clkout value (Mhz) */
400, /* a number between 10 and 400 */
0, /* 8 bits/byte to be received or transmitted */
0, /* DLB mode off */
1 /* FREE mode on */
};
2) 关于I2C_read和I2C_write,注意其中的模式选择,共有以下三种模式:
1) S-A-D..(n)..D-P
2) S-A-D..(n)..D (repeat n times)
3) S-A-D-D-D..... (continuous)
其中S表示start condition,A表示address,D表示data,P表示stop。模式1用于n个数据操作,最后会有stop信号。模式2一用于n个数据操作,但最后没有stop信号。模式3用于多个数据操作,也没有stop信号。
参考文献:
1、Programming the TMS320VC5503/C5506/C5507/C5509/C5509A I2C Peripheral (SPRA785A)
2、TMS320C55x Chip Support Library API Reference Guide(SPRU433J)
3、24LC01数据手册
4、TMS320VC5501/5502/5503/5507/5509 DSP Inter-Integrated Circuit (I2C) Module Reference Guide (SPRU146D)。
5、http://
e2e.ti.com/support/dsp/tms320c5000_power-efficient_dsps/f/109/p/11040/43000.aspx
欢迎光临 中科因仑“3+1”工程特种兵精英论坛 (http://bbs.enlern.com/)
Powered by Discuz! X3.4