【学习探索】Hello:LaunchPad(从)--SPI--EK LM3S811(主)

2019-07-31 16:47发布

本帖最后由 yirongfu 于 2012-7-5 09:41 编辑

    此前一直使用模拟的SPI接口或者主机模式的SPI接口,未尝试过从机SPI编程,近期学习了视频教程,想试试来个跨界握手:通过LaunchPad上的MSP430G2553的硬件SPIEK-LM3S811上的SSISPI模式)进行互联,简化起见,MSP430G2553作为从机,LM3S811作为主机。利用LM3S811的虚拟串口来间接检验双向通讯效果,通讯的思路是LM3S811发出若干字节数据,MSP430G2553接收到后原文回传,LM3S811接收到回传直接通过UART显示到PC端的串口调试助手上。当然也可以逆过来设计,我这么选择只是为了实验的方便,因为需要尝试的重点是SPI通讯,其他的如虚拟串口可以利用LM3S的库来快速实现。关键的难点还是接口时序的选择,比如时钟的极性、相位等。
*****************************************

硬件连接(从评估板的引出端子处飞线互连):
PC1+MSP430G2553                                 PC2+ LM3S811
GNDPin20------------------------------GND(外侧引出焊盘列,下同)
UCA0SOMIP1.1------------------------SSIRx
UCA0SIMOP1.2------------------------SSITx
UCA0CLK P1.4-------------------------SSICLK
UCA0STE P1.5-------------------------SSIFss(可省)
*****************************************

注:目前的MSP430G2553器件手册SLAS735F3页第一个器件引脚图上,第4脚描述有误,多了个字母P,变成PUCA0SIMO了。
dserror.JPG



   
    接下来的重点就是编程了,首先需要查阅官方的例程,当然没有现成的上述连接方式的例程,不过
MSP430G2553倒是有两个分别作为从机和主机的例程,主从双方均为MSP430单片机,LM3S811也有SPI主机模式的例程,但没找着对应的从机例程。参考例程作如下设计:


1. MSP430G2553采用三线SPI从机模式,上电复位进行必要的初始化后进入低功耗LPM4状态,接收数据和发送数据均在中断服务程序内执行。这也是近期的视频教程第八讲“串行通信模块”里,丁经理反复强调的430适合低功耗设计的要求,为低功耗设计而设计,它可从任意低功耗模式(LPM)实现自动时钟起动,具体来说就是即使在CPU和所有时钟禁能的LPM4模式下都可以正常通信,不过请注意,这针对的是SPI的时钟取自SMCLK且作为从机的操作,在需要的时候SMCLK被自动激活,比如接收和发送操作就可以激活,并保持到操作执行完毕,然后回到激活前的低功耗状态(详见用户手册说明)。而如果作为主机,它需要向外输送时钟的,所以就跟低功耗模式相矛盾了。为了便于调试观察,设置了一个数组用于存放从SPI收到的数据,接收到一个字节立即回传该字节,芯片大部分时间处于LPM4,另外,联调时先运行该从机。调试环境CCSv4.2.4
coachppt.JPG

2. LM3S811采用FreescaleSPI主机模式,SPH=1SPO=0,速率取500kHz8-bit数据宽度。注意,LM3S811数据手册里提到,当工作模式为主机模式时,系统时钟至少是SSIClk的两倍;当工作模式为从机模式时,系统时钟至少是SSIClk12。程序采用查询方式发送和接收数据,发送5个字符Hello,全部发送完毕再进行接收查询,接收的数据直接送UART口,UART口采用例程中的配置115200 bps8-N-1。调试环境IAREmbedded Workbench for ARM 5.30 Kickstart


3. 两个MCU的用户手册所述及的SPI接口模式不太一样,MSP430G2553并不像LM3S811那样区分出三种定义的SPI接口,从具体的配置来看,MSP430G2553LM3S811Freescale接口模式更为接近,就是不知道LM3S811支持的TI的模式是不是430上的SPI模式?最终基本可行的接口时序形式如下:
MSP430G2553CKPL=0CKPH=0
g2553spi.JPG

LM3S811FreescaleSPO= 0SPH=1
freescalesph1.JPG
其实我一开始分析时,觉得SPO=0SPH=0更配对,可惜不对。
freescalesph0.JPG

实验内容及结果总结:


1. MSP430G2553作为从机,SPI的总线时钟CLK取决于主机,当然,也不能让MCU的系统时钟低于SPI时钟线频率。实验过上电默认的约1MHz DCO,修改为8MHz,修改为4.37.3MHzRSELx = 12, DCOx = 3, MODx = 0),均可。稳妥起见,个人觉得系统时钟和总线频率的选择参考上述LM3S811数据手册的建议为宜。


2. 试了MSP430G2553配置为3线制,LM3S811配置为TI SPI模式,MSP430G2553接收到的数据错误。


3. LM3S811Freescale SPI是4线制,试验了如下情况:
· 分别试了用与不用SSISTE引脚(软件配置LM3S811I/O口部分的PA3屏蔽),MSP430G2553也分别配置了3线制和4线制,效果一样,这个STE脚应该就是多主机的时候才有用(此时注意如果使用4线JTAG进行调试,MSP430G2xx3UCA0STETMS引脚是复用的,开发环境可以使用Release JTAG on Go或者Free Run来避免冲突)。
· 试了LM3S811SPO=0SPH=0模式,MSP430G2553接收的数据正确,但LM3S811收到的其回传数据与原发出数据不一样,不过基本都是固定的几个值。
· 试了LM3S811SPO=0SPH=1模式,MSP430G2553接收数据正确,但回送给LM3S811的数据不完全一致,这个不一致是说收到的字符是对的,但先后顺序不吻合,比如实验中LM3S811发送的是“Hello”,MSP430G2553接收到的也是“Hello”,并且收一个字符回传一个,LM3S811也是读出一个就往串口送一个,结果PC端的串口调试器上得到的是“oHell”,就是说顺序错了,还试过只送三个字节“mhz”,同样存在这种现象,变成“hzm”,DCO改为8MHz后,又变成“zmh”。目前只调试到这种程度,虽然不完全吻合,排序有错,但至少收到正确的数据了,下面是串口终端的截图。
helloechoe.JPG

· 至于为何数据错位,LM3S811FIFO接收机制既然先进先出,照理不应该错,而且从机MSP430G2553也是按正确的先后顺序回传的,我想只可能在主机端接收和读取时才会产生错误,感觉也不应该是查询方式存取FIFO的问题,否则先不说错位,就连数值的正确性都无法保证。至于问题到底出在哪里,还没找出来,有待继续研究调试,如果有朋友知道,望指点!
· 现在总算深刻体会到了SPI总线的弱点:没有指定的流控制,没有完善的应答机制确认是否接收到数据。曾经将MSP430G2553的回传屏蔽,结果LM3S811的接收还是照常执行,收到的数据当然都是空白的,也就是说,SPI并没有像I2C那样有停止位、起始位、确认位之类的,它仅是依靠时钟线来作为存取数据的基准,如果主从机的时序没有严格对应上,就很可能出错。也曾怀疑我上述失败实验中有些就是数据回传与LM3S811开始程序读取FIFO之间的时间间隔问题,可惜没有示波器,暂时无法去验证分析。对于这种双MCU的由程序控制的SPI主从通讯,特别是两种不同架构的MCU之间的通讯,关键之关键,应该还是时序的同步。


    这回调试费了好几天的业余时间,因为没有好的实验条件,比调试I2C和其它仅作Slave用途的SPI器件要费劲的多,而且熟悉CCS调试环境也花了点时间,好在多少有些成果,亲自验证了MSP430LM3S之间的SPI互联,虽然还有数据错位的问题,但至少数值对了,如果大家有碰到类似的实际应用,可以再进一步做调试。


后面附上两MCU的主代码供大家参考。
另外,因为本文既涉及MSP430又涉及Stellaris,所以放到《讨论》这个版块。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
14条回答
yirongfu
1楼-- · 2019-07-31 21:04
本帖最后由 yirongfu 于 2012-7-5 09:59 编辑

发帖系统真的有些问题,烦人,上帖最后一张图重复,部分字体颜 {MOD}也编辑不成功,期待新版!

下面是MSP430G2553的源代码,环境CCSv4.2.4
参考例程:slac485a ——MSP430G2xx3Code Examples.zip(例程有些描述也不一定都正确)


  1. #include "msp430g2553.h"



  2. unsigned char temp[5];

  3. static unsigned char num;



  4. void main(void)

  5. {

  6.   WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer

  7.   

  8.   /*if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)                                    


  9. {  

  10.    
  11. while(1);                              
  12. // If calibration constants erased
  13. // do not load, trap CPU!!

  14.   }


  15. //8Mhz


  16.   BCSCTL1 = CALBC1_8MHZ;//0x0C;                    // Set range


  17.   DCOCTL = CALDCO_8MHZ;//0x60;                     // Set DCO step +
  18. modulation */

  19.   

  20.   P1SEL = BIT1 + BIT2 + BIT4;

  21.   P1SEL2 = BIT1 + BIT2 + BIT4;

  22.   UCA0CTL1 = UCSWRST;                       // **Put state machine in reset**




  23.   UCA0CTL0 |= UCMSB + UCSYNC + UCMODE_2;               // 3-pin, 8-bit SPI slave

  24. //官方例程此处注释有误,变成了master
  25.   UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**

  26.   IE2 |= UCA0RXIE;                          // Enable USCI0 RX interrupt

  27.   temp[0] = '-';

  28.   temp[1] = '-';

  29.   temp[2] = '-';

  30.   temp[3] = '-';

  31.   temp[4] = '-';

  32.   num = 0;



  33.   __bis_SR_register(LPM4_bits + GIE);       // Enter LPM4, enable interrupts

  34. }



  35. // Echo character

  36. #pragma vector=USCIAB0RX_VECTOR

  37. __interrupt void USCI0RX_ISR (void)

  38. {

  39.   temp[num] = UCA0RXBUF;

  40.   while (!(IFG2 & UCA0TXIFG));

  41.   UCA0TXBUF = temp[num];

  42.   num++;
  43.   

  44.   if(num == 5)
  45.      num = 0;

  46. }
复制代码
yirongfu
2楼-- · 2019-07-31 23:48
 精彩回答 2  元偷偷看……
nwx8899
3楼-- · 2019-08-01 03:53
mark 顶
yirongfu
4楼-- · 2019-08-01 05:24
谢谢捧场:)

没人解答我的问题吗?:L
mdq123
5楼-- · 2019-08-01 08:44
xiexielouzhu
mdq123
6楼-- · 2019-08-01 13:37
xiexielouzhu

一周热门 更多>