Hi,
I'm trying to use UCA1 SPI to communicate the MSP430FR5969 with HopeRF RFM69 transceiver. So the MSP430 (master) sends commands to configure the RFM69 and makes it transmit some data. However the transceiver doesn't work and when I check the SPI signals by logic analyser, there are some clock jitters (as in pictures) which makes the MSP430 randomly sends some wrong data to the RFM69. I have tested it on both the board EXP430FR5969 and seperately with the MSP430FR5969 chip (I made a PCB) and both had this problem. Some commands are correct and some are not due to these strange jitters.
But when I used the UCB0 SPI on the EXP430FR5969 it worked just fine, the transceiver could transmit data (tested for many times). I have included my "SPI.h" and "SPI.c" below, these were written based on the example "msp430fr59xx_eusci_spi_standard_master.c". Can you please help?
//****************************************************************************** // MSP430FR59xx Demo - eUSCI_A0, SPI 3-Wire Master multiple byte RX/TX // // Description: SPI master communicates to SPI slave sending and receiving // 3 different messages of different length. SPI master will enter LPM0 mode // while waiting for the messages to be sent/receiving using SPI interrupt. // SPI Master will initially wait for a port interrupt in LPM0 mode before // starting the SPI communication. // ACLK = NA, MCLK = SMCLK = DCO 16MHz. // // // MSP430FR5969 // ----------------- // /|\ | P1.3|-> Slave Chip Select (GPIO) // | | | // ---|RST P1.4|-> Slave Reset (GPIO) // | | // | P2.5|-> Data Out (UCA1MOSI) // | | // Button ->|P1.1 P2.6|<- Data In (UCA1MISO) // | | // | P2.4|-> Serial Clock Out (UCA1CLK) // // Nima Eskandari // Texas Instruments Inc. // April 2017 // Built with CCS V7.0 //****************************************************************************** #include <SPI.h> void SendUCA1Data(uint8_t val) { while (!(UCA1IFG & UCTXIFG)); // USCI_A0 TX buffer ready? UCA1TXBUF = val; } void SPI_CopyArray(uint8_t *source, uint8_t *dest, uint8_t count) { uint8_t copyIndex = 0; for (copyIndex = 0; copyIndex < count; copyIndex++) { dest[copyIndex] = source[copyIndex]; } } SPI_Mode SPI_Master_WriteReg(uint8_t reg_addr, uint8_t *reg_data, uint8_t count) { MasterMode = TX_REG_ADDRESS_MODE; SPI_TransmitRegAddr = reg_addr | 0x80; //Copy register data to SPI_TransmitBuffer SPI_CopyArray(reg_data, SPI_TransmitBuffer, count); SPI_TXByteCtr = count; SPI_RXByteCtr = 0; SPI_ReceiveIndex = 0; SPI_TransmitIndex = 0; SLAVE_CS_OUT &= ~(SLAVE_CS_PIN); SendUCA1Data(SPI_TransmitRegAddr); __bis_SR_register(LPM3_bits + GIE); // Enter LPM3 w/ interrupts SLAVE_CS_OUT |= SLAVE_CS_PIN; return MasterMode; } SPI_Mode SPI_Master_ReadReg(uint8_t reg_addr, uint8_t count) { MasterMode = TX_REG_ADDRESS_MODE; SPI_TransmitRegAddr = reg_addr & 0x7F; SPI_RXByteCtr = count; SPI_TXByteCtr = 0; SPI_ReceiveIndex = 0; SPI_TransmitIndex = 0; SLAVE_CS_OUT &= ~(SLAVE_CS_PIN); SendUCA1Data(SPI_TransmitRegAddr); __bis_SR_register(LPM3_bits + GIE); // Enter LPM3 w/ interrupts SLAVE_CS_OUT |= SLAVE_CS_PIN; return MasterMode; } //****************************************************************************** // Device Initialization ******************************************************* //****************************************************************************** void SPI_init() { //Clock Polarity: The inactive state is high //MSB First, 8-bit, Master, 3-pin mode, Synchronous UCA1CTLW0 = UCSWRST; // **Put state machine in reset** UCA1CTLW0 |= UCMSB + UCSYNC + UCMST + UCSSEL__SMCLK; // 3-pin, 8-bit SPI Slave UCA1BRW = 0x08; // Prescaler = 8, f(spi) = f(clk)/8 //UCA1BRW = 0x20; // Prescaler = 8, f(spi) = f(clk)/8 //UCA1MCTLW = 0; UCA1CTLW0 &= ~UCSWRST; // **Initialize USCI state machine** UCA1IE |= UCRXIE; // Enable USCI0 RX interrupt /* Used to track the state of the software state machine*/ MasterMode = IDLE_MODE; /* The Register Address/Command to use*/ SPI_TransmitRegAddr = 0; /* SPI_ReceiveBuffer: Buffer used to receive data in the ISR * SPI_RXByteCtr: Number of bytes left to receive * SPI_ReceiveIndex: The index of the next byte to be received in SPI_ReceiveBuffer * SPI_TransmitBuffer: Buffer used to transmit data in the ISR * SPI_TXByteCtr: Number of bytes left to transfer * SPI_TransmitIndex: The index of the next byte to be transmitted in SPI_TransmitBuffer * */ SPI_ReceiveBuffer[SPI_MAX_BUFFER_SIZE] = {0}; SPI_RXByteCtr = 0; SPI_ReceiveIndex = 0; SPI_TransmitBuffer[SPI_MAX_BUFFER_SIZE] = {0}; SPI_TXByteCtr = 0; SPI_TransmitIndex = 0; } void SPI_initGPIO() { //P4DIR |= BIT3; // Set pin 4.3 as output for chip enable (CE) //P4OUT |= BIT3; // Configure GPIO /* Connect up SIMO, MISO. */ //P1SEL1 |= BIT6|BIT7; //P1SEL0 &= ~(BIT6|BIT7); P2SEL1 |= BIT4 | BIT5 | BIT6; // Enable pin 2.4 (SCL), 2.5 (MOSI), 2.6 (MISO) P2SEL0 &= ~(BIT4|BIT5|BIT6); /* Connect up SCLK. */ //P2SEL1 |= BIT2; //P2SEL0 &= ~BIT2; SLAVE_CS_DIR |= SLAVE_CS_PIN; SLAVE_CS_OUT |= SLAVE_CS_PIN; // Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings PM5CTL0 &= ~LOCKLPM5; } void SPI_initClockTo8MHz() { // Configure one FRAM waitstate as required by the device datasheet for MCLK // operation beyond 8MHz _before_ configuring the clock system. FRCTL0 = FRCTLPW | NWAITS_1; // Clock System Setup CSCTL0_H = CSKEY >> 8; // Unlock CS registers CSCTL1 = DCOFSEL_3 | DCORSEL; // Set DCO to 8MHz //CSCTL1 = DCOFSEL_4 | DCORSEL; // Set DCO to 16MHz CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK; CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; // Set all dividers CSCTL0_H = 0; // Lock CS registerss } //****************************************************************************** // SPI Interrupt *************************************************************** //****************************************************************************** #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=USCI_A1_VECTOR __interrupt void USCI_A1_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A1_ISR (void) #else #error Compiler not supported! #endif { uint8_t UCA1_rx_val = 0; switch(__even_in_range(UCA1IV, USCI_SPI_UCTXIFG)) { case USCI_NONE: break; case USCI_SPI_UCRXIFG: // Receive interrupt flag. UCRXIFG is set when UCAxRXBUF has received a complete character. UCA1_rx_val = UCA1RXBUF; UCA1IFG &= ~UCRXIFG; switch (MasterMode) { case TX_REG_ADDRESS_MODE: if (SPI_RXByteCtr) { MasterMode = RX_DATA_MODE; // Need to start receiving now //Send Dummy To Start receiving //__delay_cycles(20000); SendUCA1Data(DUMMY); } else { MasterMode = TX_DATA_MODE; // Continue to transmision with the data in Transmit Buffer //Send First SendUCA1Data(SPI_TransmitBuffer[SPI_TransmitIndex++]); SPI_TXByteCtr--; } break; case TX_DATA_MODE: //uartTxString("Enter TX_DATA_MODE \n"); if (SPI_TXByteCtr) { SendUCA1Data(SPI_TransmitBuffer[SPI_TransmitIndex++]); SPI_TXByteCtr--; } else { //Done with transmission MasterMode = IDLE_MODE; __bic_SR_register_on_exit(LPM3_bits); // Exit LPM3 } break; case RX_DATA_MODE: //uartTxString("Enter RX_DATA_MODE \n"); if (SPI_RXByteCtr) { SPI_ReceiveBuffer[SPI_ReceiveIndex++] = UCA1_rx_val; //Transmit a dummy SPI_RXByteCtr--; } if (SPI_RXByteCtr == 0) { MasterMode = IDLE_MODE; __bic_SR_register_on_exit(LPM3_bits); // Exit LPM3 } else { SendUCA1Data(DUMMY); } break; default: __no_operation(); break; } //__delay_cycles(1000); break; case USCI_SPI_UCTXIFG: break; default: break; } }