Global variable value doesn't change in ISR in C

72 Views Asked by At

Program works with the two timers in Atmega328P: Timer0 and TImer1. It uses Fast PWM mode for Timer0 to generate 4ms pulses with 50% duty cycle. Timer1 is used for input capture on signal edge. We connect PORTD6 and PORTB0 so UART should transmit the same number that represents the width of the specified PWM.

#include <avr/io.h>
#include <avr/interrupt.h>

void timer0Init()  // Timer0 setup
{
    TCCR0A = (1 << COM0A1) | (1 << WGM01) | (1 << WGM00);  // Fast PWM mode
    TCCR0B = (1 << CS02);  // prescaler clk/256
    OCR0A = 128;  // duty cycle 50%
    TIMSK0 = (1 << TOIE0);  // overflow interrupt enable
}

void timer1Init()  // Timer1 setup
{
    // normal mode, edge capture, prescaler clk/1024
    TCCR1B = (1 << ICNC1) | (1 << ICES1) | (1 << CS12) | (1 << CS10);
    TIMSK1 = (1 << ICIE1);  // capture interrupt enable
}

void usartInit()  // UART setup
{
    UCSR0B = (1 << TXEN0);  // transmission enable
    UCSR0C = (0 << USBS0) | (1 << UCSZ01) | (1 << UCSZ00);  // 1 stop-bit, package size - 8 bits
    UBRR0 = 103;  // baud rate - 9600 bit/s
}

uint16_t old = 0;
ISR(TIMER1_CAPT_vect)  // Timer1 capture interrupt
{   
    uint16_t temp = ICR1;  // current capture value
    uint16_t delta = 0;  // variable for difference between capture values
    
    if (temp > old)  // if the current one is greater than the previous one
    {
        delta = temp - old;  // difference = old - new
    }
    else  // otherwise (the timer has overflowed)
    {
        delta = 65535 - old + temp; // difference = 65535 - old + new
    }
    
    if ((UCSR0A & (1 << UDRE0)) != 0)  // if UART is not busy
    {
        UDR0 = delta;  // sending via UART
    }
    
    old = temp;
}


// 00 -> 40 -> 80 -> C0

int main(void)
{
    DDRD = 0x40;
    
    timer0Init();
    timer1Init();
    usartInit();
    
    sei();
    while (1) {}
}

The problem is that UART transmits not the same number but the sequence 00 -> 40 -> 80 -> C0 that are 0 -> 64 -> 128 -> 192 in decimal.

If I try to transmit the uint16_t old variable I get only zeroes so I think that old does not change its values in ISR.

0

There are 0 best solutions below