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.

[参考译文] LP-MSP430FR2476:SPI 发送和接收中断

Guru**** 2387060 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1041715/lp-msp430fr2476-spi-transmit-and-receive-interrupts

器件型号:LP-MSP430FR2476

我有 MSP430 SPI 设置、可与从外设通信。 唤醒序列总共有9个事务。 事务5之后需要一个返回字节。 没有其他事务返回一个字节。 我遇到 SPI 接收问题。 似乎每个字节采用0xff 的值、这会触发接收中断。 我无法成功完成序列、因为我没有返回所需的字节。 从器件可通过评估 GUI 正常工作。 我很感激这里可以更改的内容的指示。

我们将尝试一种轮询方法。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include <driverlib.h>
#include <msp430.h> 
#include "clock~.h"                 // Clock configurations


static uint8_t TXData = 0;           //transaction count
static uint8_t RXData = 0;           //SPI receive byte
static uint8_t waitForReceive = 0;


typedef struct {
    uint8_t     Len;
    uint8_t    Data[5];
} spi_MaximTrans_t;

static spi_MaximTrans_t DCInit_transactions[15];


uint8_t SPI_TX_index = 0;            //byte count in transaction

/**
 *  Initialize system clocks
 */
static void init_clock(void) {
    // Configure one FRAM waitstate as required by the device datasheet for MCLK
    // operation beyond 8MHz _before_ configuring the clock system.
    FRAMCtl_configureWaitStateControl(FRAMCTL_ACCESS_TIME_CYCLES_1);

    //Set DCO FLL reference = REFO
    CS_initClockSignal(CS_FLLREF, CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);
    //Set ACLK = REFO
    CS_initClockSignal(CS_ACLK,   CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);

    CS_initFLLParam param = {0};
    //Set Ratio/Desired MCLK Frequency, initialize DCO, save trim values
    CS_initFLLCalculateTrim(CS_MCLK_DESIRED_FREQUENCY_IN_KHZ, CS_MCLK_FLLREF_RATIO, &param);

    //Set MCLK = REFO
    CS_initClockSignal(CS_MCLK,   CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);
    //Set SMCLK = DCO
    CS_initClockSignal(CS_SMCLK,  CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1);

    //Clear all OSC fault flag
    CS_clearAllOscFlagsWithTimeout(1000);
}

/**
 *  Initialize all of the IO pins per their configuration
 */
static void init_gpio(void) {
    // Set all GPIO pins to output low to prevent floating input and reduce power consumption
    GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN_ALL8);
    GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN_ALL8);
    GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN_ALL8);
    GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN_ALL8);
    GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN_ALL8);
    GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);





    GPIO_setAsOutputPin(   GPIO_PORT_P1, GPIO_PIN_ALL8);
    GPIO_setAsOutputPin(   GPIO_PORT_P2, GPIO_PIN_ALL8);
    GPIO_setAsOutputPin(   GPIO_PORT_P3, GPIO_PIN_ALL8);
    GPIO_setAsOutputPin(   GPIO_PORT_P4, GPIO_PIN_ALL8);
    GPIO_setAsOutputPin(   GPIO_PORT_P5, GPIO_PIN_ALL8);
    GPIO_setAsOutputPin(   GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);



}

/*
 * Initialize the SPI peripheral on EUSCI A1
 */
void init_spi_peripheral()
{
    //Initialize Master
        EUSCI_A_SPI_initMasterParam param = {0};
        param.selectClockSource = EUSCI_A_SPI_CLOCKSOURCE_SMCLK;
        param.clockSourceFrequency = CS_getSMCLK();
        param.desiredSpiClock = 1000000;
        param.msbFirst = UCMSB;
        param.clockPhase = 0;
        param.clockPolarity = EUSCI_A_SPI_CLOCKPOLARITY_INACTIVITY_LOW;
        param.spiMode = EUSCI_A_SPI_3PIN;
        EUSCI_A_SPI_initMaster(EUSCI_A1_BASE, &param);

        EUSCI_A_SPI_enable(EUSCI_A1_BASE);

        // Enable the TX and RX interrupts for the SPI bus.
        EUSCI_A_SPI_enableInterrupt(EUSCI_A1_BASE, EUSCI_A_SPI_TRANSMIT_INTERRUPT);
        EUSCI_A_SPI_enableInterrupt(EUSCI_A1_BASE, EUSCI_A_SPI_RECEIVE_INTERRUPT);
}


void SetUpTransactions(void){
    //Enable keep alive mode
    DCInit_transactions[0].Len = 2;
    DCInit_transactions[0].Data[0] = 0x10;
    DCInit_transactions[0].Data[1] = 0x5;       //No Receive

    //Enable Rx Interrupt flags
    DCInit_transactions[1].Len = 2;
    DCInit_transactions[1].Data[0] = 0x4;
    DCInit_transactions[1].Data[1] = 0x88;      //No Receive

    //Clear receive buffer
    DCInit_transactions[2].Len = 1;
    DCInit_transactions[2].Data[0] = 0xe0;      //No Receive

    //Wakeup UART slave devices
    DCInit_transactions[3].Len = 2;
    DCInit_transactions[3].Data[0] = 0xe0;
    DCInit_transactions[3].Data[1] = 0x30;      //No Receive

    //Wait for all UART slave devices to wake up
    DCInit_transactions[4].Len = 1;
    DCInit_transactions[4].Data[0] = 0x01;      //Receive of 0x21 expected

    //End of UART slave device wake-up period
    DCInit_transactions[5].Len = 2;
    DCInit_transactions[5].Data[0] = 0x0e;
    DCInit_transactions[5].Data[1] = 0x10;      //No Receive

    //Wait for null message to be received
    DCInit_transactions[6].Len = 1;
    DCInit_transactions[6].Data[0] = 0x01;      //No Receive

    //Clear transmit buffer
    DCInit_transactions[7].Len = 1;
    DCInit_transactions[7].Data[0] = 0x20;      //No Receive

    //Clear receive buffer
    DCInit_transactions[8].Len = 1;
    DCInit_transactions[8].Data[0] = 0xe0;      //No Receive

}


/**
 * main.c
 */
int main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
	

    init_clock();
    init_gpio();                                    // Set up IO pins

    GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);

    // Configure SPI Pins for UCA1CLK, UCA1TXD/UCA1SIMO and UCA1RXD/UCA1SOMI
    /*
    * Select Port 2
    * Set Pin 4, Pin 5 and Pin 6 to input Secondary Module Function
    */
    GPIO_setAsPeripheralModuleFunctionInputPin(
        GPIO_PORT_P2,
        GPIO_PIN4 + GPIO_PIN5 + GPIO_PIN6,
        GPIO_PRIMARY_MODULE_FUNCTION
    );

    // Set P1.0 to output direction

    GPIO_setAsOutputPin (GPIO_PORT_P1, GPIO_PIN0);
    GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P4, GPIO_PIN2);
    GPIO_enableInterrupt (GPIO_PORT_P4, GPIO_PIN2);
    GPIO_selectInterruptEdge (GPIO_PORT_P4, GPIO_PIN2, GPIO_HIGH_TO_LOW_TRANSITION);
    GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2);

    PMM_unlockLPM5();

    SetUpTransactions();
    TXData = 0x0;                             // Holds transaction number


    // Setup peripheral(s) now that gpio and clocks are setup
    init_spi_peripheral();                      // Init Maxim spi peripheral
    //Wait for slave to initialize
        __delay_cycles(100);

    GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN1);        //Maxim chip select low
    UCA1IFG |= UCTXIFG;


    __bis_SR_register(LPM0_bits + GIE);      // CPU off, enable interrupts
    __no_operation();                       // Remain in LPM0


	return 0;
}

//******************************************************************************
//
//This is the PORT2_VECTOR interrupt vector service routine
//
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=PORT4_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(PORT2_VECTOR)))
#endif
void P4_ISR (void)
{
 //   GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);
    GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2);
    // Toggle P1.0 output
    GPIO_toggleOutputOnPin (GPIO_PORT_P1, GPIO_PIN0);

    GPIO_disableInterrupt (GPIO_PORT_P4, GPIO_PIN2);
}


/****************************************************************************
 * EUSCI_A1_isr()
 *
 * This interrupt is used for SPI interrupts (UCA1).
 ****************************************************************************/
#pragma vector = EUSCI_A1_VECTOR
__interrupt void EUSCI_A1_isr(void)
{
    // SPI TX interrupt?
    if (UCA1IFG & UCTXIFG)
    {
        while (UCA1STATW & UCBUSY);
        EUSCI_A_SPI_transmitData(EUSCI_A1_BASE, DCInit_transactions[TXData].Data[SPI_TX_index]);
        SPI_TX_index++;

        if (SPI_TX_index == DCInit_transactions[TXData].Len){
                   SPI_TX_index = 0;
                   if (!waitForReceive)
                       TXData = TXData+1;
                   if (TXData == 5){
                       TXData = 4;
                       waitForReceive = 1;
                   }

                   if (TXData == 9) {
                      while (UCA1STATW & UCBUSY);     //wait for the last byte to transmit
                         EUSCI_A_SPI_disableInterrupt(EUSCI_A1_BASE, EUSCI_A_SPI_TRANSMIT_INTERRUPT);
                         EUSCI_A_SPI_disableInterrupt(EUSCI_A1_BASE, EUSCI_A_SPI_RECEIVE_INTERRUPT);
                   }
        }
        /* Put a new byte to send into the TX buffer.
         * This prevents us from stuffing an extra byte.
         *****/

            /* Disable the TX interrupt.  Since the last byte of the message
             * has been sent, disable the TX interrupt.  If this is not done,
             * the ISR will be repeatedly invoked between the time that the
             * time that the UCA1TXBUF is empty and the time that the receive
             * byte is available in UCA1RXBUF.
             *****/
     }

    if (UCA1IFG & UCRXIFG)
    {
        RXData = EUSCI_A_SPI_receiveData(EUSCI_A1_BASE);
        if (waitForReceive && (RXData == 0x21)){
            waitForReceive = 0;
            TXData = 5;
        }

    }

}


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    对于快速 SPI 和短事务、我建议您不要使用中断、因为它们会使您的设计复杂化、并实际上会使您的系统减速。 对于混用 Tx 和 Rx 的情况、此建议变得更加强烈、因为(a)很难将 Tx 与 Rx 字节匹配、(b) Rx 溢出几乎是不可避免的。

    多年来,我从这里的 spix()函数中获得了很多里程:

    https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/758000/msp430fr5729-problems-with-implementing-mcp23s08-8-bit-port-expander-on-msp430fr5729/2800722#2800722

    它故意很简单、因此您始终知道使用哪个字节、而使用快速 SPI 时、旋转环路不会旋转很长时间。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    在 spix()中的 TXIFG 上等待是浪费时间的,因为它将始终被置位。 将一个字节放入 TXBUF spix()后,等待一个字节出现在 RXBUF 中。 发生这种情况时、发送移位寄存器不仅为空、而且 TXBUF 长期以来一直为空。

    中断的问题是、在每个字节被发送的情况下都接收到一个字节。 更糟糕的是、计时偏斜。

    数据传输到 TXBUF 且前一个字节位于发送移位寄存器中后、waitForReceive 置1。 这意味着当接收中断被触发时、它将用于那个时隙。 而不是 TXBUF 中等待的数据。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    
    #include <driverlib.h>
    #include <msp430.h> 
    #include "clock~.h"                 // Clock configurations
    
    
    static uint8_t TXData = 0;           //transaction count
    static uint8_t RXData = 0;           //SPI receive byte
    
    
    typedef struct {
        uint8_t     Len;
        uint8_t    Data[5];
    } spi_MaximTrans_t;
    
    static spi_MaximTrans_t DCInit_transactions[15];
    
    
    uint8_t SPI_TX_index = 0;            //byte count in transaction
    
    /**
     *  Initialize system clocks
     */
    static void init_clock(void) {
        // Configure one FRAM waitstate as required by the device datasheet for MCLK
        // operation beyond 8MHz _before_ configuring the clock system.
        FRAMCtl_configureWaitStateControl(FRAMCTL_ACCESS_TIME_CYCLES_1);
    
        //Set DCO FLL reference = REFO
        CS_initClockSignal(CS_FLLREF, CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);
        //Set ACLK = REFO
        CS_initClockSignal(CS_ACLK,   CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);
    
        CS_initFLLParam param = {0};
        //Set Ratio/Desired MCLK Frequency, initialize DCO, save trim values
        CS_initFLLCalculateTrim(CS_MCLK_DESIRED_FREQUENCY_IN_KHZ, CS_MCLK_FLLREF_RATIO, &param);
    
        //Set MCLK = REFO
        CS_initClockSignal(CS_MCLK,   CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);
        //Set SMCLK = DCO
        CS_initClockSignal(CS_SMCLK,  CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1);
    
        //Clear all OSC fault flag
        CS_clearAllOscFlagsWithTimeout(1000);
    }
    
    /**
     *  Initialize all of the IO pins per their configuration
     */
    static void init_gpio(void) {
        // Set all GPIO pins to output low to prevent floating input and reduce power consumption
        GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);
    
        GPIO_setAsOutputPin(   GPIO_PORT_P1, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P2, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P3, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P4, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P5, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);
    
    }
    
    /*
     * Initialize the SPI peripheral on EUSCI A1
     */
    void init_spi_peripheral()
    {
        //Initialize Master
            EUSCI_A_SPI_initMasterParam param = {0};
            param.selectClockSource = EUSCI_A_SPI_CLOCKSOURCE_SMCLK;
            param.clockSourceFrequency = CS_getSMCLK();
            param.desiredSpiClock = 1000000;
            param.msbFirst = UCMSB;
            param.clockPhase = 0;
            param.clockPolarity = EUSCI_A_SPI_CLOCKPOLARITY_INACTIVITY_LOW;
            param.spiMode = EUSCI_A_SPI_3PIN;
            EUSCI_A_SPI_initMaster(EUSCI_A1_BASE, &param);
    
            EUSCI_A_SPI_enable(EUSCI_A1_BASE);
    
    }
    
    
    void SetUpTransactions(void){
        //Enable keep alive mode
        DCInit_transactions[0].Len = 2;
        DCInit_transactions[0].Data[0] = 0x10;
        DCInit_transactions[0].Data[1] = 0x5;       //No Receive
    
        //Enable Rx Interrupt flags
        DCInit_transactions[1].Len = 2;
        DCInit_transactions[1].Data[0] = 0x4;
        DCInit_transactions[1].Data[1] = 0x88;      //No Receive
    
        //Clear receive buffer
        DCInit_transactions[2].Len = 1;
        DCInit_transactions[2].Data[0] = 0xe0;      //No Receive
    
        //Wakeup UART slave devices
        DCInit_transactions[3].Len = 2;
        DCInit_transactions[3].Data[0] = 0xe0;
        DCInit_transactions[3].Data[1] = 0x30;      //No Receive
    
        //Wait for all UART slave devices to wake up
        DCInit_transactions[4].Len = 1;
        DCInit_transactions[4].Data[0] = 0x01;      //Receive of 0x21 expected
    
        //End of UART slave device wake-up period
        DCInit_transactions[5].Len = 2;
        DCInit_transactions[5].Data[0] = 0x0e;
        DCInit_transactions[5].Data[1] = 0x10;      //No Receive
    
        //Wait for null message to be received
        DCInit_transactions[6].Len = 1;
        DCInit_transactions[6].Data[0] = 0x01;      //No Receive
    
        //Clear transmit buffer
        DCInit_transactions[7].Len = 1;
        DCInit_transactions[7].Data[0] = 0x20;      //No Receive
    
        //Clear receive buffer
        DCInit_transactions[8].Len = 1;
        DCInit_transactions[8].Data[0] = 0xe0;      //No Receive
    
    }
    
    
    /**
     * main.c
     */
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    
    
        init_clock();
        init_gpio();                                    // Set up IO pins
    
        GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);
    
        // Configure SPI Pins for UCA1CLK, UCA1TXD/UCA1SIMO and UCA1RXD/UCA1SOMI
        /*
        * Select Port 2
        * Set Pin 4, Pin 5 and Pin 6 to input Secondary Module Function
        */
        GPIO_setAsPeripheralModuleFunctionInputPin(
            GPIO_PORT_P2,
            GPIO_PIN4 + GPIO_PIN5 + GPIO_PIN6,
            GPIO_PRIMARY_MODULE_FUNCTION
        );
    
        // Set P1.0 to output direction
    
        GPIO_setAsOutputPin (GPIO_PORT_P1, GPIO_PIN0);
        GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P4, GPIO_PIN2);
        GPIO_enableInterrupt (GPIO_PORT_P4, GPIO_PIN2);
        GPIO_selectInterruptEdge (GPIO_PORT_P4, GPIO_PIN2, GPIO_HIGH_TO_LOW_TRANSITION);
        GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2);
    
        PMM_unlockLPM5();
    
    
        SetUpTransactions();
        TXData = 0x0;                             // Holds transaction number
    
    
        // Setup peripheral(s) now that gpio and clocks are setup
        init_spi_peripheral();                      // Init Maxim spi peripheral
        //Wait for slave to initialize
    
    
        GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN1);        //Maxim chip select low
    
        while (TXData < 10){
            for(SPI_TX_index = 0; SPI_TX_index < DCInit_transactions[TXData].Len; SPI_TX_index++){
                EUSCI_A_SPI_transmitData(EUSCI_A1_BASE, DCInit_transactions[TXData].Data[SPI_TX_index]);
            }
            __delay_cycles(100);
            TXData = TXData+1;
            if (TXData == 5){
                while(!(UCA1IFG & UCRXIFG));
                    RXData = EUSCI_A_SPI_receiveData(EUSCI_A1_BASE);
                    if (RXData != 0x21)
                        TXData = 4;
            }
        }
    
    
    }
    
    //******************************************************************************
    //
    //This is the PORT2_VECTOR interrupt vector service routine
    //
    //******************************************************************************
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=PORT4_VECTOR
    __interrupt
    #elif defined(__GNUC__)
    __attribute__((interrupt(PORT2_VECTOR)))
    #endif
    void P4_ISR (void)
    {
     //   GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);
        GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2);
        // Toggle P1.0 output
        GPIO_toggleOutputOnPin (GPIO_PORT_P1, GPIO_PIN0);
    
        GPIO_disableInterrupt (GPIO_PORT_P4, GPIO_PIN2);
    }
    
    
    

    这是我的轮询代码。  正在进行 SPI 传输、 但预期的接收数据未到达。 SPI 正在重复发送事务5。 我将更仔细地查看从器件数据表、以查看是否有任何其他寄存器需要设置。 使用评估 GUI 可以正常工作。 如果您注意到与投票代码有关的任何问题、请告诉我。 也许这是新的范围、触发器并不是每次都出现。  

    谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您似乎正在传输一个字节序列、短暂等待、然后查找接收到的字节。 这是一场比赛、即使它能正常工作、也是一种非常糟糕的做法。

    您等待100个 MCLK。 如果您需要的是最终接收到的数据字节、则在发送字节后将发生大约16个 SPI 时钟。 (假设移位寄存器忙且刚放入 TXBUF 的数据正在等待。 SPI 时钟看起来是1MHz、虽然我无法分辨 MCLK 是什么、但它看起来大于8MHz。

    即使在8MHz 下、 这意味着在发送(和接收)完成之前有8个16或128个 MCLK。 这意味着您将获得第二个到最后一个接收到的字节。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢你的答复。 SPI 时钟源频率为15990784、约为16MHz。 您能告诉我在哪里可以发现接收数据是发送字节后的16个 SPI 时钟吗?  

    我在下面重新编排了 SPI 事务。 我仍然看不到接收字节。

      while (TXData < 10){
            for(SPI_TX_index = 0; SPI_TX_index < DCInit_transactions[TXData].Len; SPI_TX_index++){
                UCA1TXBUF = DCInit_transactions[TXData].Data[SPI_TX_index];
            }
    
            if (UCA1IFG & UCRXIFG)
                RXData = UCA1RXBUF;
            if (((TXData == 4) && (RXData == 0x21)) || (TXData != 4)){
                TXData = TXData+1;
            }
            else
                TXData = 4;
    
            __delay_cycles(100);
        }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    " param.desiredSpiClock = 1000000;"

    我从硬件的设计方式中获得16个 SPI 时钟。 当数据从 TXBUF 传输到发送移位寄存器时、TXIFG 被置位。 假设在 TXBUF 中输入新数据之前延迟很小、这意味着在 SPI 硬件完成操作之前、发送移位寄存器中有8个位加上 TXBUF 中的8个位要发送。 一旦 SPI 硬件进入空闲状态、UCBUSY 将被清零。

    因此、您的最新代码位将很快读取接收到的字节。 RXIFG 将已经被置位。 然后、 当移位寄存器中的数据被完全发送时、再次置位、当 TXBUF 中的数据被移出时、再次置位。

    即使您只是忽略它、您实际上应该正在读取 RXBUF 中的所有数据(请参阅前面讨论的 spix())。 发送一组数据并尝试查看 RXBUF 中接收到的一个字节的该位将永远不会正常工作。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

        while (TXData < 10){
            for(SPI_TX_index = 0; SPI_TX_index < DCInit_transactions[TXData].Len; SPI_TX_index++){
                UCA1TXBUF = DCInit_transactions[TXData].Data[SPI_TX_index];
                while (UCA1STATW & UCBUSY){
                   RXData = UCA1RXBUF;
                }
            }
    
            if (((TXData == 4) && (RXData == 0x21)) || (TXData != 4)){
                TXData = TXData+1;
            }
            else
                TXData = 4;
    
            __delay_cycles(100);
        }
    

    我对 spix()的讨论不清楚。 下面是我接下来尝试的操作。 结果没有差异。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

            for(SPI_TX_index = 0; SPI_TX_index < DCInit_transactions[TXData].Len; SPI_TX_index++){
                UCA1TXBUF = DCInit_transactions[TXData].Data[SPI_TX_index];
                while (!(UCA1IFG & UCRXIFG))
                  ;
                RXData = UCA1RXBUF;
            }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这很有道理、感谢您发帖。 我还没有看到 RXData 发生任何变化。 接下来、我将尝试使用范围。 由于我更改为轮询模式、因此如果未正确探测引脚、则示波器也会显示。 如果我重新校准探头、然后尝试、我会看到一个显示屏。 它的范围是500美元、不确定这是否与它有关。

    我正在与 Maxim 一起开一张有关握手的支持票。 如果我在 MSP430端遇到任何 SPI 问题、我将打开一个新线程。