This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

使用msp430FR5969 的Spi口时遇到的问题

Other Parts Discussed in Thread: MSP430FR5969

大侠们,在下第一次使用msp430FR56系例单片机,在spi使用方面遇到点问题。哪位方便帮忙看下,谢谢!

这里使用的是 eUSCI_B口,主模式,数据格式8位MSB传输,时钟信号上升沿采样传递数据。3根线传输数据不使用SET引脚。spi的时钟源来自于SMCK频率1Mhz。

P1.6

P1.7

P2.2

P3.0

这个是系统时钟初始化代码

  WDTCTL = WDTPW | WDTHOLD;                 // Stop WDT

PJSEL0 |= BIT4 + BIT5;
CSCTL0_H = 0xA5;
CSCTL1 |= DCOFSEL_6; // Set max. DCO setting
CSCTL2 = SELA_0 + SELS_3 + SELM_3; // set ACLK = XT1; MCLK = DCO
CSCTL3 = DIVA_0 + DIVS_1 + DIVM_1; // set all dividers
CSCTL4 |= LFXTDRIVE_0;
CSCTL4 &= ~LFXTOFF;
do
{
CSCTL5 &= ~LFXTOFFG;
// Clear XT1 fault flag
SFRIFG1 &= ~OFIFG;
}while (SFRIFG1&OFIFG); // Test oscillator fault flag

这是SPI初始化函数 

uint8_t System_Spi_B_Init(void)
{
UCB0CTLW0 |= UCSWRST; // **Put state machine in reset**
UCB0CTLW0 |= UCMST; // 3-pin, 8-bit SPI master
UCB0CTLW0 |= UCSYNC;
UCB0CTLW0 |= UCCKPL; // Clock polarity high, MSB
UCB0CTLW0 |= UCMSB;
UCB0CTLW0 |= UCSSEL__SMCLK;
UCB0BR0 = 0x02; // /2
UCB0BR1 = 0; //
UCA0MCTLW = 0; // No modulation
UCB0CTLW0 &= ~UCSWRST; // **Initialize USCI state machine**
return 0;
}

这是IO引脚功能复用初始化代码

  PM5CTL0 &= ~LOCKLPM5;  

//Set SPI_IF_Port
P3DIR |= BIT0;
P3REN |= BIT0;
P3OUT |= BIT0; //CS

P2SEL1 |= BIT2;                //SPI_B_CLK
P1SEL1 |= BIT6 + BIT7;   //SPI_B_MISO\SPI_B_MOSI

#define SPI_CS_H    {P3OUT|=BIT0;}
#define SPI_CS_L     {P3OUT&=~BIT0}

下面是SPI功能函数 

uint8_t SPI_RW(uint8_t byte)
{
uint8_t rec_val;
SPI_CS_L                   //    CS低为片选信号
UCB0TXBUF = byte;
while((UCTXIFG & UCB0IFG) == 0);
while((UCRXIFG & UCB0IFG) == 0);

rec_val = UCB0RXBUF;
UCB0IFG &= ~UCRXIFG;
SPI_CS_H
return rec_val;
}

问题:

我在调试时发现接入从设备后,一个字节没有发完,CS片选引脚电平却自动恢复成高   大概是时钟的第四个上升沿时CS状态发生的变化 。大侠们能不能帮忙看下,附件为完整的工程。

wenshidu.rar
  • 注:

    P1.6  MOSI   接设备 MOSI引脚

    P1.7  MISO  接设备 MISO  引脚

    P2.2 SCLK  接设备 SCLK  引脚

    P3.0 CS       接设备 CS引脚

  • 你好,

    看起来你用的是3线的SPI,因为你的CS信号是受你程序控制的。

    如你的代码所述,

    uint8_t SPI_RW(uint8_t byte)
    {
    uint8_t rec_val; 
    SPI_CS_L                   //    CS低为片选信号
    UCB0TXBUF = byte; 
    while((UCTXIFG & UCB0IFG) == 0);
    while((UCRXIFG & UCB0IFG) == 0);

    rec_val = UCB0RXBUF;
    UCB0IFG &= ~UCRXIFG; 
    SPI_CS_H
    return rec_val; 
    }

    所以你说CS信号恢复为高,是因为你程序写的有问题,和SPI无关,下面给你一个SPI例程供你参考。

    /* --COPYRIGHT--,BSD_EX
    * Copyright (c) 2012, Texas Instruments Incorporated
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    *
    * * Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    *
    * * Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the distribution.
    *
    * * Neither the name of Texas Instruments Incorporated nor the names of
    * its contributors may be used to endorse or promote products derived
    * from this software without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    *******************************************************************************
    *
    * MSP430 CODE EXAMPLE DISCLAIMER
    *
    * MSP430 code examples are self-contained low-level programs that typically
    * demonstrate a single peripheral function or device feature in a highly
    * concise manner. For this the code may rely on the device's power-on default
    * register values and settings such as the clock configuration and care must
    * be taken when combining code from several examples to avoid potential side
    * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware
    * for an API functional library-approach to peripheral configuration.
    *
    * --/COPYRIGHT--*/
    //******************************************************************************
    // MSP430F59xx Demo - eUSCI_A0, SPI 3-Wire Master Incremented Data
    //
    // Description: SPI master talks to SPI slave using 3-wire mode. Incrementing
    // data is sent by the master starting at 0x01. Received data is expected to
    // be same as the previous transmission TXData = RXData-1.
    // USCI RX ISR is used to handle communication with the CPU, normally in LPM0.
    // ACLK = 32.768kHz, MCLK = SMCLK = DCO ~1MHz. BRCLK = ACLK/2
    //
    //
    // MSP430FR5969
    // -----------------
    // /|\ | XIN|-
    // | | | 32KHz Crystal
    // ---|RST XOUT|-
    // | |
    // | P2.0|-> Data Out (UCA0SIMO)
    // | |
    // | P2.1|<- Data In (UCA0SOMI)
    // | |
    // | P1.5|-> Serial Clock Out (UCA0CLK)
    //
    // P. Thanigai
    // Texas Instruments Inc.
    // Feb 2012
    // Built with CCS V5.5
    //******************************************************************************
    #include <msp430.h>

    volatile unsigned char RXData = 0;
    volatile unsigned char TXData;

    int main(void)
    {
    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

    // Configure GPIO
    P1SEL1 |= BIT5; // USCI_A0 operation
    P2SEL1 |= BIT0 | BIT1; // USCI_A0 operation
    PJSEL0 |= BIT4 | BIT5; // For XT1

    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;

    // XT1 Setup
    CSCTL0_H = CSKEY >> 8; // Unlock CS registers
    CSCTL1 = DCOFSEL_0; // Set DCO to 1MHz
    CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK;
    CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; // set all dividers
    CSCTL4 &= ~LFXTOFF;
    do
    {
    CSCTL5 &= ~LFXTOFFG; // Clear XT1 fault flag
    SFRIFG1 &= ~OFIFG;
    }while (SFRIFG1&OFIFG); // Test oscillator fault flag
    CSCTL0_H = 0; // Lock CS registers

    // Configure USCI_A0 for SPI operation
    UCA0CTLW0 = UCSWRST; // **Put state machine in reset**
    UCA0CTLW0 |= UCMST | UCSYNC | UCCKPL | UCMSB; // 3-pin, 8-bit SPI master
    // Clock polarity high, MSB
    UCA0CTLW0 |= UCSSEL__ACLK; // ACLK
    UCA0BR0 = 0x02; // /2
    UCA0BR1 = 0; //
    UCA0MCTLW = 0; // No modulation
    UCA0CTLW0 &= ~UCSWRST; // **Initialize USCI state machine**
    UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
    TXData = 0x1; // Holds TX data

    while(1)
    {
    UCA0IE |= UCTXIE;
    __bis_SR_register(LPM0_bits | GIE); // CPU off, enable interrupts
    __delay_cycles(2000); // Delay before next transmission
    TXData++; // Increment transmit data
    }
    }

    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=USCI_A0_VECTOR
    __interrupt void USCI_A0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
    switch(__even_in_range(UCA0IV, USCI_SPI_UCTXIFG))
    {
    case USCI_NONE: break;
    case USCI_SPI_UCRXIFG:
    RXData = UCA0RXBUF;
    UCA0IFG &= ~UCRXIFG;
    __bic_SR_register_on_exit(LPM0_bits); // Wake up to setup next TX
    break;
    case USCI_SPI_UCTXIFG:
    UCA0TXBUF = TXData; // Transmit characters
    UCA0IE &= ~UCTXIE;
    break;
    default: break;
    }
    }

  • B0的SPI的baud分频也是使用UCA0MCTLW = 0?

  • 上一楼的例子中用的是A0

  • 初学者,请教一下,这个程序实现是单片机使用SPI 主机模式,发数据给你自己吗?自发自收?

  • 是SPI 主机模式,不是自发自收

  • #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=USCI_A0_VECTOR
    __interrupt void USCI_A0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
    switch(__even_in_range(UCA0IV, USCI_SPI_UCTXIFG))
    {
    case USCI_NONE: break;
    case USCI_SPI_UCRXIFG:
    RXData = UCA0RXBUF;
    UCA0IFG &= ~UCRXIFG;
    __bic_SR_register_on_exit(LPM0_bits); // Wake up to setup next TX
    break;
    case USCI_SPI_UCTXIFG:
    UCA0TXBUF = TXData; // Transmit characters
    UCA0IE &= ~UCTXIE;
    break;
    default: break;
    }
    }
    请问,这个中断函数,没有搞明白。
    这个中断服务函数为接收发的中断函数,他在什么时候会进入中断。
    特别是__even_in_range(UCA0IV, USCI_SPI_UCTXIFG))没有看明白,请指教。
  • __even_in_range()是iar提供的一个函数。

    在IAR提供的库函数里有以下内容:

    /*
    * Support for efficient switch:es. E.g. switch(__even_in_range(x, 10))
    *
    * Note that the value must be even and in the range from 0 to
    * __bound, inclusive. No code will be generated that checks this.
    *
    * This is typically used inside interrupt dispatch functions, to
    * switch on special processor registers like TAIV.
    */
    原型为:
    unsigned short __even_in_range(unsigned short value, unsignedshort upper_limit);
    功能:

    只能与switch 语句结合使用,判断value 是否为偶数且小于等于upper_limit。
    在msp430里经常被用在多源中断的查询中,如 switch( __even_in_range(TAIV,10)
    只有在TAIV的值是在0--10内的偶数时才会执行switch函数内的语句
    其作用是提高switch语句的效率