TI中文支持网
TI专业的中文技术问题搜集分享网站

MSP430F448 SPI

#include <msp430f448.h>
#include "Spi.h"

/***********************************宏定义*********************************/
#define UxCTL   U0CTL
#define UxRCTL  U0RCTL
#define UxTCTL  U0TCTL

#define UxBR0   U0BR0
#define UxBR1   U0BR1
#define UxMCTL  U0MCTL

#define UxRXBUF U0RXBUF
#define UxTXBUF U0TXBUF

#define UxME    U0ME
#define UxIE    U0IE
#define UxIFG   U0IFG

#define USPIEx  USPIE0

#define URXIEx  URXIE0
#define UTXIEx  UTXIE0

#define USARTxTX_VECTOR USART0TX_VECTOR
#define USARTxRX_VECTOR USART0RX_VECTOR

#define USPI3ON P3SEL |= 0X0E           //SPI 0的第二功能打开(三线模式)
#define USPI4ON P3SEL |= 0X0F           //SPI 0的第二功能打开(四线模式)

#define SSN0   P3OUT &= 0xFE    //P3.0=0
#define SSN1   P3OUT |= 0x01    //P3.0=1

/**************************************************************************/

char TxFlag_Spi=1;
char RxFlag_Spi=0;

/****************************************************************************
* 名    称:SpiMasterInit
* 功    能:初始化SPI。设置波特率等,主机模式
* 入口参数:
*           baud:       波特率      (300~500k)
                        只能是串口使用时钟的整数分频,spi模式UxMCTL寄存器无效
                        若为整数分频,将分频系数设为 整数部分,将不支持小数分
                        频
            datsBits:   数据位位数  (7或8)
            mode:       停止位位数  (3或4)
                        3:三线模式                         4:四线模式
            clkMode     时钟模式    (0-3)   控制时钟的极性和相位
                        0: 上升沿发送,下降沿接收 正常UCLK
                        1: 下降沿发送,上升沿接收 正常UCLK
                        2: 下降沿发送,上升沿接收 延时半个周期UCLK
                        3: 上升沿发送,下降沿接收 延时半个周期UCLK
****************************************************************************/
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>=300 && baud<=115200)                 //
    {
      UxTCTL |= SSEL0;              //ACLK,降低功耗
      brclk = 32768;                //波特率发生器时钟频率=ACLK(32768)
    }
       //————————设置波特率————————-      else if(baud < 300||baud > 115200)   //波特率超出范围
    {
        return 0;
    }
    //设置波特率寄存器
    int fen = brclk / baud;         //分频系数
    //if(fen<2)return (0);            //分频系数必须大于2
    if(fen>=2)
    {
        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':     //三线模式 P3.1-P3.3分别接SPI的SI、SO和SCK
          UxTCTL |= STC;           P3SEL |= BIT1+BIT2+BIT3;
          P3SEL &= ~BIT0;    //P3.0=SSN
          P3DIR |= BIT0+BIT2+BIT3;             break;         case 4:case'4':     //四线模式 P3.0-P3.3分别接SPI的SSN、SI、SO和SCK
          UxTCTL &=~ STC;          P3SEL = 0x0f;
          P3DIR = 0x0b;             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 TX RX interrupt           return(1);                  //设置成功
}

/****************************************************************************
* 名    称:UartLpm
* 功    能:串口收/发等待过程中,将时钟系统的部分时钟该关掉,休眠省电
* 入口参数:无
* 出口参数:无
* 说    明: 若与其他外设的时钟冲突,可注释掉该函数,但会增加功耗。
****************************************************************************/
void SpiLpm()
{
    if(UxTCTL&SSEL0) LPM3;  //若以ACLK 作时钟,进入LPM3休眠(仅打开ACLK)
    else             LPM0;  //若以SMCLK作时钟,进入LPM0休眠(不关闭SMCLK)
}

/****************************************************************************
* 名    称:UartWriteChar
* 功    能:向串口写一个字节数据
* 入口参数:c:  待发送的一字节数据
* 出口参数:无
* 说    明: 在等待发送完毕的过程中,CPU会休眠
****************************************************************************/
void SpiWriteDat(char c)
{    SSN0;
       while (TxFlag_Spi==0) SpiLpm();  // 等待上一字节发完,并休眠
    //TxFlag_Spi=0;                     //
    UxTXBUF=c;
    //while((UxIFG&UTXIFG0)==0);//等待发送缓冲器为空
    SSN1;
}

/****************************************************************************
* 名    称:UartReadChar
* 功    能:从串口读取1字节数据
* 入口参数:无 * 出口参数:收到的一字节数据
* 说    明: 如果串口没有数据,会一直等待。等待过程中,CPU会休眠
****************************************************************************/
char SpiReadDat()
{    SSN0;
    while (RxFlag_Spi==0) {}; // 收到一字节?
    //RxFlag_Spi=0;
    //while((UxIFG&URXIFG0)==0);//等待接收缓冲器为满
    return(UxRXBUF);
    SSN1;
}

/****************************************************************************
* 名    称:SpiWriteData
* 功    能:有返回的写入
* 入口参数:c:  待发送的一字节数据
* 出口参数:char:写入的同时收到的字节
* 说    明: SPI是全双工通信,每次发送,接收时钟也在接收,发送完成后的半个时钟
*           周期后,读到一个字符,这个字符也许不是从设备返回的,仅仅是信号线
*           的默认电平,根据实际情况判断;当只需读数据时,也要用此函数,否则
*           没有时钟提供给从设备,不能读到数据;强烈建议使用时,发送接收只调
*           此函数,否则读取的可能是上一次采样的字符 \0(默认电平)
****************************************************************************/
char SpiWriteData(char c)
{
    char i;
    SpiWriteDat(c);
    for (i = 0xFFFF; i > 0; i–);           // Delay
    return SpiReadDat();
}

/****************************************************************************
* 名    称:UartRx
* 功    能:串口接收中断,每接收到1字节会发生一次中断
****************************************************************************/
#pragma vector=USARTxRX_VECTOR
__interrupt void SpiRx()
{
    char a;
    //RxFlag=1;
    RxFlag_Spi=1;
    a=UxRXBUF;
    //__low_power_mode_off_on_exit();
}

/****************************************************************************
* 名    称:UartTx
* 功    能:串口发送中断,每发完1字节会发生一次中断
****************************************************************************/
#pragma vector=USARTxTX_VECTOR
__interrupt void SpiTx()
{
    //TxFlag=1;
    TxFlag_Spi=1;
    //__low_power_mode_off_on_exit();
}

用以上程序对GP21进行配置时出现以下问题:

(1)当UxCTL |= LISTEN时,发送和接收数据相同,但是不能进入发送和接收中断

(2)当注释掉UxCTL |= LISTEN时,用while((UxIFG&URXIFG0)==0)判断是否有接收中断时,可通过while语句,但是接收数据为0

(3)当注释掉UxCTL |= LISTEN,并开启中断时,不能进入中断

请工程师回答我的问题,谢谢

灰小子:

“可通过while语句”是什么意思?这一句能执行过去?

Zhao Li2:

回复 灰小子:

是的,while可执行过去,但是收到的数为0

赞(0)
未经允许不得转载:TI中文支持网 » MSP430F448 SPI
分享到: 更多 (0)