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.

CCS/MSP430FR2355: issues about spi communication

Part Number: MSP430FR2355
Other Parts Discussed in Thread: MSP430G2553

Tool/software: Code Composer Studio

Hello, I'm implementing SPI communication using msp430fr2355, I need this in order to interface a CAN controller. I'm using examples from resource explorer for my SPI driver, and I'm using drivers

I've already implemented using msp430g2553 to program the controller and the CAN communication, so I just need to port my SPI driver for the new microcontroller (msp430fr2355)

This is my code for SPI driver:

unsigned char tx_a0_data;
unsigned char rx_a0_data;


void SPI_init()
{
    P1SEL0 |= BIT5 | BIT6 | BIT7;                                                 // set 3-SPI pin as second function

    UCA0CTLW0 |= UCSWRST;                                                         // **Put state machine in reset**
    UCA0CTLW0 |= UCMST|UCSYNC|UCCKPL|UCMSB;                                       // 3-pin, 8-bit SPI master
                                                                                  // Clock polarity high, MSB
    UCA0CTLW0 &= ~UCSSEL_1;
    UCA0CTLW0 |= UCSSEL__SMCLK;                                                   // Select SMCLk = 24Mhz
    UCA0BR0 |= 24;                                                              //Transmission clock 1Mhz
    UCA0BR1 = 0;                                                                  // .-

    UCA0MCTLW = 0;                                                                // No modulation
    UCA0CTLW0 &= ~UCSWRST;                                                        // **Initialize USCI state machine**
    UCA0IE |= UCRXIE;     
}

unsigned char SPI_transmit(unsigned char data)
{
    tx_a0_data = data;
    UCA0IE |= UCTXIE;                                                                 // Enable TX interrupt
    return rx_a0_data;   
}

#pragma vector=EUSCI_A0_VECTOR
__interrupt void USCI_A0_ISR (void)
//interrupt [UART0TX_VECTOR] void UART0_TX_ISR (void)
{ //ToDo: Generalize this interruptions
    
    switch(__even_in_range(UCA0IV,USCI_SPI_UCTXIFG))
    {
        case USCI_NONE:
             break;                    // Vector 0 - no interrupt
        case USCI_SPI_UCRXIFG:
            rx_a0_data = UCA0RXBUF;
            UCA0IFG&=~UCRXIFG;
            break;
        case USCI_SPI_UCTXIFG:
            UCA0TXBUF = tx_a0_data;
            UCA0IE &= ~UCTXIE;
            break;
        default: break;

    }

}

I have a question in this code, specifically about the spi clock configuration, I have the microcontroller's clock configured like this:

void init_clock(void)
{
    /// Configure two FRAM waitstate as required by the device datasheet for MCLK
    // operation at 24MHz(beyond 8MHz) _before_ configuring the clock system.
    FRCTL0 = FRCTLPW | NWAITS_2 ;

    P2SEL1 |= BIT6 | BIT7;                       // P2.6~P2.7: crystal pins
    do
    {
        CSCTL7 &= ~(XT1OFFG | DCOFFG);           // Clear XT1 and DCO fault flag
        SFRIFG1 &= ~OFIFG;
    } while (SFRIFG1 & OFIFG);                   // Test oscillator fault flag

    __bis_SR_register(SCG0);                     // disable FLL
    CSCTL3 |= SELREF__XT1CLK;                    // Set XT1 as FLL reference source
    CSCTL0 = 0;                                  // clear DCO and MOD registers
    CSCTL1 |= DCORSEL_7;                         // Set DCO = 24MHz
    CSCTL2 = FLLD_0 + 731;                       // DCOCLKDIV = 24MHz
    __delay_cycles(3);
    __bic_SR_register(SCG0);                     // enable FLL
    while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));   // FLL locked

    CSCTL4 = SELMS__DCOCLKDIV | SELA__XT1CLK;   // set XT1 (~32768Hz) as ACLK source, ACLK = 32768Hz
                                                 // default DCOCLKDIV as MCLK and SMCLK source
//    P1DIR |= BIT0 | BIT1 ;                       // set ACLK SMCLK and LED pin as output
//    P1SEL1 |= BIT0 | BIT1;                             // set ACLK and  SMCLK pin as second function
}

I understand my SMCLK is 24Mhz, so in the code above, my spi clock is configured for 1Mhz. Is it correct?

I'm trying to do the same configuration I had with the msp430g2553, this was the code in that case:

void init_CLK(){

    BCSCTL1 = CALBC1_8MHZ;                                                      //BCSCTL1 Calibration Data for 1MHz
    DCOCTL = CALDCO_8MHZ;                                                       //DCOCTL  Calibration Data for 1MHz
    BCSCTL2|=SELM0+DIVM_0;                                                      //MCLK sourced from DCO DIV/1
    BCSCTL2&=~SELS;                                                             //SMCLK sourced from DCO
    BCSCTL2=DIVS_2;                                                             //SMCLK DIV/4
}

void msp430_SPI_init(uint8_t USCIX)
{
    UCA0CTL0=0x00;                                                                // Clear the contents of the register
                                                                                  //using USCI A0 (Universal Serial Communication Interface)
    UCA0CTL1 |= UCSWRST;                                                          // Reset
    UCA0CTL0 |= UCCKPH + UCMST + UCMODE_0 + UCSYNC;                               // 3-pin, 8-bit SPI master

    UCA0CTL0|=UCMSB;                                                              //MSB FIRST
    UCA0CTL0&=~UC7BIT;                                                            // Data for 8 Bit

    UCA0CTL1 = 0x00;                                                               // Clear content of register
    UCA0CTL1 |= UCSSEL_2;                                                          // SMCLK
    UCA0CTL1 &= ~UCSWRST;                                                          // Initialize USCI state machine

    UCA0BR0 |= 0x02;                                                               //Transmission clock SMCLK / 2
    UCA0BR1 = 0;                                                                   // .-

    // No modulation
    IE2|= UCA0RXIE + UCA0TXIE;                                                     //USCI_A0 receive/transmit interrupt enable
    IFG2 &=~UCA0TXIFG;                                                             //clear flag, no Interrupt pending

    P1SEL  = BIT1 | BIT2 | BIT4;                                                   // P1.1 SOMI - P1.2 SIMO - P1.4 SCK
    P1SEL2 = BIT1 | BIT2 | BIT4;
}

I understand in that case, the SMCLK was configured to work at 8Mhz/4 and finally spi clock in 1Mhz. Then the configurations of spi clock for both microcontrollers 

would be the same. Is this right or am I doing or understanding something wrong in the configurations?

The CAN controller is programmed via SPI. Right now, my CAN communication is not working with the msp430fr2355 then I suppose my SPI driver is not working and I'm not able to program the controller correctly.

I hope you can help me, thanks in advance.

Regards,

Diana 

  • Your register initialization is suspect. Starting with ORing in the bits to CTLW0. Not all of bits in that register default to zero out of reset. In particular both clock select bits start as 1s. Then you clear one and set something else. Far too easy to get something unexpected that way. Make life simple by simply setting the entire register to zero when set the reset bit. Then OR in the settings you want.

    Then there is the bit rate divider. A sixteen bit register that you access as two bytes. Are you dividing SMCLK by 24 or by 24<<8? Use UCA0BRW  = 24  and avoid the confusion. The interrupts appear to be a wasted effort here since there is no buffering of data and the result is the same as using a simple polled transmit/receive function. (Write data to TXBUF, wait for RXIFG, read RXBUF.)

  • Hello David, thank you very much for your answer. 

    This is my code with the changes I understood from your answer:

    void SPI_init()
    {
        P1SEL0 |= BIT5 | BIT6 | BIT7;                                                 // set 3-SPI pin as second function
    
        UCA0CTLW0 |= UCSWRST;                                                         // **Put state machine in reset**
        UCA0CTLW0 &= 0x00;
        UCA0CTLW0 |= UCMST|UCSYNC|UCCKPL|UCMSB|UCSSEL__SMCLK;                         // 3-pin, 8-bit SPI master
                                                                                      // Clock polarity high, MSB
        UCA0BRW = 24;
    
        UCA0MCTLW = 0;                                                                // No modulation
        UCA0CTLW0 &= ~UCSWRST;                                                        // **Initialize USCI state machine**
        UCA0IE |= UCRXIE;                                                             // Enable USCI_A0 RX interrupt
    }

    I'm not sure with the code for transmission, this is my code but I don`t know if I'm using the correct registers:

    unsigned char SPI_transmit(unsigned char data)
    {
        UCA0TXBUF = data;
        //UCA0IE |= UCTXIE;                                                                 // Enable TX interrupt
        while(UCA0STATW & UCBUSY);
        return UCA0RXBUF; 
    } 

    I still have the same results, my CAN communication is not working.

    I'll hope for your answer, thanks again.

    Diana

  •  UCA0CTLW0 |= UCSWRST;                                                         // **Put state machine in reset**
        UCA0CTLW0 &= 0x00;

    Will not work because you clear the reset bit. Many of the settings you change after this point can only be changed when iti is set. Drop the useless  OR and simply use: UCA0CTLW0 = UCSWRST;

  • Hi David, thanks again for your support and sorry for my inexperience .

    I made the changes in my code and now my SPI initialization code is like this: 

    P1SEL0 |= BIT5 | BIT6 | BIT7;                                                 // set 3-SPI pin as second function
    
    UCA0CTLW0 = UCSWRST;                                                         // **Put state machine in reset**
    
    UCA0CTLW0 |= UCMST|UCSYNC|UCCKPL|UCMSB|UCSSEL__SMCLK;                         // 3-pin, 8-bit SPI master
                                                                                              // Clock polarity high, MSB
    UCA0BRW = 24;
    
    UCA0MCTLW = 0;                                                                // No modulation
    UCA0CTLW0 &= ~UCSWRST;                                                        // **Initialize USCI state machine**
    UCA0IE |= UCRXIE;                                                             // Enable USCI_A0 RX interrup

    I still don't have results, can you tell  me if my transmit function is ok?

    UCA0TXBUF = data;
    while(UCA0STATW & UCBUSY);
    return UCA0RXBUF;                                                               // return the register received
    

    thanks for your help,

    Diana

  • I've already solved the problem, CAN communication wasn't working because of transceiver configuration and not the controller.

    Also, the code above for initialization and transmission is working well. Thank you very much!!

**Attention** This is a public forum