"); //-->
TMS320F280X SPI SPIA使用入门与总结
Netjob @ 2009年 8月31日晚
我使用过NXP ARM LPC2138的SPI口,ATMEL AT91SAM7S256的SPI,MSP430F5438的SPI口,
还有STM32 的SPI模块。都是用来读 SPI FLASH 例如 AT45DB642D之类。
本以为对SPI已经入门了, 谁不知使用TMS320F280X的SPI后,才知道自己其实还是一知半解。
TMS320F280X 的SPI 真是好好给我上了一课!
不久前有款 OLED 真彩色液晶。使用的是SSD1351控制器,SPI接口。 想测试一下它的速度。就把它接到我的
TMS320F280X的DSP 开发板上。之前使用DSP的IO模拟,运行程序后OLED的效果不错的。
本想这次使用SPI应该没事吧『虽然I/O模拟也是使用这个SPI的引进』?
新建立一个工程 MYOLED, 拷贝一些TMS320F28X相关的头文件,C文件。把工程的设置好后,编译OK!
加上定时器中断用来点亮一个LED,把I/O模拟的工程相关文件的两个子函数改为SPI方式的。
在编译。文件太大非得使用FLASH下载仿真。
发现程序不能运行! 没办法改回RAM仿真,把很多函数注释掉。仅仅留下测试OLED的程序。
SSD1351的测试功能,向它写命令码,可以改变 GPIO1/GPIO2引脚的电平。这样测试SSD1351引脚的电平就知道SPI 驱动函数是否成功了。
其实移植就是仅仅这两个SPI底层函数:
void Write_Data(unsigned char Data)
void Write_Command(unsigned char Data)
测试好几次都没反应, 因此 就有下面的入门与详解了。
使用的是SPIA模块,如果SPIB没有什么特别(功能设置与SPIA差不多的话)也是没什么问题的。
但是我之前使用SPIB测试过,发觉SPIB还是与SPIA有区别的。这点我也很不解~。
按道理应该不会这样。但事实却是如此.
TMS320F280X的SPI 支持1-16位的数据类型。
而且 只有MSB先发送,不像ARM7/STM32等可以设MSB或LSB先发送。
TMS320F280X的SPI有回环模式, 可以用于测试,自发自收。
TMS320F280X的SPI有TX FIFO和RX FIFO. 及其中断字节设置。
看来没什么特别? 是吧~? 先别小看啊~,就是搞不定它呢!
首先是要回环模式,这样就是一个自发自收,方便测试。
其实现在看来,我曾经范了几点毛病。
1. 使用8位模式,但SPIA的总线,发送接收等寄存器都是16位模式。
2. 数据的位数设置不对
3. 时钟极性与时钟相位。
4. 使用了 TX FIFO与RX FIFO. 其实不用使用FIFO比较好。为什么?下面会讲。
5. 没有完全理解SPIA的发送与接收是【同时】进行的概念,这点实在很惭愧!
6. 发送是MSB对齐先发送,接收是LSB对齐接收,发送与接收是【同时】进行的!
SSD1351的设置,是:
时钟 空闲保持高电平。第二个时钟边沿数据采样捕获,第一时钟边沿锁存
SCLK的空闲无效状态是高电平 (其实也可以是低电平,但相位就要改改了,变为第二个时钟边沿锁存,,第一时钟边沿数据采样捕获)
数据的MSB 先发送。
好了,看看我是如何范这些毛病的,
void Write_Data(unsigned char Data)
void Write_Command(unsigned char Data)
看出参数都是8位的数据,比如要发送Data=0x55;那么传输到DSP 的SPI寄存器里这就出问题了!
是吧? 因为是MSB先发送,这样0x55到了16位的SPI寄存器例如SpiaRegs.SPITXBUF或SpiaRegs.SPIDAT 就变为0x0055了,由于SPIA 设置位8位模式,而且是MSB 先发送。那么就是只发送 0x0055的 00(高8位)了,低8位55就没有发送了。
因此 发送前要做如下变换:
Uint16 tmp;
tmp=Data;
tmp<<=8;
。。。。
SpiaRegs.SPIDAT =tmp
而接收时无需移位,SpiaRegs.SPIDAT、SpiaRegs.SPIRXBUF中低8位就是发送的tmp
SPIA的数据宽度设为8位。
SpiaRegs.SPICCR.bit.SPICHAR=7;
这个其实很简单,看看手册就知道了,不过我在网上看的HOTPOWER有关C54X的SPI设置。
就把SpiaRegs.SPICCR.bit.SPICHAR=8;来设8位的,这点我认为是不对了,虽然我不了解C54的SPI设置。
但估计也与C28X是一样的吧?哈哈!看来HOTPOWER也会范这样的低级毛病?不会吧?
时钟极性与时钟相位,其实我的OLED要求的是
【时钟 空闲保持高电平。第二个时钟边沿数据采样捕获,第一时钟边沿锁存,SCLK的空闲无效状态是高电平】
这个我想当然的搞错了:
SpiaRegs.SPICCR.bit.CLKPOLARITY=1; // 空闲时是高电平 这是对的
SpiaRegs.SPICTL.bit.CLK_PHASE=1; //这个是错的!**
后来我认真看看了TI C28X SPI的数据手册,这个大家一定要好好看看啊!
这个图就是数据在时钟下跳沿改变、锁存,在时钟上升沿被捕获采样。
如果不明白可以看看我的《精解 SPI 的
CPHA 时钟相位 与CPLK 时钟极性》
正确如下:
SpiaRegs.SPICCR.bit.CLKPOLARITY=1; // 空闲时是高电平 这是对的
SpiaRegs.SPICTL.bit.CLK_PHASE=0;//
SPIA的发送与接收是【同时】进行的概念
SPIA数据发送移位寄存器SpiaRegs.SPIDAT 是先发送MSB位,也就是BIT15位移位出SIMO,
同时从SOMI采样一位数据到LSB 也就是BIT0。如此类推
BIT14移位到BIT15,然后发送到SIMO
BIT0移位到BIT1,然后从SOMI移入一位数据到BIT0……..
这个过程发送到SIMO和接收SOMI是同时进行的。
因此要想知道发送到底完成没有,可以查看接收到完整的8位数据没有。不管数据线怎样,只要有MSB移出SIMO就有数据从SOMI移入BIT0,哪怕全是0或全是1.
有点不同的是,C28X SPI手册上说当数据接收完毕的SpiaRegs.SPIDAT,就会把SpiaRegs.SPIDAT的数据输入到SpiaRegs.RXBUF的RX FIFO中,并置位SpiaRegs.SPISTS.bit.INT_FLAG.
这点,我认为TI的数据手册在忽悠我们。 真实情况是非的要关闭FIFO增强才会出现这个情况。
就是SpiaRegs.SPIFFTX.bit.SPIFFENA=0;
这样我们要查询到的数据发送完毕没有,只有等到SpiaRegs.SPISTS.bit.INT_FLAG置位就可以了。
之前在网上有个 《TMS320F2812 SPI 总结》,
http://blog.chinaunix.net/u/31491/showart_654915.html
文中说"spi速率不能超过15M,超过后会出现严重误码"
这个应该不对的, 我的这个OLED与C28X SPIA的通信速度就到了20M.(其实还可以到30MHZ, 恐怕OLED受不了)
SpiaRegs.SPIBRR =0x0002; // 60MHZ/(2+1)=20MHZ SPI SPEED
而且是烧写到FLASH里运行,一直没问题。
哎,有点晚了,明天还要上班啦~,大家请原谅在下了,
其实有决心写这个全是因为当时出了问题比较着急,但在网上GOOGLE却没有什么收获!真让人气愤!
全大陆这么多大学的YY,GG ,不是很会出啥书啥书的吗?汗!
希望各位能从这文中有点收获~,不要再被C28X的SPI折腾和TI文档的折腾了~!哈哈。
希望TI别见怪啦~!
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。