I'm working with an ATMega32u2 and I wrote a function which waits (hogging the CPU) for a given amount of milliseconds, but I have to convert the milliseconds to ticks.
Here's the function, please note that the 8,000,000 value is the Hz of the microcontroller, 1024 is the value of the prescaler (which slows down the TCNT1 timer), and the 1000 integer is just there to convert from milliseconds to seconds or microseconds:
void timer_delay_ms(uint16_t milliseconds)
{
if (milliseconds > 8388) {
printf("ERROR: Milliseconds cannot exceed 8388 as this will overflow TCNT1.");
return;
}
/* Why does this work? It correctly makes an LED flash at 7812 ticks (every second). */
uint16_t ticks = milliseconds * (8000000 / 1024) / 1000;
/* This doesn't work. It makes an LED flash super fast, at about 644 ticks.
uint16_t ticks = (milliseconds * 1000) / 128;
*/
/* Sets timer to 0. */
TCNT1 = 0;
while (TCNT1 <= ticks) {
continue;
}
}
I initially thought that C promotes integers during the evaluation of an expressions to types that are large enough to carry on with the evaluation without any overflow. However, it appears that it only promotes integers to int, which in the ATMega32u2 is 16 bits. So I tested this by comparing the flashing of an LED using 500 (ms) as the argument for this function (which should yield a waiting period of 3906 ticks) to a hardcoded version with what I think is going on, which is overflowing 16 bits. So ((500 * 1000) modulo (2^16 - 1)) divided by 128 yields 322 ticks, and the LED seems to indeed flash at the same rate as when the function tries to convert 500 milliseconds to ticks using the erroneous evaluation shown above. I'm not sure if this is what's actually going wrong so if someone could confirm this that would be great.