I am trying to do quadrature decoding using atmel xmega avr microcontroller. Xmega has only 16-bit
counters. And in addition I have used up all the available timers.
Now to make 32-bit
counter I have used one 16-bit
counter and in its over/under flow interrupt
I have increment/decrement a 16-bit global variable, so that by combining them we can make 32-bit counter.
ISR(timer_16bit)
{
if(quad_enc_mov_forward)
{
timer_over_flow++;
}
else if (quad_enc_mov_backward)
{
timer_over_flow--;
}
}
so far it is working fine. But I need to use this 32-bit value in various tasks running parallel. I'm trying to read 32-bit values as below
uint32_t current_count = timer_over_flow;
current_count = current_count << 16;
current_count = current_count + timer_16bit_count;
`timer_16_bit_count` is a hardware register.
Now the problem I am facing is when I read the read timer_over_flow
to current_count
in the first statement and by the time I add the timer_16bit_count
there may be overflow and the 16bit
timer may have become zero
. This may result in taking total wrong value.
And I am trying to read this 32-bit value in multiple tasks .
Is there a way to prevent this data corruption and get the working model of 32-bit value.
Details sought by different members:
My motor can move forward or backward and accordingly counter increments/decrements.
In case of ISR, before starting my motor I'm making the global variables(
quad_enc_mov_forward
&quad_enc_mov_backward
) set so that if there is a overflow/underflowtimer_over_flow
will get changed accordingly.Variables that are modified in the ISR are declared as
volatile
.Multiple tasks means that I'm using RTOS Kernel with about 6 tasks (mostly 3 tasks running parallel).
In the XMEGA I'm directly reading
TCCO_CNT
register for the lower byte.