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.

Argument from function does not pass to ISR



Hi. I am trying to write a program that outputs on P1.0 an adjustabla PWM. This is obtained using a function "void setSpeed(unsigned long speed)". The problem that I encounter is that the argument "speed" does not pass to the "Timer A0 interrupt service routine". While debugging, when the compiler gets to the Timer A0 ISR, the value of "speed" is always reset back to 0. 

         Here is the code:

#include <msp430.h>

 long counter;

 unsigned long speed;

void setSpeed(speed);




int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;                     // Stop WDT



    // Configure GPIO

    counter=0;

    P1DIR |= BIT0;                                // P1.0 output
    P1OUT |= BIT0;                                // P1.0 high

    P5DIR |= BIT0;                                // P5.0 output
    P5OUT |= BIT0;                               //P5.0 high

    P8DIR |= BIT0;                              //P8.0 output
    P8SEL0 |= BIT0;                             //P8.0 selected as SMCLK


    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;

    setSpeed(10);

}


void setSpeed(speed)


{
	    TA0EX0 &= ~(BIT0 + BIT1 + BIT2);          //SMCLK divided by 1 => 1 tick = 1us
	    TA0CCTL0 |= CCIE;                             // TACCR0 interrupt enabled
	    TA0CCR0 = 4;                              // every 4 us
	    TA0CTL = TASSEL__SMCLK | MC__UP;             // SMCLK, UP mode

	    __bis_SR_register(LPM0_bits | GIE);          // Enter LPM0 w/ interrupt
	    __no_operation();                            // For debugger



}

	    // Timer A0 interrupt service routine
	    	    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
	    	    #pragma vector = TIMER0_A0_VECTOR
	    	    __interrupt void Timer_A (void)
	    	    #elif defined(__GNUC__)
	    	    void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A (void)
	    	    #else
	    	    #error Compiler not supported!
	    	    #endif

	    	    	{

	    	    	counter++;

	   	    		if (counter == speed)  //here, speed always is reset to 0
	    	    		{
	    	    			P1OUT ^= BIT0;
	    	    			P5OUT ^= BIT0;
	    	    			counter = 0;
	    	    		}
	    	    	}


   There is also a warning for the setSpeed function:

93-D identifier-list parameters may only be used in a function definition

    Can anyone help me correct my code?

    Thank you.

  • Hi Vlad!

    Variables used in interrupts should be declared as volatile.

    Dennis
    1. You don't set the value of  the global "speed" anywhere.
    2. The compile warning is because you haven't given the "speed" parameter of setSpeed a type.

    By the way, you're likely to have trouble soon with the fact that "speed" is both a global variable and a function parameter.

  • A function should not set lpm, main should do that, preferable inside a: while(1){
    Why is speed a long?,. msp registers are 16bit so I can not see why you need 64bits.
    Use timer to output pwm directly to a pin.
  • Tony Philipsson said:
    Why is speed a long?,. msp registers are 16bit so I can not see why you need 64bits.

    For TI's compiler, "long" is 32 bits; you have to use "long long" to get 64.

    The point still stands that 32 bits doesn't fit in a register, so "int" or "short" would be a better choice. This matters because 16 bit variables can be set atomically on MSP430, but larger ones can't. If an interrupt occurs between the two instructions needed to set each half of a 32 bit variable the ISR could observe an incorrect value.

  • I need a "long" because I will need to have an adjustable PWM from 2.22Hz to 555Hz with a 2.22 step, so the the output PIN will have to toggle at every 225225 us(2.2Hz) to 900 us (555Hz).
  • >If an interrupt occurs between the two instructions needed to set each half of a 32 bit variable the ISR could observe an incorrect value.
    That' s not a problem actually. Disable interrupts before update and enable after.
  • Hi Vlad!

    Maybe it would be easier if you would describe in detail what you plan to do here. Do you want a PWM with fixed frequency and changeable duty-cycle or do you also want to change the PWM's frequency? PWM can be done completely in hardware without the need for any ISR.

    Dennis
  • >PWM from 2.22Hz to 555Hz with a 2.22 step

    Sounds like you want adjustable freq square wave, not PWM
    w.m. stands for  Width Modulation and you are not adjusting width.

    Do you have  a 32K crystal?

    Even with just the 1MHz DCO,
    you can still get the low 2.22Hz by Div timer by 8 and output this square wave directly to a TA0.0 or TA1.0 pin.

    1'000'000 /8 /2(toggle mode) = 62500 fits in 16bit = slowest is just under 1Hz

  •    Hi Dennis.

       I want to create a function, lets call it "setFrequency ( int valueFrequency)" that outputs a frequency at my choice, between 2,22 Hz and 555Hz. I need to use a function because I want other persons to use my code by using just 2 functions: setFrequency and a delay function. By using these two functions anyone will be able to create cycles like the following:

    setFrequency(100);
    delay(60);           //MSP430 will output 100Hz frequency signal for 1 hour
    setFrequency(60);
    dealy(120);           //MSP430 will output 60Hz frequency signal for 2 hours
    setFrequency(250);
    dealy(30);           //MSP430 will output 250Hz frequency signal for 30 minutes
    
    //and so on

  • Yes, you are right. I want an adjustable freq square wave, not PWM. But my problem is that I dont have the skills to program the MSP430. I have some experience with C programming but this embedded software is quite different. I dont know why if I declare the variable "speed" as 10 at line 36, when the program enters the interrupt rutine , at line 69, the "speed" variable is 0. Why does it not remain 10? I declared "speed" as volatile but the result is the same.
  • I forgot to mention: I want a square wave with adjustable frequency. The duty cycle is always 50%. It is not changeable.
    Thank you, Dennis.
  • I declared "speed" volatile. Still doesn't work.
  • I set the value for "speed " as 10 at line 36 when I call the function as setSpeed(10). Or does the compiler expects something else from me?
    And for no.2, isn't the type of the variable unsigned long, as I declared it at line 5?
    Thank you.
  • You may want to read the User's Guide chapter about timers. If you want a square wave with fixed duty-cycle you can use the hardware toggle mode of the timer (OUTMOD_4). What is your delay function for?

  • The delay function is to tell the MSP430 for how long I want a certain frequency.
  • vlad balu said:
    I set the value for "speed " as 10 at line 36 when I call the function as setSpeed(10).

    No, you passed the value 10 as the parameter "speed" of the function setSpeed. The global variable called "speed" is a separate thing, and you never set that anywhere. For the same reason, though you set the type of the global variable "speed" to unsigned long, the type of the "speed" parameter of setSpeed is not set*.

    * Since the type is not specified the compiler assumes it to be int, which is a signed 16-bit value for MSP430.

  •   Thank you for clearing this up for me. And what must I do so that "speed" parameter from setSpeed function is passed to the interrupt routine? 

  • In order to access the global variable you named "speed", you cannot name a local variable or a function parameter by the same name ("speed").

    Also, you should declare your global variable "volatile". Here "volatile" is not a bird, nor something that vaporizes. It is a "c-thing". If you do not use it, your code may be ignored by the c- compiler. If you do use it, your code might still not work if there is something else wrong.

**Attention** This is a public forum