首先注意几个问题:
1,SPI通信时,双方的时序(相位,极性)必须一致(看后面SPI四种时序设置)
2,主机设置时钟,从机不需要设置时钟.
3,时钟引脚上,在有数据传输时,才有时钟,没有数据传输时,则没有时钟
经测试下面程序在msp430F149上实验成功,用于两个板子通信
主机:
(SPI.C)
#include<msp430x14x.h>
#define USPI3ON P3SEL |= 0X0E
#define USPI4ON P3SEL |= 0X0F
char TxFlag=1;
char RxFlag=0;
void ClkInit()
{
char i;
BCSCTL1&=~XT2OFF;
IFG1&=~OFIFG;
while((IFG1&OFIFG)!=0)
{
for(i=0;i<0xff;i++)
IFG1&=~OFIFG;
}
BCSCTL2 |= SELM_2+SELS+DIVS_3;
}
char SpiMasterInit(long baud,char dataBits,char mode,char clkMode)
{
long int brclk;
U0CTL |= SWRST;
U0CTL |= SYNC+MM;
U0TCTL |=SSEL0;
U0BR0 =0X02;
U0BR1 =0;
//这里可以设置波特率,为了测试时简单就省略啦
/*if(baud<=16364)
{
U0TCTL |= SSEL0;
brclk = 32768;
}
else
{
U0TCTL |=SSEL1;
brclk=1000000;
}
if(baud<300||baud>115200)
{
return 0;
}
int fen = brclk / baud;
if(fen<2)return (0);
else
{
U0BR0 = fen / 256;
U0BR1 = fen % 256;
}*/
switch(dataBits)
{
case 7:case'7':U0CTL &=~CHAR;break;
case 8:case'8':U0CTL |=CHAR;break;
default:return 0;
}
switch(mode)
{
case 3:case'3':U0TCTL |=STC; USPI3ON;break;
case 4:case'4':U0TCTL &=~STC;USPI4ON;break;
default:return 0;
}
switch(clkMode)
{
case 0:case'0':U0TCTL &=~CKPH;U0TCTL &=~CKPL;break;
case 1:case'1':U0TCTL &=~CKPH;U0TCTL |= CKPL;break;
case 2:case'2':U0TCTL |= CKPH;U0TCTL &=~CKPL;break;
case 3:case'3':U0TCTL |= CKPH;U0TCTL |= CKPL;break;
default:return 0;
}
ME1 |= USPIE0;
UCTL0 &= ~SWRST;
IE1 |= URXIE0+UTXIE0;
return (1);
}
void SpiLpm()
{
if(U0TCTL&SSEL0)LPM3;
else LPM0;
}
void SpiWriteDat(char c)
{
while(TxFlag==0);
TxFlag=0;
U0TXBUF=c;
}
char SpiReadDat()
{
while(RxFlag==0);
RxFlag=0;
return (U0RXBUF);
}
char SpiWriteData(char c)
{
SpiWriteDat(c);
return SpiReadDat();
}
#pragma vector=USART0RX_VECTOR
__interrupt void UartRx()
{
RxFlag=1;
}
#pragma vector=USART0TX_VECTOR
__interrupt void UartTx()
{
TxFlag=1;
}
(main.c)
#include "msp430x14x.h"
#include "SPi.h"
void main()
{
char f,d=0x02;
char e=0x02;
WDTCTL=WDTPW+WDTHOLD;
ClkInit();
SpiMasterInit(16362,8,3,0);
_EINT();
while(1)
{
SpiWriteDat(d);
f=SpiReadDat();
if(f==e)
{
d++;
e++;
}
}
}
从机程序:基本一样,就是没有时钟设置,以及设置成从机模式.
SPI四种时序如图所示: