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.

About vectored interrupts.

Other Parts Discussed in Thread: CCSTUDIO, MSP430G2231

Hi guys,

I've gone through the Lab 5 of the TI workshop tutorial for MSP430 about timer and interrupts. I've found out that many tutorial topics just tell us what to do without telling us why.

I have a few things don't understand:

#pragma vector = TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
  ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON;
  _delay_cycles(5);                         // Wait for ADC Ref to settle 
  ADC10CTL0 |= ENC + ADC10SC;               // Sampling and conversion start
  P1OUT |= BIT6;                             // P1.6 on (green LED)
  _delay_cycles(100);
  ADC10CTL0 &= ~ENC;                   // Disable ADC conversion
  ADC10CTL0 &= ~(REFON + ADC10ON);        // Ref and ADC10 off
  tempRaw = ADC10MEM;                        // Read conversion value
  P1OUT &= ~BIT6;                             // green LED off
  CCR0 +=12000;
}

Above is a ISR for a timer in the tutorial.

May I ask what is #pragma vector = TIMERA0_VECTOR? Is it that we always need to declare it for before our ISR?

The name TIMERA0_VECTOR is it fixed? Or we can change to other name like FIRSTTIMER_VECTOR?

  • Steven,

    because you didn't mention it, i am assuming that you are using CCSTUDIO or IAR EWB. Basically the answer is yes, you need to put the #pragma vector directive before any ISR. The name of the vectors are defined basically in the header file of the MSP430 devices, so you shall not change it to other name. By defining this directive, the compiler will also put the address of the ISR function in the Interrupt vector table (located at the end of the 64K MSP430 memory)

    For more explanation, you can try to look at the CCSTUDIO MSP430 compiler manual chapter 5.9.16.

    I hope this helps.

  • Steven Gan Teck Yik said:
    May I ask what is #pragma vector = TIMERA0_VECTOR?

    A #pragma in general is a compiler specific instruction that tells teh compiler to do certain things. The pragma 'vector' tells the compiler that the next symbols (usually an interupt function) address is to be placed at the given (named) position in the interrupt vector table.
    On the bottom line, it is similar to defining a constant function pointer, assign it the ISRs address and have it placed in the vector table.

    The vector names are predefined and refer to a certain position in the vector table. In theory, you can define your own symbols for thsi pragma, but as these are just offsets in the vector table, it will only make your ode unreadable at best and not working as expected in the worst case, since all possible locations already got a name that is consistent across different processors (if supported by them at all). Or in other words: if you have to ask, don't touch it. If you don't have to ask, you won't touch it. :)

  • OK. Thanks.

    Another question, now my msp430g2231 got a 32kHz crystal connect to XIN and XOUT. if I use the below routine:

    void main (void)
    {        
        WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
        P1OUT = ~LED1; // Preload LED1 off (active low!)
        P1DIR = LED1|LED2; // Set pin with LED1 to output
        TACTL = MC_2|ID_3|TASSEL_2|TACLR; // Set up and start Timer A
        // Continuous up mode , divide clock by 8, clock from SMCLK , clear timer
        for (;;)
        { // Loop forever
            while (TAIFG == 0)
            { // Wait for overflow
            } // doing nothing
            TACTL &= ~TAIFG; // Clear overflow flag
            P1OUT ^= LED1|LED2; // Toggle LEDs
        }
    }

    Do you know what is the difference of the toggling LED with or without the crystal?

    Seems like with the crystal connected, the LED won't toggle. But from above code, I do not do any setting regarding the crystal right? Why?

    Or I have to disconnect the crystal then only the LED will toggle?

  • Steven,

    the best way to start programming the MSP430 is by referring to the code examples provided. This is usually available under the "Software & Tools" section of the product page. For example, for the G2231 here: http://www.ti.com/product/msp430g2231#toolssoftware

    However to your questions:

    - the problem in your code seems to be that the while loop should be look like this: while(!(TACTL&TAIFG));

    - you are right, because you set the TASSELx bit as 2 (10), it means that the timer is sourced by SMCLK which is pre default source from DCO instead of the LFXT1CLK/ACLK. To source the timer with LFXT1CLK/ACLK, you should set the TASSELx bit as 1.

    I hope this helps you.

     

  • Steven Gan Teck Yik said:
    Do you know what is the difference of the toggling LED with or without the crystal?

    There should be none. Per default, SMCLK (which you selected as clock source for the timer) runs from DCO, and you didn't do anything to change that. YOu do not configure the clock module at all, so it runs on plain default configuration. Which doesn't include a crystal clock source for SMCLK.

    Whether you have acrystal or not means that ACLK will run on it or on VLO (a factor of 2 to 8 slower), but since you don't use ACLK, it shouldn't make any difference.

    Maybe you made something wrong when connecting the crystal, and the MSP is not starting at all with the crystal connected...

  • I see. Thanks.

    I have another question.

    Below is some of the coding I encounter:

    #define   LED2     P2OUT_bit.P2OUT_4

    LED2 = ~IFG1_bit.WDTIFG;

    This functions is for bit wise function. LED2 is set whenever WDTIFG is raised. 

    This kind of bit-wise function only can use in IAR workbench right? Cos I tried in CCS4 but can't recognize.

    Then, how do we write 'LED2 = ~IFG1_bit.WDTIFG;' so that it can be use in CCS4?

  • Steven Gan Teck Yik said:
    I tried in CCS4 but can't recognize

    What, exactly, can it "not recognise" ?

    Post the source code that you actually used, and the full text of the exact error message(s) that you get (use copy & paste; do not manually re-type)

  • Andy Neil said:

    I tried in CCS4 but can't recognize

    What, exactly, can it "not recognise" ?

    Post the source code that you actually used, and the full text of the exact error message(s) that you get (use copy & paste; do not manually re-type)

    [/quote]

    I mean the bit field function like 'P2OUT_bit.P2OUT_4' or 'LED2 = ~IFG1_bit.WDTIFG'.

    As I know, CCS4 doesn't have io430xxxx.h file so it cannot recognize those function. Or you mean your CCS4 can recognize?

  • Steven,

    as i am aware, usually we do not use bit field programming with CCS and IAR (as you can see in the whole example code). If you want, you can look into the header files of CCS compiler which can be found usually at : C:\Program Files\Texas Instruments\ccsv4\msp430\include

    I hope this helps.

    -Leo-

  • lhend said:

    Steven,

    as i am aware, usually we do not use bit field programming with CCS and IAR (as you can see in the whole example code). If you want, you can look into the header files of CCS compiler which can be found usually at : C:\Program Files\Texas Instruments\ccsv4\msp430\include

    I hope this helps.

    -Leo-

    I've look through already and that directory does not include the io430xxxx.h header file.

    So then, how am I going to change the below coding so that CCS4 can compile it:

    LED2 = ~IFG1_bit.WDTIFG;

    P2OUT_bit.P2OUT_4

     

     

     

  • Steven Gan Teck Yik said:
    I've look through already and that directory does not include the io430xxxx.h header file.

    And there is a reason.

    Bitfields, while convenient and usually not less efficient than direct manual bit manipulations, are highly ineffective on volatile variables such as hardware registers.
    The compiler must not optimize accesses to volatile variables. It needs to make as many accesses and in teh exact orher and the exact position in the code flow as they appear.
    So setting several bits in a bitfield leads to larger and more ineffective code than a direct bit manipulation. And the mutiple accesses may have unwanted side-effects (depending on register type and situation).
    So bitfields are no longer officially supported.

    Steven Gan Teck Yik said:
    So then, how am I going to change the below coding so that CCS4 can compile it:

    Steven Gan Teck Yik said:
    LED2 = ~IFG1_bit.WDTIFG;

    There are several solution.
    If LED2 really needs to be 1 or 0, then a possible way would be
    LED2 = (IFG1&WDTIFG)?1:0;
    if LED2 jus tneeds to be 0 (false) or non-0 (true), then
    LED2=IFG1&WDTIFG;
    is sufficient. LED2 then is either 0 or WDTIFG.

    Steven Gan Teck Yik said:
    P2OUT_bit.P2OUT_4


    This depends on whether it is used as lvalue or rvalue.
    Ther value expression would be
    ((P2OUT&BIT4)>>4)
    and returns 0 or 1, dependign on whether P2OUT.4 is set or not. However, if you use it as LVALUE (the likelier usage, since P2OUT is usually used for output), then there
    are two instructions, depending on whether you want to set or clear the bit:
    P2OUT &=~BIT4;
    clears P2OUT.4 and
    P2OUT|=BIT4;
    sets it.
    If you have the value to set in a variable x, and it is 0 or 1, you can do
    P2OUT = (P2OUT&~BIT4)|(x<<4);
    If x is true or false (0 or non-0, btu not guaranteed to be 1 then), use
    P2OUT = (P2OUT&~BIT4)|(x?BIT4:0);
    This is actually what the compiler would generate for a bitfield access anyway.

    Inverting the bit (P2OUT_bit.P2OUT_4 = !P2OUT_bit.P2OUT_4) would translate into
    P2OUT ^= BIT4;

**Attention** This is a public forum