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's Timer A problem.

Other Parts Discussed in Thread: MSP430F5438A, MSP430F5438

Hi, I want that two LEDs blink at specific times using the compare module of the timer A of the MSP430F5438A.I was thinking use the up mode of the ccomparator.

 The program works great  when I use just one register ( In my case, the TA1CCTL0), but when I do the same, with other register, for example TA1CCTL0, the program just restart, I can not see why. if anybody can help me, I will really appreciate that. This is my code:

 

#include "msp430x54xA.h"

 

unsigned int i=0;

 

 

void main(void)

{

      WDTCTL = WDTPW + WDTHOLD;

      P1OUT = 0x00;

      P1DIR |= BIT0;

      P1DIR |= BIT1;

 

     //LEDs sequence

      P1OUT=0x01;

      for(i=15000;i>0;i--);

      P1OUT=0x02;

      for(i=15000;i>0;i--);

      P1OUT=0x01;

      for(i=15000;i>0;i--);

      P1OUT=0x02;

      for(i=15000;i>0;i--);

      P1OUT=0x00;

 

      P7SEL|=0x03;//XIN XOUT

 

      UCSCTL4=0;//ACLK

      UCSCTL5=0;

      UCSCTL6=18;

 

      TA1CCR0=32768;

      TA1CTL=0x116;// ACLK source, ACLK/1, up mode, ISR enable

      TA1CCTL0=16;

 //   TA1CCTL1=16;      if I uncomment this, the program just RESTART

 

      __bis_SR_register(GIE);     

      while(1);

}

 

 

 

#pragma vector=TIMER1_A0_VECTOR
__interrupt void TIMER1_A0_ISR(void)
{
    switch(TA1IV)
    {
        case 2:
        P1OUT ^= 0x02;
        break;
        
        case 14:
        P1OUT^=0x01;
        break;
        
        default:
        break;
    }
    TA1CTL=0x116;
}

 

#include "msp430x54xA.h"

 

unsigned int i=0;

 

 

void main(void)

{

      WDTCTL = WDTPW + WDTHOLD;

      P1OUT = 0x00;

      P1DIR |= BIT0;

      P1DIR |= BIT1;

 

     //LEDs sequence

      P1OUT=0x01;

      for(i=15000;i>0;i--);

      P1OUT=0x02;

      for(i=15000;i>0;i--);

      P1OUT=0x01;

      for(i=15000;i>0;i--);

      P1OUT=0x02;

      for(i=15000;i>0;i--);

      P1OUT=0x00;

 

      P7SEL|=0x03;//XIN XOUT

 

      UCSCTL4=0;//ACLK

      UCSCTL5=0;

      UCSCTL6=18;

 

      TA1CCR0=32768;

      TA1CTL=0x116;// ACLK source, ACLK/1, up mode, ISR enable

      TA1CCTL0=16;

 //   TA1CCTL1=16;     

 

      __bis_SR_register(GIE);     

      while(1);

}

 

 

 

#pragma vector=TIMER1_A0_VECTOR

__interrupt void TIMER1_A0_ISR(void)

{

  

      TA1CTL=0x116;

      P1OUT ^= 0x02;

}

  • Alejandro,

    Happy New Year and thanks for your question. I'm moving this thread to the MSP430 forum where you can get further help in this regard.

  • Alejandro de la Cadena said:

    #pragma vector=TIMER1_A0_VECTOR
    __interrupt void TIMER1_A0_ISR(void)
    {
        switch(TA1IV)
        ...

    You probably meant this ISR to use TIMER1_A1_VECTOR not TIMER1_A0_VECTOR

    With the code as-is, if you tried to use CCR1 or higher, you would get the TIMER1_A1 interrupt but there would be no handler for it.  This typically results in some kind of reset very quickly.

    Jeff

  • Jeff, I already did it:

    #pragma vector=TIMER1_A1_VECTOR
    __interrupt void TIMER1_A1_ISR(void)
    {
        switch(TA1IV)
    .......

    but when I do it, the program never go to the TIMER1_A1_VECTOR  :S, I can not understand why.

    When I was debugging, I noted that the GIE bit in the SR(Status Register) in certain moment, goes to 0, and I dont know how avoid that this happen.

    I am using the MSP-EXP430F5438 Experimenter Board, and I used 2 uC, to see if one of them was wrong, but the result is the same.

    Thanks!

  • Hi Alejandro,

    Please post your code again, but:

    - post only one version per post, and post the complete code

    - please use symbols from the TI header files (not numeric literals) for control register values and case statements

    If you can post your code this way, forum members will be able to help.

    Jeff

  • Hi,

    Notice that you have two interrupts enabled:


    TA1CTL=0x116; ----> Timer_A interrupt enable requires a handler for vector TIMER1_A1_VECTOR
    TA1CCTL0=16;  ----> Capture/compare CCR0 interrupt requires a handler for vector TIMER1_A0_VECTOR

    When you uncomment the code line bellow, you are activating one more interrupt source.
    //   TA1CCTL1=16; ----> Capture/compare CCR1 interrupt requires a handler for vector TIMER1_A1_VECTOR

    Another question: why do you include the code line bellow Inside the interrupt handler?
       TA1CTL=0x116;


    The GIE bit is disable inside the interrupt handler.

    Best regards,
    AES

  • Alejandro de la Cadena said:
     //   TA1CCTL1=16;      if I uncomment this, the program just RESTART

    Because, as Jeff already wrote, this will trigger a TIMER1_A1 interrupt, while TA1CCTL0 (and only TA1CCTL0) will trigger a TIMER1_A0 intterrup. And since you don't have an ISR for TIMER1_A1, thw processor jumps into the filed, rampaging through emmory that Isn't meant ot be executed and finally resets.

    However, in TIMER1_A1 ISR you'll need to manually reset the CCIFG bit, or the ISR will be called over and over again. For TA1CCR0, as it is the only possible interrupt source for TIMER1_A0 interrupt, it will be handled by the hardware.

    In any case, avoid something like "xxx = 16". Use the proper defines (e.g. CCIE), so it is clear what you want to do. Without having to look it up in the users guide.
    Code that uses numerical constants rather than defined values tends to be ignored by forum members, as it takes too much time to interpret it and leaves too much room for speculations about 'typo or intention'
    e.g: Did you really mean TA!CCTL1=16 (= CCIE) or did you really mean TA1CCTL1=0x16 (CCIE+OUT+COV)? And was TA1CTL=0x116 intentional or was it really meaning TA1CTL=0x16?

    By using the defines, it is clear that you switch the timer to ACLK, UP mode, clear it and enable the overflow interrupt. Which will after 65536 timer counts cause a TIMER1_A1 interrupt too (crashing your MSP without a proper ISR). However, since the CCR ISR will reset the tiemr, this will usually not happen ever.

    I guess, enabling the overflow interrupt was not your intention at all. It is not necessary to set TAIE to enable the capture interrupts of TA1CCRx. TAIE is a for completely separate interrupt reason.

    In any case, resetting the timer inside a CCR ISR is not a normal operation. For this purpose, the UP mode in conjuntion with TAxCCR0 is made: it counts up to CCR0 and then begins wth 0 again. No need to manually reset the timer. Doing so will only introduce a drift, as it resets the timer somewhere (probably a long time) after the CCR0 interrupt happened (at least for the ISR latency time and some code overhead on ISR entry, but maybe even longer if interrutps were temporarily disabled or a different ISR was running at the moment of the event). So when you finally arrive at the timer clear code, you lose some timer ticks that have already happened since the compare event.

  • Hi.

    I appreciate all your replies. I disabled the timer1 interrupt, changed the interrupt vector and the operation mode of the comparator from 'up mode' to 'continuos mode', and it works as I want.

    ****Configuration:

        TA1CCR2=32768;
        TA1CCR1=3176;

        TA1CCTL1=16;
        TA1CCTL2=16;
        TA1CTL=0x124;
      __bis_SR_register(GIE);

    ****Interrupt:

    #pragma vector=TIMER1_A1_VECTOR

    __interrupt void TIMER1_A1_ISR(void)

    {

       switch(TA1IV)

        {

                case 14:

                break;

                 case 4:

                P1OUT^=0x01;

                TA1CCTL2=16;

                TA1CTL=0x126;//TA1R reset

                break;

                 case 2://CCR1

                P1OUT ^= 0x02;

                TA1CCTL1=16;//

               break;

               default:break;

        }

      __bis_SR_register(GIE);

    }

    *********

    It was using the XT1CLOCK (with a 32768Hz crystal) as clock source for the TIMER1. I tried to use the XT2CLOCK instead XT1CLOCK as source for the ACLK, with a 4MHz crystal, I configured the unified clock system as I'll show:

    ******UCS configuration (I dont know how to do what you recommend me, but I''ll comment the code, Jens-Michael Gross):

        P5SEL|=0x0C;//P5.2 and P5.3 as XT2IN and XT2OUT respectively

        UCSCTL4=0x555;//ACLK's source: XT2
        UCSCTL5=0;//ACLK/1
        UCSCTL6=0x0;//no bypass
    ******

    I expected that the led blink were faster, but it wasnt. I think that the XT2 is ignored.

    I dont know if there are more considerations to make the XT2 works. Greetings!



  • Alejandro de la Cadena said:
    (I dont know how to do what you recommend me, but I''ll comment the code

    In the users guide, all bits (o rbitfields) inside a register got a name.

    If the name of a bit is just 'CCIE', then you can use this name for the assignment.
    register = CCIE; or register |= CCIE (to just set this single bit) or register &= ~CCIE (to clear the bit).

    These symbols are defined along with the register names in the header files.

    Bitfields (more than one bit) have defines like xxx_n where n is an enumeration (0..7 for 3-bit fields etc). And usually there is an even a more telling version too.

    You can combine more than one assignment in one instruciton.

    UCSCTL4 = 0x555 then turns into
    UCSCTL4 = SELA_5 | SELS_5 | SELM_5;
    or (even more descriptive)
    UCSCTL4 = SELA_XT2CLK | SELS_XT2CLK | SEM_XT2CLK;

    which is (except for bugs in the header file) error-proof and easily to interpret.

    Alejandro de la Cadena said:
    I think that the XT2 is ignored.

    This can have several reasons. Maybe you have the wrong capacitors? (HF XTAL requires external capacitors, whilw LF on XT1 doesn't - however, writing 0 to UCSCTL6 sets the XT1 internal capacitors to 0, effectively stopping the 32kHz crystal too.

  • hey,

    i am using msp430f5438 controller and trying to make simple timer but it can not go in interrupt subroutine.

    so please help me for that.

    my code is,


    #include "io430.h"
    #include "intrinsics.h"

    void set_clock()
    {
     // UCSCTL0=0x1F00;   //dcox=31, modx=0
      //UCSCTL1=0X0051;   //dcorselx=0
      //UCSCTL2=0X20FF;   //d=1;,flln=3
      //UCSCTL3=0X0020;   //fll ref. frequency and devider
      UCSCTL4=0X0222;   //source for all clock signal
      //UCSCTL5=0X0000;   //clock divider for all clock signal==1
      UCSCTL6=0X0103;   //xt1 and xt2 off smclk on
      //UCSCTL7=0X7000;   //warning enable.interupt enable
    }


    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void TIMER0_A0()
    {
       P10OUT = 0X80;
    }





    void SET_TIMER()
    {
       TA0CCR0 = 500-1;
       TA0CTL = MC_1  + TASSEL_2; //clock smclk and up mode
       TA0CCTL0 = CCIE;
      __bis_SR_register(GIE);
      __enable_interrupt();
    }


    int main( void )
    {
      // Stop watchdog timer to prevent time out reset
      WDTCTL = WDTPW + WDTHOLD;
      set_clock();
      SET_TIMER();
      while(1){}
      return 0;
    }


    if i use simulator for timer interrupt then it goes in interrupt routine finly..........

  • HARDIK DAVE said:
    UCSCTL6=0X0103;   //xt1 and xt2 off smclk on

    No, it actually sets the SMCLKOFF bit (0x0002) and therefore your SMCLK is off and the timer is not clocked. I tlooks like the simulator does not support this bit and therefore the code seems to work in the simulator.

**Attention** This is a public forum