2
\$\begingroup\$

I can't seem to get my global variables (low, high) to change inside my interrupt, despite having declared them volatile. Below is my code.

I find it strange that I can modify my global variable 'change' but modifications to 'low' and 'high' don't seem to work. I know for sure that my interrupt is being completed, since the text is reprinting to the LCD display, just that the numbers aren't being modified.

I marked out the most relevant locations with "HERE" where I think that the problem is most likely at. I also tested whether it's just because the variable turn is always 0 by adding code at the end of the ISR to see whether the global variables change or not. They don't.

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd.h"
int state;
volatile int low; //HERE
volatile int high;
char scount[5];
char snum[5];
char mode;
volatile char change=0;//HERE
int main()
{
    char b_high;
    char b_low;
    DDRD=0xf0;
    DDRB=0b00000011;
    PORTD |= 0b00001000; 
    PORTC |= (1 << PC1);
    PORTC |= (1 << PC2);
    PORTB |= 0b00100000;
    PCICR=0b00000010;
    PCMSK1=0b00000110;
    sei();
    init_lcd();
    writecommand(0x01);
    moveto(0x80);
    stringout("Low:    ");
    stringout("High:    ");
    moveto(0xc0);
    stringout("Change:high");
    int low=70;
    int high=85;
    moveto(0x84);
    itoa(low, scount, 10);
    stringout(scount);
    moveto(0x8d);
    itoa(high, scount, 10);
    stringout(scount);
    while(1){
        b_high = PIND & 0b00001000; 
        b_low = PINB & 0b00100000;
        if(!b_high)
        {
            moveto(0xc7);
            stringout("high");
            mode=0;
        }
        if(!b_low)
        {
            moveto(0xc7);
            stringout("low ");
            mode=1;
        }
        if(change)//HERE
        {
            if(mode)
            {
                //low+=turn;
                itoa(low, snum, 10);//HERE
                moveto(0x84);
                stringout("   ");
                moveto(0x84);
                stringout(snum);
            }
            else
            {
                //high+=turn;
                itoa(high, snum, 10);//HERE
                moveto(0x8d);
                stringout("   ");
                moveto(0x8d);
                stringout(snum);
            }
            change=0;
        }
    }
    return 1;
}
ISR(PCINT1_vect)
{
    int turn=0;
    int pstate=state;
    int bitA = PINC & 0b00000010;
    int bitB = PINC & 0b00000100;
    bitA=bitA>>1;        
    bitB=bitB>>1;
    state=bitA+bitB;
    if((pstate==0&&state==1)||(pstate==1&&state==3)||(pstate==3&&state==2)||(pstate==2&&state==0))
    {
        turn=1;
    }
    if((state==0&&pstate==1)||(state==1&&pstate==3)||(state==3&&pstate==2)||(state==2&&pstate==0))
    {
        turn =-1;
    }
    if(mode)
    {
        low+=turn;//HERE
    }
    else
    {
        high+=turn;//HERE
    }
    high++;//test code, high is still not modified in the main()
    change=1;//HERE
}
\$\endgroup\$
  • \$\begingroup\$ Are you sure those if statements ever set the value of turn? Maybe put turn=1 right before the if(mode) and see what happens. \$\endgroup\$ – PeterJ Dec 5 '14 at 2:34
  • \$\begingroup\$ I thought of that earlier, edited my original post. Thanks! \$\endgroup\$ – Noidontknow Dec 5 '14 at 2:36
  • \$\begingroup\$ One other thing I spotted with your string buffers they probably should be larger and you might be overwriting those variables. Try changing the sizes from 5 to 7. \$\endgroup\$ – PeterJ Dec 5 '14 at 2:44
  • \$\begingroup\$ The ints low and high are usually only two digits, three digits at max. \$\endgroup\$ – Noidontknow Dec 5 '14 at 2:49
9
\$\begingroup\$

You've re-declared 'low' and 'high' as separate variables in your main function. The global variables won't show up in main() if you do that. Remove the duplicate declarations and try again.

\$\endgroup\$
  • \$\begingroup\$ Oh. I see now. Although I wonder why it wasn't caught by the compiler? In the other languages I've worked with, this type of error is always caught by the compiler. Thanks! \$\endgroup\$ – Noidontknow Dec 5 '14 at 2:52
  • 4
    \$\begingroup\$ It's not an error. C explicitly allows local variables with the same name as global variables. I think it's for source compatibility, so that adding a global variable doesn't force you to change existing code. en.wikipedia.org/wiki/Variable_shadowing \$\endgroup\$ – Adam Haun Dec 5 '14 at 3:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.