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.

[参考译文] MSP430FR2676:SPI 从器件问题

Guru**** 1831610 points
Other Parts Discussed in Thread: MSP430FR2676, CAPTIVATE-FR2676
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1041827/msp430fr2676-spi-slave-issues

器件型号:MSP430FR2676
主题中讨论的其他器件: CAPTIVATE-FR2676

 目标

使该处理器作为 SPI 从器件正常工作时出现问题。 基本而言、目标是使该 MCU 成为从主器件发送请求的收发器、然后根据请求做出相应响应。

问题

但是、当我 尝试传输到主器件时、我会得到间歇性和错误的结果。 错误的字节将被完全发送、或者时序将关闭、或者字节被发送到主器件的顺序将不同步等  

我尝试过的:

-我已经对我的接线进行了四次检查。

-确保两个 MCU 上的 SPI 模式设置(时钟极性、相位、LSB/MSB 等)正确。

-尝试了我在主器件上能想到的每一个时钟速度。

-绘制 MSP430FR4xx 和 MSP430FR2xx 系列用户指南和 MSP430FR2676数据表。

- 尝试使用 DriverLibrary 和直接写入寄存器。

我的代码基于 TI 提供的示例代码、如下所示。 目前、我尝试工作的所有内容是:从器件从主器件接收3个字节、然后从器 件相应地以3个字节进行响应。 我们非常感谢您为使其正常工作提供的任何帮助。  

注意:我使用 CAPTIVATE-FR2676开发板 作为从器件。 以及简单的 Arduino 作为主站。

//******************************************************************************
//   MSP430FR2676x Demo - eUSCI_A0, SPI 4-Wire Slave multiple byte RX/TX
//
//   Description: SPI master communicates to SPI slave sending and receiving
//   3 different messages of different length. SPI slave will enter LPM0
//   while waiting for the messages to be sent/receiving using SPI interrupt.
//   ACLK = NA, MCLK = SMCLK = DCO 16MHz.
//
//
//                   MSP430FR2676
//                 -----------------
//                |                 |
//                |                 |
//                |             P5.2|<- Data In (UCA0SIMO)
//                |                 |
//                |             P5.1|-> Data Out (UCA0SOMI)
//                |                 |
//                |             P5.0|<- Serial Clock In (UCA0CLK)
//                |                 |
//                |             P4.7|<- Master's GPIO (UCA0STE)
//
//******************************************************************************

#include <msp430.h>
#include <stdint.h>
#include <stdbool.h>
#include "Board.h"
#include "driverlib.h"

//******************************************************************************
// Pin Config ******************************************************************
//******************************************************************************

#define LED_OUT     P5OUT
#define LED_DIR     P5DIR
#define LED0_PIN    BIT7


//******************************************************************************
// General SPI State Machine ***************************************************
//******************************************************************************

typedef enum SPI_ModeEnum{
    IDLE_MODE,
    RX_PREAMBLE_MODE,
    TX_DATA_MODE,
    RX_DATA_MODE,
    TIMEOUT_MODE
} SPI_Mode;

/* Used to track the state of the software state machine*/
SPI_Mode SlaveMode = RX_PREAMBLE_MODE;

#define MAX_BUFFER_SIZE     20
uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0};
uint8_t RXByteCtr = 0;
uint8_t ReceiveIndex = 0;
uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0};
uint8_t TXByteCtr = 0;
uint8_t TransmitIndex = 0;

uint8_t ReceiveNumBytes = 0;
uint8_t ReceiveRW = 0;
uint8_t ReceiveRegAddr = 0;
uint8_t ReceiveHeader = 0;
uint8_t frame = 0;
static const uint8_t RX = 1;
static const uint8_t TX = 2;
uint8_t AckByteCtr = 0;

uint8_t RegisterMap[0xFF];

void SendUCA0Data(uint8_t val);
void SPI_Slave_ProcessCMD(uint8_t regaddr, uint8_t header);
void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count, uint8_t startAddr);
void initSPI();
void initSystem();
void initClockTo16MHz();



void SendUCA0Data(uint8_t val)
{
    while (!(UCA0IFG & UCTXIFG));              // USCI_A0 TX buffer ready?
    UCA0TXBUF = val;
}

void SPI_Slave_ProcessCMD(uint8_t regaddr, uint8_t header)
{
        ReceiveIndex = 0;
        TransmitIndex = 0;
        RXByteCtr = 0;
        TXByteCtr = 0;
        ReceiveRegAddr = regaddr;
        ReceiveRW = (header & 0b10000000) >> 7;
        ReceiveNumBytes = (header & 0b01111111);

         if(frame == RX)
         {
          SlaveMode = RX_DATA_MODE;
          RXByteCtr = ReceiveNumBytes;
         }
         else if(frame == TX)
         {
           SlaveMode = TX_DATA_MODE;
           TXByteCtr = ReceiveNumBytes;
           CopyArray(RegisterMap, TransmitBuffer, ReceiveNumBytes, ReceiveRegAddr);
           SendUCA0Data(header);
           SendUCA0Data(ReceiveRegAddr);
         }

}

void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count, uint8_t startAddr)
{
    unsigned int copyIndex = 0;
    for (copyIndex = 0; copyIndex < count; copyIndex++)
    {
        dest[copyIndex] = source[copyIndex+startAddr];
    }
}

//******************************************************************************
// Device Initialization *******************************************************
//******************************************************************************

void initSPI()
{
    SYSCFG3|=USCIA0RMP;                       //Set the SPI remapping source
    P5SEL0 |= BIT0 | BIT1 | BIT2;             // set SPI MOSI, MISO, & CLK pins as second function
    //Initialize slave to LSB first, clock polarity of 0, clock phase of 1 and 4 wire SPI
    EUSCI_A_SPI_initSlaveParam param = {0};
    param.msbFirst = EUSCI_A_SPI_MSB_FIRST;
    param.clockPhase = EUSCI_A_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT;
    param.clockPolarity = EUSCI_A_SPI_CLOCKPOLARITY_INACTIVITY_LOW;
    param.spiMode = EUSCI_A_SPI_4PIN_UCxSTE_ACTIVE_LOW; //UCMODE_2
    EUSCI_A_SPI_initSlave(EUSCI_A0_BASE, &param);

    //Enable SPI Module
    EUSCI_A_SPI_enable(EUSCI_A0_BASE);
    //Clear receive interrupt flag
    EUSCI_A_SPI_clearInterrupt(EUSCI_A0_BASE, EUSCI_A_SPI_RECEIVE_INTERRUPT);
    //Enable Receive interrupt
    EUSCI_A_SPI_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_SPI_RECEIVE_INTERRUPT);
}

void initSystem()
{
    WDTCTL = WDTPW | WDTHOLD;   // Stop watchdog timer
    initClockTo16MHz();
    //Stop watchdog timer
    WDT_A_hold(WDT_A_BASE);

    // Configure Pins for XIN
    //Set P2.0 and P2.1 as Module Function Input.
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN1 + GPIO_PIN0, GPIO_PRIMARY_MODULE_FUNCTION);

    // Configure SPI Pins for UCA0CLK, UCA0TXD/UCA0SIMO and UCA0RXD/UCA0SOMI
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2, GPIO_PRIMARY_MODULE_FUNCTION);

    // Disable the GPIO power-on default high-impedance mode to activate previously configured port settings
    PMM_unlockLPM5();

    initSPI();

    __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0, enable interrupts
}

void initClockTo16MHz()
{
    // Configure one FRAM waitstate as required by the device datasheet for MCLK
    // operation beyond 8MHz _before_ configuring the clock system.
    FRCTL0 = FRCTLPW | NWAITS_1;

    __bis_SR_register(SCG0);    // disable FLL
    CSCTL3 |= SELREF__REFOCLK;  // Set REFO as FLL reference source
    CSCTL0 = 0;                 // clear DCO and MOD registers
    CSCTL1 &= ~(DCORSEL_7);     // Clear DCO frequency select bits first
    CSCTL1 |= DCORSEL_5;        // Set DCO = 16MHz
    CSCTL2 = FLLD_0 + 487;      // set to fDCOCLKDIV = (FLLN + 1)*(fFLLREFCLK/n)
                                //                   = (487 + 1)*(32.768 kHz/1)
                                //                   = 16 MHz

    __delay_cycles(3);
    __bic_SR_register(SCG0);                        // enable FLL
    while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));      // FLL locked
}


//******************************************************************************
// Main ************************************************************************
// Enters LPM0 and waits for SPI interrupts. The data sent from the master is  *
// then interpreted and the device will respond accordingly                    *
//******************************************************************************
void main(void) 
{
    initSystem();
    __no_operation();
    RegisterMap[128] = 1;
}

//******************************************************************************
// SPI Interrupt ***************************************************************
//******************************************************************************
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
{
    uint8_t uca0_rx_val = 0;
    switch(__even_in_range(UCA0IV, USCI_SPI_UCTXIFG))
    {
        case USCI_NONE: break;
        case USCI_SPI_UCRXIFG:
            uca0_rx_val = UCA0RXBUF;
            UCA0IFG &= ~UCRXIFG;
            switch (SlaveMode)
            {
                case (RX_PREAMBLE_MODE):
                    frame = RX;
                    if(AckByteCtr == 0)
                    {
                      ReceiveHeader = uca0_rx_val;
                      AckByteCtr = 1;
                    }
                    else if(AckByteCtr == 1)
                    {
                        ReceiveRegAddr = uca0_rx_val;
                        SPI_Slave_ProcessCMD(ReceiveRegAddr, ReceiveHeader);
                        AckByteCtr = 0;
                    }
                    break;
                case (RX_DATA_MODE):
                    ReceiveBuffer[ReceiveIndex++] = uca0_rx_val;
                    RXByteCtr--;
                    if (RXByteCtr == 0)
                    {
                        frame = TX;
                        SPI_Slave_ProcessCMD(ReceiveRegAddr, ReceiveHeader);
                    }
                    break;
                case (TX_DATA_MODE):
                    if (TXByteCtr > 0)
                    {
                        SendUCA0Data(1);//TransmitBuffer[TransmitIndex++]);
                        TXByteCtr--;
                    }
                    if (TXByteCtr == 0)
                    {
                        //Done Transmitting MSG
                        SlaveMode = RX_PREAMBLE_MODE;
                    }
                    break;
                default:
                    __no_operation();
                    break;
                }
            break;
        case USCI_SPI_UCTXIFG:
            break;
        default: break;
    }
}

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

    尊敬的 Max:

    查看这个代码、很明显、当主器件发送8个时钟并且它是第一个字节到从器件(MSP430)时、生成 SPI 接收中断并且 ISR 调用函数 SendUCA0Data (1)。  在该函数中、值1被写入 TXBUF。  到目前为止都很好。  然后、为了时钟输出 TXBUF 中的值、主器件必须再发送8个时钟脉冲、该值为= 1。  因此、我怀疑您在主器件的前8个时钟脉冲期间看到的是随机的、在第二组8个时钟脉冲上、您应该看到值1。 有道理?  你看到什么?

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

    尊敬的 Dennis:  

    那么、现在我得到的是-第一笔交易按预期进行。 但后续的每一个事务都是错误的(从器件只发送0x01)

    第一个事务:主机发送 0x01、0x80、0x02到从机。 然后从器件用0x01、0x80、0x01进行响应。  

     第一个传输后的每个传输: 主机发送  0x01、0x80、0x02到从机。 然后从器件用0x01、0x01、0x01进行响应。  

    逻辑分析仪中的第一个事务(正确):

    逻辑分析仪中的以下每个事务(错误):

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

    Dennis 在这里是最新的代码(主要是更多注释以帮助理解逻辑)。

    //******************************************************************************
    //   MSP430FR2676x Demo - eUSCI_A0, SPI 4-Wire Slave multiple byte RX/TX
    //
    //   Description: SPI master communicates to SPI slave sending and receiving
    //   3 different messages of different length. SPI slave will enter LPM0
    //   while waiting for the messages to be sent/receiving using SPI interrupt.
    //   ACLK = NA, MCLK = SMCLK = DCO 16MHz.
    //
    //
    //                   MSP430FR2676
    //                 -----------------
    //                |                 |
    //                |             P5.2|<- Data In (UCA0SIMO)
    //                |                 |
    //                |             P5.1|-> Data Out (UCA0SOMI)
    //                |                 |
    //                |             P5.0|<- Serial Clock In (UCA0CLK)
    //                |                 |
    //                |             P4.7|<- Master's GPIO (UCA0STE)
    //
    //******************************************************************************
    
    #include <msp430.h>
    #include <stdint.h>
    #include <stdbool.h>
    #include "Board.h"
    #include "driverlib.h"
    
    //******************************************************************************
    // Defines *********************************************************************
    //******************************************************************************
    
    #define LED_OUT     P5OUT
    #define LED_DIR     P5DIR
    #define LED0_PIN    BIT7
    
    
    #define MAX_BUFFER_SIZE     20
    
    
    //******************************************************************************
    // Globals *********************************************************************
    //******************************************************************************
    
    uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0};
    uint8_t RXByteCtr = 0;
    uint8_t ReceiveIndex = 0;
    uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0};
    uint8_t TXByteCtr = 0;
    uint8_t TransmitIndex = 0;
    
    uint8_t ReceiveNumBytes = 0;
    uint8_t ReceiveRW = 0;
    uint8_t ReceiveRegAddr = 0;
    uint8_t ReceiveHeader = 0;
    uint8_t frame = 0;
    const uint8_t RX = 1;
    const uint8_t TX = 2;
    uint8_t AckByteCtr = 0;
    
    uint8_t RegisterMap[0xFF];
    
    
    //******************************************************************************
    // SPI State Machine ***********************************************************
    //******************************************************************************
    
    typedef enum SPI_ModeEnum{
        IDLE_MODE,
        RX_PREAMBLE_MODE,
        TX_DATA_MODE,
        RX_DATA_MODE,
        TIMEOUT_MODE
    } SPI_Mode;
    
    /* Used to track the state of the software state machine*/
    SPI_Mode SlaveMode = RX_PREAMBLE_MODE;
    
    
    
    void SendUCA0Data(uint8_t val);
    void SPI_Slave_ProcessCMD(uint8_t regaddr, uint8_t header);
    void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count, uint8_t startAddr);
    void initSPI();
    void initSystem();
    void initClockTo16MHz();
    
    
    
    void SendUCA0Data(uint8_t val)
    {
        while (!(UCA0IFG & UCTXIFG));              // USCI_A0 TX buffer ready?
        UCA0TXBUF = val;
    }
    
    void SPI_Slave_ProcessCMD(uint8_t regaddr, uint8_t header)
    {
            ReceiveIndex = 0; //Clear Rx Index
            TransmitIndex = 0; //Clear Tx Index
            RXByteCtr = 0; //Clear Rx Byte Counter
            TXByteCtr = 0; //Clear Tx Byte Counter
            ReceiveRegAddr = regaddr; //Get Register Address for processing
            ReceiveRW = (header & 0b10000000) >> 7; //Get RW Bit from 1st bit of Header Byte
            ReceiveNumBytes = (header & 0b01111111); //Get Num Regs from last 7 bits of Header Byte
    
             if(frame == RX)
             {
              SlaveMode = RX_DATA_MODE; //Enter RX_Data Mode inside interrupt
              RXByteCtr = ReceiveNumBytes; //Set Rx Counter to # of data bytes to be received
             }
             else if(frame == TX)
             {
               SlaveMode = TX_DATA_MODE; //Enter TX_Data Mode inside interrupt
               TXByteCtr = ReceiveNumBytes; //Set Tx Counter to # of data bytes to be sent
               CopyArray(RegisterMap, TransmitBuffer, ReceiveNumBytes, ReceiveRegAddr); //Gather data from requested registers and add it to the transmit buffer.
               SendUCA0Data(header); //Send header byte
               SendUCA0Data(ReceiveRegAddr); //Send Register Address byte
             }
    
    }
    
    void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count, uint8_t startAddr)
    {
        unsigned int copyIndex = 0;
        for (copyIndex = 0; copyIndex < count; copyIndex++)
        {
            dest[copyIndex] = source[copyIndex+startAddr];
        }
    }
    
    //******************************************************************************
    // Device Initialization *******************************************************
    //******************************************************************************
    
    void initSPI()
    {
        SYSCFG3|=USCIA0RMP;                       //Set the SPI remapping source
        P5SEL0 |= BIT0 | BIT1 | BIT2;             // set SPI MOSI, MISO, & CLK pins as second function
    
        //Initialize slave to MSB first, clock polarity of 0, clock phase of 1 and 4 wire SPI
        EUSCI_A_SPI_initSlaveParam param = {0};
        param.msbFirst = EUSCI_A_SPI_MSB_FIRST;
        param.clockPhase = EUSCI_A_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT;
        param.clockPolarity = EUSCI_A_SPI_CLOCKPOLARITY_INACTIVITY_LOW;
        param.spiMode = EUSCI_A_SPI_4PIN_UCxSTE_ACTIVE_LOW; //UCMODE_2
        EUSCI_A_SPI_initSlave(EUSCI_A0_BASE, &param);
    
        EUSCI_A_SPI_enable(EUSCI_A0_BASE); //Enable SPI Module
        EUSCI_A_SPI_clearInterrupt(EUSCI_A0_BASE, EUSCI_A_SPI_RECEIVE_INTERRUPT); //Clear receive interrupt flag
        EUSCI_A_SPI_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_SPI_RECEIVE_INTERRUPT);//Enable Receive interrupt
    }
    
    void initSystem()
    {
        WDTCTL = WDTPW | WDTHOLD;   // Stop watchdog timer
        initClockTo16MHz(); //init clock
        WDT_A_hold(WDT_A_BASE); //Stop watchdog timer
    
        GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN1 + GPIO_PIN0, GPIO_PRIMARY_MODULE_FUNCTION); //Configure Pins for XIN - Set P2.0 and P2.1 as Module Function Input.
        GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2, GPIO_PRIMARY_MODULE_FUNCTION); // Configure SPI Pins for UCA0CLK, UCA0TXD/UCA0SIMO and UCA0RXD/UCA0SOMI
    
        PMM_unlockLPM5(); // Disable the GPIO power-on default high-impedance mode to activate previously configured port settings
        initSPI(); //init SPI
        __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0, enable interrupts
    }
    
    void initClockTo16MHz()
    {
        FRCTL0 = FRCTLPW | NWAITS_1; // Configure one FRAM waitstate as required by the device datasheet for MCLK operation beyond 8MHz _before_ configuring the clock system.
        __bis_SR_register(SCG0);    // disable FLL
        CSCTL3 |= SELREF__REFOCLK;  // Set REFO as FLL reference source
        CSCTL0 = 0;                 // clear DCO and MOD registers
        CSCTL1 &= ~(DCORSEL_7);     // Clear DCO frequency select bits first
        CSCTL1 |= DCORSEL_5;        // Set DCO = 16MHz
        CSCTL2 = FLLD_0 + 487;      // set to fDCOCLKDIV = (FLLN + 1)*(fFLLREFCLK/n) = (487 + 1)*(32.768 kHz/1) = 16 MHz
    
        __delay_cycles(3);
        __bic_SR_register(SCG0);                        // enable FLL
        while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));      // FLL locked
    }
    
    
    //******************************************************************************
    // Main ************************************************************************
    // Enters LPM0 and waits for SPI interrupts. The data sent from the master is  *
    // then interpreted and the device will respond accordingly                    *
    //******************************************************************************
    void main(void)
    {
        initSystem();
        __no_operation();
    }
    
    //******************************************************************************
    // SPI Interrupt ***************************************************************
    //******************************************************************************
    #pragma vector=USCI_A0_VECTOR
    __interrupt void USCI_A0_ISR(void)
    {
        RegisterMap[128] = 1;
        uint8_t uca0_rx_val = 0;
        switch(__even_in_range(UCA0IV, USCI_SPI_UCTXIFG))
        {
            case USCI_NONE: break;
            case USCI_SPI_UCRXIFG:
                uca0_rx_val = UCA0RXBUF;
                UCA0IFG &= ~UCRXIFG;
                switch (SlaveMode)
                {
                    case (RX_PREAMBLE_MODE):
                        frame = RX;
                        if(AckByteCtr == 0)
                        {
                          ReceiveHeader = uca0_rx_val; //Grab Header Byte
                          AckByteCtr = 1; //Get ready to grab next byte
                        }
                        else if(AckByteCtr == 1)
                        {
                            ReceiveRegAddr = uca0_rx_val; //Grab Register Address Byte
                            SPI_Slave_ProcessCMD(ReceiveRegAddr, ReceiveHeader); //Process receiving part of transaction
                            AckByteCtr = 0;
                        }
                        break;
                    case (RX_DATA_MODE):
                        ReceiveBuffer[ReceiveIndex++] = uca0_rx_val; //Receive # of Data Bytes Requested
                        RXByteCtr--;
                        if (RXByteCtr == 0)
                        {
                            frame = TX; //Get ready to send response
                            SPI_Slave_ProcessCMD(ReceiveRegAddr, ReceiveHeader); //Process transmitting part of transaction
                        }
                        break;
                    case (TX_DATA_MODE):
                        if (TXByteCtr > 0)
                        {
                            SendUCA0Data(TransmitBuffer[TransmitIndex++]); //Transmit # of Data Bytes Requested
                            TXByteCtr--;
                        }
                        if (TXByteCtr == 0)
                        {
                            //Done Transmitting MSG
                            SlaveMode = RX_PREAMBLE_MODE; // Transaction complete, get ready for next transaction
                        }
                        break;
                    default:
                        __no_operation();
                        break;
                    }
                break;
            case USCI_SPI_UCTXIFG:
                break;
            default: break;
        }
    }
    

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

    这也是我要使用的 board.h 文件(找不到适用于此处理器/开发套件的文件、因此必须从头开始创建)

    /* --COPYRIGHT--,BSD
     * Copyright (c) 2017, 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.
     * --/COPYRIGHT--*/
    /**
     * ===
     * Board.h
     * ===
     * This file is meant to provide generic GPIO selection definitions that allows
     * DriverLib to be used portably across different LaunchPads. The same module
     * pin might not be populated on the same physical port and pin on different
     * LaunchPads.
     *
     * This file is intended to be modified and updated by individual users based
     * on application need. It will be initially populated according to common
     * peripherals available on a LaunchPad board, but by all means not complete.
     *
     * GPIO_PRIMARY_MODULE_FUNCTION indicates Port SEL bits are 01
     * GPIO_SECONDARY_MODULE_FUNCTION indicates Port SEL bits are 10
     * GPIO_TERNARY_MODULE_FUNCTION indicates Port SEL bits are 11
     * If the Port SEL bits are 00, the FUNCTION bits should be ignored
     * Please consult device datasheet for more info, under "Input/Output Diagrams"
     *
     **/
    
    #ifndef __BOARD_H__
    #define __BOARD_H__
    
    #ifdef __MSP430FR2676__
    
    
    #define GPIO_PORT_LED1          GPIO_PORT_P1
    #define GPIO_PIN_LED1           GPIO_PIN7
    
    #define GPIO_PORT_LED2          GPIO_PORT_P1
    #define GPIO_PIN_LED2           GPIO_PIN6
    
    #define GPIO_PORT_LED3          GPIO_PORT_P5
    #define GPIO_PIN_LED3           GPIO_PIN7
    
    #define GPIO_PORT_S1            GPIO_PORT_P5
    #define GPIO_PIN_S1             GPIO_PIN3
    
    #define GPIO_PORT_ADC7          GPIO_PORT_P1
    #define GPIO_PIN_ADC7           GPIO_PIN7
    #define GPIO_FUNCTION_ADC7      GPIO_PRIMARY_MODULE_FUNCTION
    
    #define GPIO_PORT_MCLK          GPIO_PORT_P1
    #define GPIO_PIN_MCLK           GPIO_PIN3
    #define GPIO_FUNCTION_MCLK      GPIO_PRIMARY_MODULE_FUNCTION
    
    #define GPIO_PORT_SMCLK         GPIO_PORT_P1
    #define GPIO_PIN_SMCLK          GPIO_PIN7
    #define GPIO_FUNCTION_SMCLK     GPIO_SECONDARY_MODULE_FUNCTION
    
    #define GPIO_PORT_ACLK          GPIO_PORT_P2
    #define GPIO_PIN_ACLK           GPIO_PIN2
    #define GPIO_FUNCTION_ACLK      GPIO_SECONDARY_MODULE_FUNCTION
    
    #define GPIO_PORT_UCA0TXD       GPIO_PORT_P1
    #define GPIO_PIN_UCA0TXD        GPIO_PIN4
    #define GPIO_FUNCTION_UCA0TXD   GPIO_PRIMARY_MODULE_FUNCTION
    
    #define GPIO_PORT_UCA0RXD       GPIO_PORT_P1
    #define GPIO_PIN_UCA0RXD        GPIO_PIN5
    #define GPIO_FUNCTION_UCA0RXD   GPIO_PRIMARY_MODULE_FUNCTION
    
    #define GPIO_PORT_UCB0SCL       GPIO_PORT_P1
    #define GPIO_PIN_UCB0SCL        GPIO_PIN3
    #define GPIO_FUNCTION_UCB0SCL   GPIO_PRIMARY_MODULE_FUNCTION
    
    #define GPIO_PORT_UCB0SDA       GPIO_PORT_P1
    #define GPIO_PIN_UCB0SDA        GPIO_PIN2
    #define GPIO_FUNCTION_UCB0SDA   GPIO_PRIMARY_MODULE_FUNCTION
    
    #endif // __MSP430FR2676__
    
    
    #ifdef __MSP430FR4133__
    
    #define GPIO_PORT_LED1          GPIO_PORT_P1
    #define GPIO_PIN_LED1           GPIO_PIN0
    #define GPIO_PORT_LED2          GPIO_PORT_P4
    #define GPIO_PIN_LED2           GPIO_PIN0
    #define GPIO_PORT_S1            GPIO_PORT_P1
    #define GPIO_PIN_S1             GPIO_PIN2
    
    #define GPIO_PORT_ADC7          GPIO_PORT_P1
    #define GPIO_PIN_ADC7           GPIO_PIN7
    #define GPIO_FUNCTION_ADC7      GPIO_PRIMARY_MODULE_FUNCTION
    
    #define GPIO_PORT_MCLK          GPIO_PORT_P1
    #define GPIO_PIN_MCLK           GPIO_PIN4
    #define GPIO_FUNCTION_MCLK      GPIO_PRIMARY_MODULE_FUNCTION
    #define GPIO_PORT_SMCLK         GPIO_PORT_P8
    #define GPIO_PIN_SMCLK          GPIO_PIN0
    #define GPIO_FUNCTION_SMCLK     GPIO_PRIMARY_MODULE_FUNCTION
    #define GPIO_PORT_ACLK          GPIO_PORT_P8
    #define GPIO_PIN_ACLK           GPIO_PIN1
    #define GPIO_FUNCTION_ACLK      GPIO_PRIMARY_MODULE_FUNCTION
    
    #define GPIO_PORT_UCA0TXD       GPIO_PORT_P1
    #define GPIO_PIN_UCA0TXD        GPIO_PIN0
    #define GPIO_FUNCTION_UCA0TXD   GPIO_PRIMARY_MODULE_FUNCTION
    #define GPIO_PORT_UCA0RXD       GPIO_PORT_P1
    #define GPIO_PIN_UCA0RXD        GPIO_PIN1
    #define GPIO_FUNCTION_UCA0RXD   GPIO_PRIMARY_MODULE_FUNCTION
    
    #define GPIO_PORT_UCB0SCL       GPIO_PORT_P5
    #define GPIO_PIN_UCB0SCL        GPIO_PIN3
    #define GPIO_FUNCTION_UCB0SCL   GPIO_PRIMARY_MODULE_FUNCTION
    #define GPIO_PORT_UCB0SDA       GPIO_PORT_P5
    #define GPIO_PIN_UCB0SDA        GPIO_PIN2
    #define GPIO_FUNCTION_UCB0SDA   GPIO_PRIMARY_MODULE_FUNCTION
    
    #endif // __MSP430FR4133__
    
    
    #endif // __BOARD_H__

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

    Dennis、

    讨厌保留消息、但这是一 个紧急工作项目 、我们目前处于停滞状态。 我们非常感谢您的任何帮助。

    谢谢

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

    尊敬的 Max:

    很抱歉耽误你的时间。  让我来总结一下您最近的帖子。

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

    我感觉比赛有问题。 在您接收到发送数据的命令后、主器件会不断输出时钟。 那么、哪种情况首先发生:您将数据输入 TXBUF 或 TXBUF、然后将其传输到移位寄存器?

    我在文档中看不到任何内容、甚至暗示了何时会发生这种转移。

    但是、由于对于第一个事务似乎可以正常工作、而不是第二个事务、因此问题出在您的状态机中的某个位置。 由于某种原因、它不会将任何数据放入 TXBUF 中、因此最后写入的值会不断被发送。

    但要考虑时间。 ISR 将其最终字节放入 TXBUF 并将状态切换为前导码模式。 但在这个传输中仍然有时钟(发送移位寄存器和 TXBUF 中的数据)和两个接收中断。 这意味着接收状态机似乎不关心接收到的值、它会发送另一组要处理的数据。 这不能很好地结束。

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

    尊敬的 David:

    你的钱是对的。  

    在切换回前导码模式之前、我只需插入 以下内容:

    while (EUSCI_A_SPI_isBusy (EUSCI_A0_BASE)== EUSCI_A_SPI_BUSY);

    等待 SPI 事务完成、然后再切换。

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

    尊敬的 Max:

    按照代码的逻辑、我认为这可能是问题所在。  更改它并告知我。

    情况(TX_DATA_MODE):


    IF (TXByteCtr > 0)

    // TXByteCtr = 1、主器件刚刚计时为0x00 in、从器件计时为0x01 out、TXBUF (0x80)移至移位寄存器、TXIFG 置1

    SendUCA0Data (TransmitBuffer[TransmitIndex++]);//发送请求的数据字节数//将 transmitBuffer[0](这是寄存器映射的副本[])移入 TXBUF

    TXByteCtr -;//此时 TXByteCtr = 0

    如果(TXByteCtr = 0)<--- 我认为这是问题-应该是->如果 else (TXByteCtr = 0)

    //完成发送 MSG
    SlaveMode = RX_PREAMARY_MODE;//事务完成、为下一个事务做好准备

    中断;
    默认值:

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

    Dennis、

    感谢您的回答。 David 的回答解决了问题。

    有关如何从中断例程的内部和外部访问"RegisterMap[]"数组中的值的任何想法?

    这是否可行?

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

    RegisterMap[]是一个全局变量,可在任何地方访问。

    另一件事。 许多 SPI 从器件使用 CS 信号进行帧事务、但您在这里所做的只是启用 SPI 从器件。 最好使用 STE 信号转换来重置状态机。 PxSEL 位会禁用端口中断硬件、因此这不是一个选项、但这一点似乎并不完全清零。

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

    尊敬的 Max:

    感谢 David :)

    我看不到如何使用 RegisterMap[]的问题。  它是一个全局变量、因此您可以使用 ISR 和主代码来访问它。  不过、我会将其声明为"易失性"、原因如下:

    volatile 关键字旨在防止编译器对可能以编译器无法确定的方式更改的对象应用任何优化。  

    优化时省略声明为易失性的对象、因为在当前代码范围之外的代码可以随时更改其值。 系统始终从存储器位置读取易失性对象的当前值、而不是在请求时将其值保存在临时寄存器中、即使之前的指令要求同一对象提供值也是如此。 因此、简单的问题是、变量的值如何以编译器无法预测的方式变化。 请考虑以下情况来回答此问题。  

    由范围外的中断服务例程修改的全局变量: 例如、全局变量可以表示将动态更新的数据端口(通常称为存储器映射 IO 的全局指针)。 必须将读取数据端口的代码声明为易失性、以便获取端口上可用的最新数据。 如果无法将变量声明为易失性、编译器将优化代码、使其只读取端口一次、并在临时寄存器中继续使用相同的值来加速程序(速度优化)。 通常、当由于新数据的可用性而产生中断时、用于更新这些数据端口的 ISR  

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

    Dennis、  

    无论我是否将其声明为易失性,都不能从中断中访问 main()中存储的任何值。 例如、如果我必须从 主循环中将寄存器0x28中的数据更新为2的值(例如、RegisterMap[0x28]= 2;)、因为按下按钮后一切正常。 但是、当我返回到中断时、该值不会给出。  我如何做到这一点、以便可以从围栏的两侧访问每个寄存器中存储的数据?

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

    最大值、

    当然、volatile 不是为了处理变量的范围。  让我确保我理解。

    您在代码中顶部的"Globals"下显示  

    uint8_t 寄存器映射[0xFF];

    根据我的经验,只要变量位于同一文件中并且未在函数中声明(除非声明为静态变量),就可以由同一文件中的任何函数访问该变量,包括 ISR 或 main()。

    我有这样的权利吗?

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

    David、  

    再次感谢、此中断由 CS 引脚上的低电平信号触发。 如果您回头看我对 Dennis 的第一次答复、逻辑分析仪剪辑会显示该行在交易中变为低电平、然后在交易结束后再次变为高电平。

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

    Dennis、  

    我认为差异是因为它是一个硬件中断、而不仅仅是一个软件中断。 我唯一能够使寄存器值发生变化 并且仍然可以在中断中访问的方法是 、如果我 从中断例程中更新它们... 但是、当然、如果我根据  我在中断例程之外监视的传感器更新寄存器数据、那么我将如何将这些更新的值发送到中断例程、反之亦然?

    我很想在这方面出错、但这正是我所经历的。

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

    CS 信号不会导致中断。 它使能 SPI 从器件、RXIFG 触发中断。 它对您的状态机没有影响。

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

    David、  

    我明白了。 因此 CS 线路只允许设置中断标志之一、进而触发中断。  

    感谢大家的帮助。 如果有人有建议、仍在寻找中断问题的解决方案。

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

    Dennis、  

    我发现问题是因为 MCU 进入了低功耗模式! 因此、更改主循环中的任何变量甚至都无法访问、因此在中断中显示为空。  

    因此、以下内容:

        __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0, enable interrupts

    需要更改为:

        __bis_SR_register(GIE);       // Enable interrupts

    这篇文章 让我意识到了这个问题: https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/119681/loop-on-a-global-variable-that-is-changed-in-interrupt

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

    虽然这些内容出现在 MSP430头文件中、但我从未使用过它们。 这些头文件还定义了一些可读性稍高的宏、例如"LPM0;"和"LPM0_EXIT;"。 为了控制全局中断使能、我使用"_eint()"。

    使这些操作完全分离。 我通常在进入主(无限)循环并进入循环内的低功耗模式之前启用中断。