主题中讨论的其他器件: 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, ¶m); //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; } }