• Join
  • Sign In with my.TI Login
Texas Instruments
  • Products
  • Applications
  • Tools & Software
  • Support & Community
  • Sample & Buy
  • About TI
Sample & Purchase Cart Sample & Purchase Cart
  • Search
  • Advanced
TI E2E™ Community
  • Support Forums
  • Blogs
  • Groups
  • Videos
  • 简体中文
  • More ...
TI Home » TI E2E Community » Support Forums » Microcontrollers » MSP430™ Microcontrollers » MSP430 Ultra-Low Power 16-bit Microcontroller Forum » Using CCR0 & CCR1 for Timer A0 using MSP430G2553
Share
MSP430™ Microcontrollers
  • Forum
  • Announcements
  • E2E Wiki
Options
  • Subscribe via RSS
MSP430 Resources
  • MSP430 Product Folder
  • MSP-EXP430G2 - MSP430 LaunchPad Value Line Development kit
  • MSP430 Getting Started Guide
  • MSP430 Microcontroller Projects
  • More Resources >
  • Using CCR0 & CCR1 for Timer A0 using MSP430G2553

    Using CCR0 & CCR1 for Timer A0 using MSP430G2553

    This question is answered
    Jonathan Hunter1
    Posted by Jonathan Hunter1
    on Aug 19 2012 16:26 PM
    Prodigy140 points

    I have been trying to get my code to run two functions at different intervals.  I want my UART update to happen at about every 200ms and my SPI commands to about every 5ms.  CCR0 works for me, but CCR1 does not.  Both functions execute but CCR1 seems to execute as quickly as possible while CCR0 executes about every 200ms.  Can anyone see what I am missing here?

    #include

    <msp430.h>

    #define

    MYTRUE 1

    #define

    MYFALSE 0

    #define

    numcycles 10

    #define

    update_delay 2620//1310 //0

    #define

    page_write 3000 //5

    #define

    recharge_cycles 3000000

    extern void CSL_init(void);

    void adc2asciidec(unsigned long anum);

    void

    adc2asciihex(unsigned long anum);

    unsigned

    char MST_Data, SLV_Data;

    volatile

    unsigned int i;

    float

    curr_V;

    unsigned

    long device_id;

    unsigned

    long charge_cnt;

    unsigned

    long bytes_wr;

    int

    first_run;

    unsigned

    char digit[16];

    unsigned

    long lnum;

    char

    lnum2;

    void

    main(int argc, char *argv[])

    {

    CSL_init();

    //confirmation copy

    WDTCTL = WDTPW + WDTHOLD;

    UCA0CTL1 |= UCSWRST;

    UCB0CTL1 |= UCSWRST;

    ADC10CTL0 &= ~ENC;

    UCB0CTL0 =

    /*UCCKPL +*/ UCCKPH + UCMSB + UCMST + UCMODE_0; //+ UCSYNC;

    ADC10CTL0 = ADC10IE + ADC10ON +

    /*REFON +*/ ADC10SHT_3 + SREF_0;

    UCA0CTL1 = UCSSEL_2 + UCSWRST;

    UCB0CTL1 = UCSSEL_2 + UCSWRST;

    ADC10CTL1 = CONSEQ_0 + ADC10SSEL_0 + ADC10DIV_3 + SHS_0 + INCH_0;

    UCA0MCTL = UCBRF_0 + UCBRS_1;

    UCA0BR0 = 104;

    //64;

    UCA0BR1 = 0;

    //3;

    UCB0BR0 |= 0x1;

    UCB0BR1 = 0;

    ADC10CTL0 |= ENC;

    UCA0CTL1 &= ~UCSWRST;

    UCB0CTL1 &= ~UCSWRST;

    P2OUT = BIT0;

    P1SEL = BIT1 + BIT2 + BIT5 + BIT6 + BIT7;

    P1SEL2 = BIT1 + BIT2 + BIT5 + BIT6 + BIT7;

    P1DIR = BIT3 + BIT4;

    P2DIR = BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7;

    P1IES = 0;

    P1IFG = 0;

    P2IES = 0;

    P2IFG = 0;

    IFG2 &= ~(UCA0RXIFG + UCB0RXIFG);

    IE2 |= UCA0RXIE;

    IE2 |= UCB0TXIE;

    IE2 |= UCB0RXIE;

    TA0CCTL0 = CCIE;

    TA0CCTL1 = CCIE;

    TA0CCR0 = update_delay;

    TA0CCR1 = page_write;

    TA0CTL = TASSEL_1 + MC_1 + TAIE;

    // ACLCK, 1/8 DIVIDER, upmode to TCCR0 value

    charge_cnt = 0;

    bytes_wr = 0;

    lnum2 = 0x01;

    first_run = MYFALSE;

    P2OUT |= BIT1;

    // Vdd

    __delay_cycles(recharge_cycles);

    // Wait for slave to initialize

    P2OUT &= ~BIT1;

    // Vdd

    for(;;){

    __bis_SR_register(LPM0_bits + GIE); // CPU off, enable interrupt

    }

    }

    void

    USCIA0RX_ISR(void)

    {

    int x = 0;

    int y = 0;

    lnum2 = 0x01;

    ADC10CTL0 &= ~ENC;

    while (ADC10CTL1 & BUSY); // Wait if ADC10 core is active

    ADC10CTL0 |= ENC + ADC10SC;

    lnum = ADC10MEM;

    if (lnum < 559)//512

    {

    P2OUT |= BIT1;

    __delay_cycles(recharge_cycles);

    P2OUT &= ~BIT1;

    __delay_cycles(200);

    charge_cnt++;

    }

    P2OUT &= ~BIT0;

    // /CE low

    __delay_cycles(numcycles);

    // Add time between transmissions to

    UCB0TXBUF = 0x06;

    // WREN

    __delay_cycles(numcycles);

    // Add time between transmissions to

    P2OUT |= BIT0;

    // /CE high

    P2OUT &= ~BIT0;

    // /CE low

    __delay_cycles(numcycles);

    // Add time between transmissions to

    while (!(IFG2 & UCB0TXIFG));

    UCB0TXBUF = 0x02;

    // write op code

    while (!(IFG2 & UCB0TXIFG));

    UCB0TXBUF = 0x01;

    // write MSB address

    while (!(IFG2 & UCB0TXIFG));

    UCB0TXBUF = MST_Data;

    // write LSB address

    for (x = 0; x < 32; x++)

    {

    while (!(IFG2 & UCB0TXIFG));

    UCB0TXBUF = 0xAA;

    // write 1byte

    }

    __delay_cycles(numcycles);

    // Add time between transmissions to

    P2OUT |= BIT0;

    // /CE high

    while

    ((lnum2 % 2) > 0)

    {

    P2OUT &= ~BIT0;

    // /CE low

    __delay_cycles(numcycles);

    // Add time between transmissions to

    while (!(IFG2 & UCB0TXIFG));

    UCB0TXBUF = 0x05;

    // read op code

    while (!(IFG2 & UCB0TXIFG));

    UCB0TXBUF = 0xFF;

    // dummy for clock

    while (!(IFG2 & UCB0TXIFG));

    UCB0TXBUF = 0xFF;

    // dummy for clock

    while (!(IFG2 & UCB0RXIFG));

    lnum2 = UCB0RXBUF;

    // write 1byte

    __delay_cycles(numcycles);

    // Add time between transmissions to

    P2OUT |= BIT0;

    // /CE high

    y++;

    }

    if

    (y > 1)

    {

    device_id = 1;

    }

    else

    {

    device_id = 0;

    }

    lnum2 = 0x01;

    bytes_wr = bytes_wr + 32;

    MST_Data++;

    __delay_cycles(numcycles);

    // Add time between transmissions to

    TA0CCR1 = page_write;

    }

     

    void

    TIMER_ISR(void)

    {

    adc2asciihex(device_id);

    adc2asciihex(lnum);

    adc2asciihex(charge_cnt);

    adc2asciihex(bytes_wr);

    while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready?

    UCA0TXBUF =

    '\r'; // Send next value

    while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready?

    UCA0TXBUF =

    '\n'; // Send next value

    TA0CCR0 = update_delay;

    }

    void

    adc2asciidec(unsigned long anum)

    {

    int i=0;

    while(anum >= 10)

    {

    digit[i] = anum % 0x0a;

    anum = anum / 0x0a;

    i++;

    }

    digit[i] = anum;

    while(i>=0)

    {

    while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready?

    UCA0TXBUF = digit[i] + 48;

    //uart_data[x];//ADC10MEM; // Send next value

    digit[i] = 0;

    i--;

    }

    //delay_ms(500);

    while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready?

    UCA0TXBUF =

    ' '; // Send next value

    while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready?

    UCA0TXBUF =

    ' '; // Send next value

    }

    void

    adc2asciihex(unsigned long anum)

    {

    int i=0;

    while(anum >= 0x10)

    {

    digit[i] = anum % 0x10;

    anum = anum / 0x10;

    i++;

    }

    digit[i] = anum;

    while(i>=0)

    {

    while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready?

    if (digit[i] < 10)

    {

    UCA0TXBUF = digit[i] + 48;

    //uart_data[x];//ADC10MEM; // Send next value

    }

    else

    {

    UCA0TXBUF = digit[i] - 10 + 65;

    //uart_data[x];//ADC10MEM; // Send next value

    }

    digit[i] = 0;

    i--;

    }

    //delay_ms(500);

    while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready?

    UCA0TXBUF =

    ' '; // Send next value

    while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready?

    UCA0TXBUF =

    ' '; // Send next value

    }

     

     

    #pragma vector = TIMER0_A1_VECTOR

    __interrupt

    void TIMER_A1(void)

    {

    USCIA0RX_ISR();

    }

    #pragma

    vector = TIMER0_A0_VECTOR

    __interrupt

    void TIMER_A0(void)

    {

    TIMER_ISR();

    }

    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    All Replies
    • Jonathan Hunter1
      Posted by Jonathan Hunter1
      on Aug 19 2012 16:29 PM
      Prodigy140 points

      The paste came out weird for my code.  Please let me know if clarification is needed.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Leo Hendrawan
      Posted by Leo Hendrawan
      on Aug 20 2012 04:19 AM
      Mastermind27270 points

      Hi,

      Jonathan Hunter1

      TA0CCTL0 = CCIE;

      TA0CCTL1 = CCIE;

      TA0CCR0 = update_delay;

      TA0CCR1 = page_write;

      TA0CTL = TASSEL_1 + MC_1 + TAIE;

      // ACLCK, 1/8 DIVIDER, upmode to TCCR0 value

      You are basically using the Up mode which means that the timer counter TA0R will count up to TA0CCR0 then resets back to zero. Which value are using at ACLK?

      Jonathan Hunter1

      #define update_delay 2620//1310 //0

      #define page_write 3000 //5

      However you are setting the value of TA0CCR1 with a value which is greater than the TA0CCR0 itself (means TA0R will never reach the TA0CCR1).

      I would suggest the following:

      #define ACLK_FREQ_INPUT_HZ       (32768UL)  // assume 32 kHz input at ACLK

      #define CCR0_PERIOD_MS           (200UL)  // 200 ms

      #define CCR1_PERIOD_MS           (5UL)  // 5ms

      #define CCR0_VALUE               ((unsigned int) (CCR0_PERIOD_MS*ACLK_FREQ_INPUT/1000UL))

      #define CCR1_VALUE               ((unsigned int) (CCR1_PERIOD_MS*ACLK_FREQ_INPUT/1000UL))

      and use the CCR0_VALUE and CCR1_VALUE above as your input to the TA0CCR0/1 registers.

      Regards,

      Leo Hendrawan

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jonathan Hunter1
      Posted by Jonathan Hunter1
      on Aug 20 2012 19:10 PM
      Prodigy140 points

      Hello Leo,

      Thanks for replying!

      I agree that I need to be more precise with my CCR0 and CCR1 values, but no matter what value I make CCR1 the timing does not seem to change for executing that section of code.  As I understand it with a CCR1 = 3000, that interrupt code should be occurring even less frequently than my CCR0 interrupt code.  For some reason, my code is triggering constantly and the only time CCR1 is not running is when CCR0 triggers.

      I think it points to a configuration error, but I don't know what.  I also reference ADC10, SPI ports for B0, and UART A0 pins.  I will use all the rest of the pins for GPIOs to control other components.  Is there a conflict with using TA0CCR1 with these configurations?

      Here are my CLK settings that I forgot to add:

          BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0;

      if (CALBC1_1MHZ != 0xFF) {

      /* Follow recommended flow. First, clear all DCOx and MODx bits. Then

               * apply new RSELx values. Finally, apply new DCOx and MODx bit values.

               */

              DCOCTL = 0x00;

              BCSCTL1 = CALBC1_1MHZ;     

      /* Set DCO to 1MHz */

              DCOCTL = CALDCO_1MHZ;

          }

          BCSCTL1 |= XT2OFF + DIVA_0;

          BCSCTL3 = XT2S_0 + LFXT1S_2 + XCAP_1;

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • old_cow_yellow
      Posted by old_cow_yellow
      on Aug 20 2012 20:41 PM
      Guru25715 points

      CCR0 generates an unique interrupt.  Its interrupt flag is automatically cleared when that interrupt is acknowledged.

      CCR1 shares its interrupt with other causes. Thus its interrupt flag is not automatically cleared. The ISR must clear it, otherwise it will cause another interrupt the moment your ISR finishes. And that is what you experienced.  Add a CCTL1 &= ~CCIFG; statement in its ISR.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Leo Hendrawan
      Posted by Leo Hendrawan
      on Aug 21 2012 02:44 AM
      Mastermind27270 points

      Hi,

      old_cow_yellow

      CCR1 shares its interrupt with other causes. Thus its interrupt flag is not automatically cleared. The ISR must clear it, otherwise it will cause another interrupt the moment your ISR finishes. And that is what you experienced.  Add a CCTL1 &= ~CCIFG; statement in its ISR.

      OCY was right. referring to the User's Guide document, the best way to do this is by reading out the TAIV register:

      12.2.6.2 TAIV, Interrupt Vector Generator
      The TACCR1 CCIFG, TACCR2 CCIFG, and TAIFG flags are prioritized and combined to source a single interrupt vector. The interrupt vector register TAIV is used to determine which flag requested an interrupt. The highest priority enabled interrupt generates a number in the TAIV register (see register description).
      This number can be evaluated or added to the program counter to automatically enter the appropriate software routine. Disabled Timer_A interrupts do not affect the TAIV value.


      Any access, read or write, of the TAIV register automatically resets the highest pending interrupt flag. If another interrupt flag is set, another interrupt is immediately generated after servicing the initial interrupt. For example, if the TACCR1 and TACCR2 CCIFG flags are set when the interrupt service routine accesses the TAIV register, TACCR1 CCIFG is reset automatically. After the RETI instruction of the interrupt service routine is executed, the TACCR2 CCIFG flag will generate another interrupt. 

      Regards,

      Leo Hendrawan

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jens-Michael Gross
      Posted by Jens-Michael Gross
      on Aug 21 2012 09:25 AM
      Guru140085 points

      Jonathan Hunter1
      As I understand it with a CCR1 = 3000, that interrupt code should be occurring even less frequently than my CCR0 interrupt code.

      No. In cont mode, wher ethe tiemr counts fromm 0 to 65535 and begins with 0, all CCR units trigger once per round, just at different moments.
      In up mode, which you use,the timer counts from 0 to CCR0 and then begins with 0 again. But the interrupts trigger when the timer counts to the stored value. Hence 'compare mode', in opposition to 'capture mode' for the CCRs (Capture-Compare-Registers). SO if the CCR1 value is higher than CCR0 value, the timer never will count that high and the interrupt is never triggered at all.
      If it is less than CCR0, it will trigger exactly as often (once per tiemr cycle), only the moment during the cycle differs with the value.

      BTW: if you want the cycle to be 1000 timer ticks, you'll have to write 999 into CCR0, since '0' is a tick as well.

      The reason why you got this amount of CCR1 interrupts was already explained by the others. And since CCR1 and CCR0 were 0 before you wrote the values that effectively prohibited any CCR1 interrupt, there was already one interrutp pending which you never cleared.

      _____________________________________
      Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.
      If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jonathan Hunter1
      Posted by Jonathan Hunter1
      on Aug 21 2012 21:17 PM
      Prodigy140 points

      Thanks for the replies!

      So I tried clearing the interrupt after it triggered using (because the CCR1 interrupt is not clearing):

      TA0CCTL1 &= ~CCIFG;

      I put this line at the end of my USCIA0RX_ISR() function call.  It had no effect on the how the code operated.

       

      I then tried reading the TA0IV register with:

      lnum2 = TA0IV;

      This caused my code to go back to the main function each time this line was reached.  The code was planned to go through the main function once to initialize variables and then remain in the infinite loop that contained sleep and interrupt enable.  The program would only run when CCR0 and CCR1 interrupts occur.

       

      I see what you are saying Jens about the CCR1 must be smaller than CCR0 otherwise the code will never trigger.  I suppose that is why I am confused because with the timer in up configuration, I should never see my SPI commands rather than always seeing my SPI commands. So I suppose this all points back to I still am not clearing interrupt correctly or my configuration is not allowing me to do so.

      Do you see anything else that could be causing this?

       

       

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jens-Michael Gross
      Posted by Jens-Michael Gross
      on Aug 22 2012 09:37 AM
      Guru140085 points

      Jonathan Hunter1
      So I tried clearing the interrupt after it triggered using (because the CCR1 interrupt is not clearing):
      TA0CCTL1 &= ~CCIFG;
      I put this line at the end of my USCIA0RX_ISR() function call.  It had no effect on the how the code operated.


      I wouldn't expect it to work :)
      You must clear the IFG bit inside the ISR it was triggering. So inside the timer ISR. If you leave the timer ISR before it is cleared, you'll go into the timer ISR again right away, and never execute any ISR with a lower interrupt priority.

      _____________________________________
      Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.
      If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jonathan Hunter1
      Posted by Jonathan Hunter1
      on Aug 22 2012 15:26 PM
      Prodigy140 points

       

      I see what you are saying.  I corrected Timer_A1 ISR function call.

      #pragma vector = TIMER0_A1_VECTOR

      __interrupt void TIMER_A1(void)

      {

          TA0CCTL1 &= ~CCIFG;

          USCIA0RX_ISR();

      }

      #pragma vector = TIMER0_A0_VECTOR

      __interrupt void TIMER_A0(void)

      {

      TIMER_ISR();

      }

      This change does not seem to change how the program runs. 

      The only thing that seems to change how the code executes is reading/writing from TA0IV, but that just causes the program to reset and start from the beginning of main again.

      Here is my current configuration:

      In the main() function:

      #define update_delay 3000

      #define page_write 200

       

      TA0CCR0 = update_delay;

      TA0CCR1 = page_write;

      TA0CTL = TASSEL_1 + MC_1 + TAIE;   

      TA0CCTL0 |= CCIE;

      TA0CCTL1 |= CCIE;

       

      At the end of USCIA0RX_ISR():

      TA0CCR1 += page_write;

       

      In my CCR0 interrrupt function:

      void TIMER_ISR(void)

      {

      int x;

         adc2asciihex(device_id);

          adc2asciihex(lnum);

      adc2asciihex(charge_cnt);

          adc2asciihex(bytes_wr);

        

      while (!(IFG2 & UCA0TXIFG));              // USCI_A0 TX buffer ready?

          UCA0TXBUF = '\r';                         // Send next value

         

      while (!(IFG2 & UCA0TXIFG));              // USCI_A0 TX buffer ready?

          UCA0TXBUF = '\n';                         // Send next value

          TA0CCR1 = page_write;

          TA0CCR0 = update_delay;

        }

       

      So my understanding, the code should have timerA0 count up to CCR0 = 3000 and reset. Since CCR1 += 200, then every 200 cycles it would run the SPI commands until CCR0 triggers and the timer is reset to 0.  The Timer_ISR() function that triggers at CCR0 interrupt shoud reset CCR1 value to 200.  I know that CCR0 works because I can increase that value and watch teh updates happen at a slower rate.

      Is there something else that I need to do before 'TA0CCTL1 &= ~CCIFG;' that would allow me to clear the interrupt? Would it help to zip up my project to view?

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jonathan Hunter1
      Posted by Jonathan Hunter1
      on Aug 23 2012 18:52 PM
      Prodigy140 points

      Is there any further advice?  Does anyone know why reading from TA0IV would cause the entire program to reset?

      Could someone point me to code that runs 2 interrupt routines in a similar setup that I am trying to acheive?

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Leo Hendrawan
      Posted by Leo Hendrawan
      on Aug 24 2012 03:36 AM
      Mastermind27270 points

      Jonathan,

      could you share your code? i might try to test it myself. Looking the code above gives a little headache :)

      Regards,

      Leo Hendrawan

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jonathan Hunter1
      Posted by Jonathan Hunter1
      on Aug 24 2012 10:07 AM
      Prodigy140 points

      Thanks Leo!

      This code is supposed to work with a development board but you can still see the issue with out that board.

      I included 2 images from a logic analyzer to show what I am seeing.

      In MSP430_1.jpg, you will see a lot of activity with periods (every ~200ms) of "no activity" for the SPI lines (this is the UART update which you can see on the terminal as well).  That 200ms period will change if you modify the CCR0 value in the code.

      In MSP430_2.jpg, you see the SPI commands which are 32 bytes of written data and a status register update.

      In the terminal window, you will see the 4 values printed on each line.  The main value to be concerned about is the 4th value (number of bytes written in hex)  which should increment a certain rate depending on CCR1, but it does not.  As you can see from the logic analyzer, the rate is as fast as possible.

      Please let me know if need any other information.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jonathan Hunter1
      Posted by Jonathan Hunter1
      on Aug 24 2012 10:09 AM
      Prodigy140 points

      forgot the link...

      5226.msp430g2xx3_usci_spi_master.zip

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • old_cow_yellow
      Posted by old_cow_yellow
      on Aug 26 2012 11:43 AM
      Verified Answer
      Verified by Jonathan Hunter1
      Guru25715 points

      I do not use c to program MSP430, especially not CCS or Libraries from TI. They tend to do things “automatically” which I know nothing about. (What I do not know often hurts me.) Hence I cannot help you much.

      I did try to read the code you posted.

      CCIE in both TA0CCTL0 and TA0CCTL1 are enabled. And the corresponding handlers exist. TAIE in TA0CTL is also enabled but not handled. I am not sure how many other interrupts are enabled (automatically) and not handled. Any interrupt without a matching “#pragma vector = …” handler may “automatically” cause a crash.

      TA0CTL is configured to count ACLK in Up-mode. TA0CCR is set to 2620. This means TA0R will count from 0 up to 2620 and back to 0 and up again repeatedly, resulting in a 2621 ACLK cycle repetitive counting pattern.

      CCIE in TA0CCTL0 is enabled. A corresponding interrupt is generated when TA0CCR0 matches the TA0R counter. Thus this happens repetitively at every 2620 of the 0-2620 counting pattern. The period is 2621, very close to what you want.

      TA0CCR1 is set to 100 and CCIE in TA0CCTL1 is also enabled. A corresponding interrupt is generated when TA0CCR1 matches the TA0R counter. Thus this happens repetitively at every 100 of the 0-2620 counting pattern. The period is also 2621. The only difference is that it is 100 counts later than the other one. This is not what you want.

      The interrupt caused by TAIE of TA0CTL shares the same “#pragma vector = …” as the CCIE of TA0CCTL1. Thus the code there gets executed unintentionally. Further more, the TAIFG in TA0CTL is not cleared. And the code there gets executed repeatedly.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Leo Hendrawan
      Posted by Leo Hendrawan
      on Aug 27 2012 02:20 AM
      Verified Answer
      Verified by Jonathan Hunter1
      Mastermind27270 points

      Good morning Gentlemen,

      So Jonathan, i read your code, and although i didn't test your code directly, here are some thoughts:

      - You are setting the TAIE bit in TA0CTL register. Do you really need this? Referring to the 2xx Family User's Guide, this interrupt is basically "almost" the same as the CCR0  IFG in up mode:

      As you can see above, the TAIFG bit will be generated everytime 1 clock cycle right after the CCR CCIFG interrupt. OCY has also pointed out above that this shares the same interrupt with other CCRx interrupts other than CCR0. In my opinion i don't think you need to set this TAIE bit since it will makes the same interrupt vector as CCR1 CCIFG invoked (maybe this is the root of your problem). Please read the following chapter from the users guide document carefully again:

      - I am not really sure what is the goal of your program. I can see that you do some ADC sampling and send the results, however i don't think this is the right way to do it (e.g. you do the ADC sampling inside the interrupt routine which basically blocks other interrupt). If you are not familiar with the MSP430 programming, would heavily recommend you to read the following short document : MSP430 Software Coding Techniques: http://www.ti.com/lit/an/slaa294a/slaa294a.pdf. This is a very great documentation which i always recommend for starting in the world of MSP430. Just to summarize:  basically you shall do the hard work in the main loop. The ISRs are only used for getting the events, and setting a flag to notify the main loop to do the job.

      -You don't need to reload the TAxCCRy value in the interrupt routine, as long as you don't touch it, it will not be changed.

      - @OCY: actually Jonathan has assigned the interrupt routines. He is using GRACE (http://www.ti.com/tool/grace), and if you search for a file called CSL_init.c in the zip file, you can find the interrupt vectors assigned.

      Let me know if you still have other questions.

      Regards,

      Leo Hendrawan

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    12
    TI E2E™ Community
    • Support Forums
    • Blogs
    • Videos
    • Groups
    • Site Support & Feedback
    • Settings
    TI E2E™ Community Groups
    • TI University Program
    • Make the Switch
    • Microcontroller Projects
    • Motor Drive & Control
    Other Communities
    • Deyisupport
    • Designsomething.org
    • beagleboard.org
    • TI on Element 14
    • TI on TechXchangeSM
    Other Technical & Support Resources
    • WEBENCH® Design Center
    • Product Information Centers
    • Technical Documents
    • TI Design Network
    • TI Technical Articles
    • TI Training

    All content and materials on this site are provided "as is". TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with regard to these materials, including but not limited to all implied warranties and conditions of merchantability, fitness for a particular purpose, title and non-infringement of any third party intellectual property right. TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with respect to these materials. No license, either express or implied, by estoppel or otherwise, is granted by TI. Use of the information on this site may require a license from a third party, or a license from TI.

    Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms of Use of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms of Use of this site. TI, its suppliers and providers of content reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.

    Follow Us Texas Instruments on Facebook Texas Instruments on Twitter Texas Instruments on LinkedIn Texas Instruments on Google+
    TI Worldwide | Contact Us | my.TI Login | Site Map | Corporate Citizenship | mobile m.ti.com (Mobile Version)

    TI is a global semiconductor design and manufacturing company. Innovate with 100,000+ analog ICs and
    embedded processors, along with software, tools and the industry’s largest sales/support staff.

    © Copyright 1995-2013 Texas Instruments Incorporated. All rights reserved.
    Trademarks | Privacy Policy | Terms of Use