程序实现:程序和异步通信方式类似:首先是初始化函数,然后是读取数据、写入数据函数。此程序采用和我之前的UART程序库类似的结构,写入数据后进入低功耗等待中断,判断标志位进行写入数据和读取数据。
这里函数只实现430的主机模式,如需从机模式可以仿照我的程序,进行简化实现。
由于,我即将使用的SPI设备(AD7708)不是字符型设备,这里不再实现写入字符串函数,也不再移植printf和scanf函数
初始化函数:SpiMasterInit,实现主机模式的初始化工作,函数内容如下:
char SpiMasterInit(long baud,char dataBits,char mode,char clkMode){ long int brclk; //波特率发生器时钟频率 UxCTL |= SWRST; //初始 //反馈选择位,为1,发送的数被自己接收,用于测试,正常使用时注释掉 //UxCTL |= LISTEN; UxCTL |= SYNC + MM; //SPI 主机模式 //时钟源设置 UxTCTL &=~ (SSEL0+SSEL1); //清除之前的时钟设置 if(baud<=16364) // { UxTCTL |= SSEL0; //ACLK,降低功耗 brclk = 32768; //波特率发生器时钟频率=ACLK(32768) } else { UxTCTL |= SSEL1; //SMCLK,保证速度 brclk = 1000000; //波特率发生器时钟频率=SMCLK(1MHz) } //------------------------设置波特率------------------------- if(baud < 300||baud > 115200) //波特率超出范围 { return 0; } //设置波特率寄存器 int fen = brclk / baud; //分频系数 if(fen<2)return (0); //分频系数必须大于2 else { UxBR0 = fen / 256; UxBR1 = fen % 256; } //------------------------设置数据位------------------------- switch(dataBits) { case 7:case'7': UxCTL &=~ CHAR; break; //7位数据 case 8:case'8': UxCTL |= CHAR; break; //8位数据 default : return(0); //参数错误 } //------------------------设置模式--------------------------- switch(mode) { case 3:case'3': UxTCTL |= STC; USPI3ON; break; //三线模式 case 4:case'4': UxTCTL &=~ STC; USPI4ON; break; //四线模式 default : return(0); //参数错误 } //------------------------设置UCLK模式----------------------- switch(clkMode) { case 0:case'0': UxTCTL &=~ CKPH; UxTCTL &=~ CKPL; break; //模式0 case 1:case'1': UxTCTL &=~ CKPH; UxTCTL |= CKPL; break; //模式1 case 2:case'2': UxTCTL |= CKPH; UxTCTL &=~ CKPL; break; //模式2 case 3:case'3': UxTCTL |= CKPH; UxTCTL |= CKPL; break; //模式3 default : return(0); //参数错误 } UxME |= USPIEx; //模块使能 UCTL0 &= ~SWRST; // Initialize USART state machine UxIE |= URXIEx + UTXIEx; // Enable USART0 RX interrupt return(1); //设置成功}程序注释已经比较详细,这里不再细说;如果要改为从机模式,把时钟设置和波特率设置去掉应该就可以了。
发送函数和接收函数:
void SpiWriteDat(char c){ while (TxFlag==0) SpiLpm(); // 等待上一字节发完,并休眠 TxFlag=0; // UxTXBUF=c;}char SpiReadDat(){ while (RxFlag==0) SpiLpm(); // 收到一字节? RxFlag=0; return(UxRXBUF);}发送和接收函数和异步通信里面的几乎一样,如果标志位为0,则等待改变为1,然后写入或读出;标志位在中断函数里被更改;中断函数如下:
#pragma vector=USARTxRX_VECTOR__interrupt void UartRx(){ RxFlag=1; __low_power_mode_off_on_exit();}#pragma vector=USARTxTX_VECTOR__interrupt void UartTx (){ TxFlag=1; __low_power_mode_off_on_exit();}中断里面仅仅置标志位后,就退出低功耗;退出后即写入或者读取数据。
读取或写入函数调用的SpiLpm函数:
void SpiLpm(){ if(UxTCTL&SSEL0) LPM3; //若以ACLK 作时钟,进入LPM3休眠(仅打开ACLK) else LPM0; //若以SMCLK作时钟,进入LPM0休眠(不关闭SMCLK)}根据不同情况进入低功耗,如果单片机其他地方不允许进入低功耗,可以更改这个函数。
程序部分就这么多了。需要的函数在头文件里面声明,方便使用。