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.

MSP430F5438A as SPI slave using UCB2 SPI problem



Hi to all! I'm trying to develop an SPI slave. The purpose is the following: The MSP430 is a sensor module and comunicate via SPI with an ARM processor (SPI master). The MSP430 use a GPIO like an alert for ARM. In that case the ARM starts the SPI communication and the MSP430 enter into the SPI interrupt.

The code for example is the following

#include "main.h"
#include <msp430.h>

void main()
{
  WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
  
  while(!(P9IN & BIT3));  // If clock sig from mstr stays low // it is not yet in SPI mode
  
  P9SEL |= 0x0e;    // UCLK,SOMI,SIMO=FUNC, all other=GPIOs (9.1,9.2,9.3)

  /*GPIOS LED y ALERT*/
  /*---------------------------------*/
  P9DIR |= BIT7;
  P8DIR |= BIT6;   //LED
  /*---------------------------------*/
  
  UCB2CTL1 |= UCSWRST;       // Put the state machine in reset

  UCB2CTL0  |= UCSYNC+UCCKPL+UCMSB;  // 3-pin, 8-bit SPI slave,
                                     // Clock polarity high, MSB 
 
  UCB2CTL1 &= ~UCSWRST;         // **Initialize USCI state machine** 
  UCB2IE |= UCRXIE;             // Enable USCI_B2 RX interrupt
  
  __bis_SR_register(LPM4_bits + GIE);       // Enter LPM4, enable interrupts

  
  for(;;)
  {
    volatile unsigned int i;
    P8OUT ^= BIT6;
    P9OUT ^= BIT7;      // Toggle
    
    
    i = 50000;         // Delay
    do (i--);
    while (i != 0);
    i = 50000;         // Delay
    do (i--);
    while (i != 0);
  }
}


#pragma vector = USCI_B2_VECTOR
__interrupt void USCI_B2_ISR(void)
{
  switch(__even_in_range(UCB2IV,4))         // Interrupt vector register
  {
  case 0:break;                             // No interrupt   
  case 2:                                     // Vector 2 - RXIFG
      while (!(UCB2IFG&UCTXIFG));             // USCI_B2 TX buffer ready?
      UCB2TXBUF = 0x0F;
      break;
  case 4:                                  // Vector 4 - TXIFG
    break;
  default:
    break;
  }
}

---------------------------------------------------------------------------------------------

The program is blocked in the line of toggles the GPIOS.  I can't find information to solve it.

If anything is wrong in my code, please tell me. Thanks!

  • Pablo del Campo said:
    The program is blocked in the line of toggles the GPIOS. 

    Actually not. It is stopped in the line before. But since the debugger breakpoint is triggered at instruction fetch, not on instruction execution, it stops in the next line.

    Pablo del Campo said:
    __bis_SR_register(LPM4_bits + GIE); // Enter LPM4, enable interrupts

    THis line enters LPM4. This means, the CPU is stopped (the very moment it has fetched the next instruction, which is the toggle), and the clocks are deactivated.

    Only the ISR will be executed (in case of an interrupt). Since the ISR never ends the LPM, the main code won't be executed.

    If you want main to continue working again, the ISR must call an exit intrinsic, such as _bic_SR_register_on_exit(LPM4_bits), Otherwise, the CPU will stop again when the ISR exits.

  • A lot of thanks for your fast answer Jens-Michael Gross.

    I noticed it after post the thread. My real problem now is with the code at the end of this post (the slave code), I get the following signal.

    My question is, why the MISO line keeps in high level after the communication, is all correct?


    If I use cnt=UCB2TXBUF instead cnt++ the output has no sense. Why it occurs? It should be the same that the entry, right?

    The code is

    #include "main.h"
    #include <msp430.h>
    
    unsigned char cnt=1;
    
    void main()
    {
      WDTCTL = WDTPW + WDTHOLD;     // Stop watchdog timer
      
      /*GPIOS LED, ALERT*/
      /*---------------------------------*/
      P9DIR |= BIT7;  
      P8DIR |= BIT6;
      /*---------------------------------*/
        
      P9SEL |= (BIT1 + BIT2 + BIT3); //0x0e;    /* UCLK,SOMI,SIMO, SC, y Alert=FUNC, all other=GPIOs
      
      P9DIR |=  BIT2;                         // SOMI (output)  
      P9DIR &= ~BIT1;                            // SIMO (input)
      P9DIR &= ~BIT3;                            // CLK_IN
      
      while(!(P9IN & BIT3));      
    
      UCB2CTL1 |= UCSWRST;              // Put the state machine in reset
          
      UCB2CTL0 |= UCMSB + UCSYNC;  // 3-pin, 8-bit SPI slave MSB first
      
      UCB2CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine** 
      
      UCB2IE |= UCRXIE;     // Enable USCI_B2 RX interrupt
    
      __enable_interrupt();
    
      unsigned int i;
      
      for(;;)
      {
        P8OUT ^= BIT6;
        P9OUT ^= BIT7; //P8OUT ^= BIT6;      // Toggle using exclusive-OR
        
        i = 50000;                          // Delay
        do (i--);
        while (i != 0);
        i = 50000;                          // Delay
        do (i--);
        while (i != 0);
      }
    }
    
    
    #pragma vector = USCI_B2_VECTOR
    __interrupt void USCI_B2_ISR(void)
    {
      switch(__even_in_range(UCB2IV,4))         // Interrupt vector register
      {
      case 0:break;                             // No interrupt   
      case 2:                                     // Vector 2 - RXIFG
          //while (!(UCB2IFG&UCTXIFG));            
          UCB2TXBUF = cnt;
          cnt++;
          break;
      case 4:                                  // Vector 4 - TXIFG
        break;
      default:
        break;
      }
    }
    

    Please if anyone can help me I will be very grateful. A lot of thanks.

  • Pablo del Campo said:
    My question is, why the MISO line keeps in high level after the communication, is all correct?

    Because the last bit was a '1'. If the last bit had been a '0' then the MISO line would be low after the transfer. The MISO is driven by the output of the shift register, and after the last clock edge it stops shifting, so last bit stays on the output. In fact, it must be this way, because the slave has no idea when the master is going to sample that bit. It could be anytime between the positive clock edge and the next positive clock edge. (Typically it happens at the negative clock edge, but that's not a hard rule)

    Pablo del Campo said:
    If I use cnt=UCB2TXBUF instead cnt++ the output has no sense. Why it occurs? It should be the same that the entry, right?

    I guess that depends on what the MSP430 does to the TXBUF register when it reads it. What do you expect to see and what do you actually see? I think I would expect the MSP430 implementation to be what was last written there since it doesn't have a FIFO mode.

  • Brian Boorman said:

    If I use cnt=UCB2TXBUF instead cnt++ the output has no sense. Why it occurs? It should be the same that the entry, right?

    I guess that depends on what the MSP430 does to the TXBUF register when it reads it. What do you expect to see and what do you actually see? I think I would expect the MSP430 implementation to be what was last written there since it doesn't have a FIFO mode.

    [/quote]

    Sorry I want to say cnt=UCB2RXBUF. If I use cnt= UCB2RXBUF, the SOMI line must be the previous byte sent by the Master but it isn't and has no sense.

    my other problem is while I am sending a array (in this case and array of 4 bytes) the first two bytes are repeated and in the first array the first byte must be "0x01" but it is 0x00.

    This is the first array, as you can see the first byte must be "1" but it's double zero.

    The second arrive must be start with "3" due to the first arrray finished with "2" but it's double four.


    Why it occurs?

    A last question if I use the line while (!(UCB2IFG&UCTXIFG)); in the case 2 of the interrupt it freeze the device after the first array. Why?

    PD: The code for the MSP430 Slave is the following

    #include "main.h"
    #include <msp430.h>
    
    unsigned char cnt=1;
    
    void main()
    {
      WDTCTL = WDTPW + WDTHOLD;     // Stop watchdog timer
      
      /*GPIOS LED y ALERT*/
      /*---------------------------------*/
      P9DIR |= BIT7;  
      P8DIR |= BIT6;
      /*---------------------------------*/
        
      P9SEL |= (BIT0+BIT1 + BIT2 + BIT3); //0x0e;    /* UCLK,SOMI,SIMO, SC, y Alert=FUNC, all other=GPIOs
      
      P9DIR |=  BIT2;                         // SOMI (output)  
      P9DIR &= ~BIT1;                            // SIMO (input)
      P9DIR &= ~BIT3;                            // CLK_IN
      P9DIR &= ~BIT0;                          //SC input
      
      while(!(P9IN & BIT3));                  // If clock sig from mstr stays low,it is not in SPI mode
    
    
      UCB2CTL1 |= UCSWRST;              // Put the state machine in reset
          
      UCB2CTL0 |= UCMSB + UCSYNC+UCMODE_2; // 3-pin, 8-bit SPI slave MSB first
    
      UCB2CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine** 
      
      UCB2IE |= UCRXIE;     // Enable USCI_B2 RX interrupt
      
      __enable_interrupt();
    
      unsigned int i;
      
      for(;;)
      {
        P8OUT ^= BIT6;
        P9OUT ^= BIT7; //P8OUT ^= BIT6;      // Toggle using exclusive-OR
           
        i = 50000;                          // Delay
        do (i--);
        while (i != 0);
        i = 50000;                          // Delay
        do (i--);
        while (i != 0);
      }
    }
    
    #pragma vector = USCI_B2_VECTOR
    __interrupt void USCI_B2_ISR(void)
    {
      switch(__even_in_range(UCB2IV,4))         // Interrupt vector register
      {
      case 0:break;                             // No interrupt   
      case 2:                                     // Vector 2 - RXIFG
          //while (!(UCB2IFG&UCTXIFG));             // USCI_B2 TX buffer ready? 
          
          UCB2TXBUF = cnt;
          cnt++;
          //cnt=UCB2RXBUF;
          
          break;
      case 4:                                  // Vector 4 - TXIFG
        break;
      default:
        break;
      }
    }
    

**Attention** This is a public forum