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.

MSP430F5529: MSP430F5529 TIMER_A AND USCI_A0 INTERRUPTS

Part Number: MSP430F5529
Other Parts Discussed in Thread: MSP430FR6989

Hey guys,

I have conflict problems in my RS232 serial USCI_A0 when I use TIMER2_A1 at the same time.

While TIMER2_A1 is off, USCI_A0 works normally. If TIMER2_A1 is turned on, USCI_A0 starts to fail serial communication and becomes unstable.

I'm using the MSP430F5529 with revision "H"... latest revision "K"...don't know if this could be a problem?

I've seen other reports of this same problem on other MSP430s, but they weren't entirely conclusive.

I've been trying to understand and solve this problem for days!

Here's a snippet of the configuration:

void initRS232(void)
{  
   P3SEL = BIT3+BIT4;                                                           // P3.4,5 = USCI_A0 TXD/RXD
   UCA0CTL1 |= UCSWRST;                                                         // **Put state machine in reset**
   UCA0CTL1 |= UCSSEL_1;                                                        // CLK = ACLK
   UCA0BR0 = 0x03;                                                              // 32kHz/9600=3.41 (see User's Guide)
   UCA0BR1 = 0x00;                                                              //
   UCA0MCTL = UCBRS_3+UCBRF_0;                                                  // Modulation UCBRSx=3, UCBRFx=0
   UCA0CTL1 &= ~UCSWRST;                                                        // **Initialize USCI state machine**
   UCA0IE |= UCRXIE;                                                            // Enable USCI_A0 RX interrupt
}

.....

TA2CCR0 = 32767;                                                                    // Inicializa o Registro do TimerA2 com 1 segundo
TA2CTL = TASSEL_1 + MC_1 + TACLR + TAIE;                                            // Habilita o Controle Manual da VRP via Timer_A2(ACLK, cont. mode, interrupt)

.....

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{   
   switch(__even_in_range(UCA0IV,4))
     {
        case 0:break;                                                           // Vector 0 - no interrupt
        case 2:                                                                 // Vector 2 - RXIFG
                 Caracter_0 = UCA0RXBUF;                                        // Recebe o Dado da Serial,
                 BufferRX[IndexBuf] = Caracter_0;                               // Guarda o caracter no buffer.
  
                 if ( BufferRX[IndexBuf] == '*' )                               // Se é o Fim da String de Comando?
                   {
                      BufferRX[IndexBuf+1] = '\0';                              // Finaliza sting.
                      IndexBuf = 0;                                             // Reseta a Variável IndexBuf        
                      CHEGOU_COMANDO = TRUE;                                    // Se Recebeu Algum Dado via Serial RS232 Habilita Checagem de Comando.
                   }
                 else
                   {
                      IndexBuf++;                                               // Incrementa as Strings Recebidas
                   }
  
                 if ((BufferRX[0] != '>' ) || (IndexBuf >= MAX_BUFFER))         // Se Não Inicializar com ">" e Não se IndexBuf for Maior que Max Buffer
                   {
                      IndexBuf = 0;                                             // Reseta a Variável IndexBuf
                   }
        break;
        case 4:  break;                                                         // Vector 4 - TXIFG
        default: break;
     } 
}

......

// Timer2_A1 Interrupt Vector (TAIV) handler
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER2_A1_VECTOR
__interrupt void TIMER2_A1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER2_A1_VECTOR))) TIMER2_A1_ISR (void)
#else
#error Compiler not supported!
#endif
{
   switch(__even_in_range(TA2IV,14))
     {
        case  0: break;                                                         // No interrupt
        case  2: break;                                                         // CCR1 not used
        case  4: break;                                                         // CCR2 not used
        case  6: break;                                                         // reserved
        case  8: break;                                                         // reserved
        case 10: break;                                                         // reserved
        case 12: break;                                                         // reserved
        case 14: 
                 Temporiza_1_segundo = Temporiza_1_segundo + 1;                 // Temporiza 1 Segundo++;                                                  // Temporiza 1 Segundo
                 Monitora_Pressao_Saida++;                                      // Monitoramento de Pressão de Saída 1 Segundo
                 
                 if (Temporiza_1_segundo == Intervalo_Controle)                 // Se Temporiza 1 Segundo = Intervalo Controle?
                   {
                      Temporiza_1_segundo = 0;                                  // Reseta a Variável Temporiza 1 segundo
                      
                      if (Controle_Baixa == 1)                                  // Se Controle de Pressão Baixa?
                        {
                           PORTA_P8OUT |= G2012_S32;                            // Habilita o Circuito da Válvula Solenóide de Entrada
                           delay_ms(5);                                         // Periodo de Tempo da Válvula Solenóide de Entrada Aberta
                           PORTA_P8OUT &=~ G2012_S32;                           // Desabilita o Circuito da Válvula Solenóide de Entrada
                        }
                      else
                        {
                           if (Controle_Alta == 1)                              // Se Controle de Pressão Alta?
                             {
                                PORTA_P8OUT |= G2012_S31;                       // Habilita o Circuito da Válvula Solenóide de Saída
                                delay_ms(5);                                    // Periodo de Tempo da Válvula Solenóide de Saída Aberta
                                PORTA_P8OUT &=~ G2012_S31;                      // Desabilita o Circuito da Válvula Solenóide de Saída
                             }
                        }
                  }
        break;
        default: break; 
     }
}

  • >  delay_ms(5); // Periodo de Tempo da Válvula Solenóide de Entrada Aberta

    At 9600bps, 5ms is 5 byte times. If your data is arriving in a burst (bytes back-to-back), the UART will overrun and some of the bytes will be lost.

    You need to find a way to do this (presumed) spin-loop outside the ISR, maybe by using another timer.

  • I'm using all timers in this project. Each one with their occupation! I have no other Timer left to implement the delay.

    Unless it can be done with WDT?

    I saw something with WDT for bounce.

    Code snippet with WDT just below:

    I don't want to have to migrate to MSP430FR6989 for now until I know if the project with MSP430F5529 is possible.

    /***************************************************************************//**
     * @brief  Sets up the WDT as a button debouncer, only activated once a
     *         button interrupt has occurred.
     * @param  none
     * @return none
     ******************************************************************************/
    
    void Buttons_startWDT()
    {
        // WDT as 250ms interval counter
        SFRIFG1 &= ~WDTIFG;
        WDTCTL = WDTPW + WDTSSEL_1 + WDTTMSEL + WDTCNTCL + WDTIS_5;
        SFRIE1 |= WDTIE;
    }
    
    /***************************************************************************//**
     * @brief  Handles Watchdog Timer interrupts.
     *
     *         Global variables are used to determine the module triggering the
     *         interrupt, and therefore, how to handle it.
     * @param  none
     * @return none
     ******************************************************************************/
    
    #pragma vector=WDT_VECTOR
    __interrupt void WDT_ISR(void)
    {
        if (buttonDebounce == 2)
        {
            buttonDebounce = 1;
    
            SFRIFG1 &= ~WDTIFG;
            SFRIE1 &= ~WDTIE;
            WDTCTL = WDTPW + WDTHOLD;
        }
    }
    

  • Yes, you can use the WDT as an extra timer (WDTTMSEL=1). It's fairly low function, though.

    In particular, it has only 8 possible clock divisors. Glancing at the WDTIS definition [Ref user guide (SLAU208Q) Table 16-2] with ACLK=32kHz you can only get 2ms or 15.6ms, not 5ms.

    SMCLK (WDTSSEL=00) might work better, depending on how fast you have that running.

  • Hey guys,

    I managed to configure the WDT, which I was not able to!

    Any ideas how to make the WDT in the delay function?

    Any code as an example for me to study?

    Thanks!

  • The TI Examples on Resource Explorer show some fairly straightforward usage cases:

    https://dev.ti.com/tirex/explore/node?node=ACt.3NsUP.t3V3gtuC8DhQ__IOGqZri__LATEST

    Examples MSP430F55xx_WDT_01.c/_02.c are probably relevant.

**Attention** This is a public forum