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

