#interrupt #atmega
#прерывание #atmega
Вопрос:
Я пытаюсь заставить цикл регулярно выполняться каждые 50 миллисекунд на Atmega 2560. Использование простой функции задержки не сработает, потому что общее время цикла в конечном итоге равно времени, которое потребовалось для выполнения других функций в цикле, плюс ваше время задержки. Это работает еще хуже, если вызовы ваших функций занимают переменное время, что обычно и происходит.
Чтобы решить эту проблему, я реализовал простой класс timer:
volatile unsigned long timer0_ms_tick;
timer::timer()
{
// Set timer0 registers
TCCR0A = 0b00000000; // Nothing here
TCCR0B = 0b00000000; // Timer stopped, begin function start by setting last three bits to 011 for prescaler of 64
TIMSK0 = 0b00000001; // Last bit to 1 to enable timer0 OFV interrupt enable
sei(); // Enable global interrupts
}
void timer::start()
{
timer0_ms_tick = 0;
// Set timer value for 1ms tick (2500000 ticks/sec)*(1 OFV/250 ticks) = 1000OVF/sec
// 256ticks - 250ticks - 6 ticks, but starting at 0 means setting to 5
TCNT0 = 5;
// Set prescaler and start timer
TCCR0B = 0b00000011;
}
unsigned long timer::now_ms()
{
return timer0_ms_tick;
}
ISR(TIMER0_OVF_vect)
{
timer0_ms_tick =1;
TCNT0 = 5;
}
Основной цикл использует это следующим образом:
unsigned long startTime, now;
while(true)
{
startTime = startup_timer.now_ms();
/* Loop Functions */
// Wait time step
now = startup_timer.now_ms();
while(now-startTime < 50)
{
now = startup_timer.now_ms();
}
Serial0.print(ltoa(now,time_string, 10));
Serial0.writeChar('-');
Serial0.print(ltoa(startTime,time_string, 10));
Serial0.writeChar('=');
Serial0.println(ltoa(now-startTime,time_string, 10));
}
Мой вывод выглядит следующим образом:
11600-11550=50
11652-11602=50
11704-11654=50
11756-11706=50
12031-11758=273
11828-11778=50
11880-11830=50
11932-11882=50
11984-11934=50
12036-11986=50
12088-12038=50
12140-12090=50
12192-12142=50
12244-12194=50
12296-12246=50
12348-12298=50
12400-12350=50
12452-12402=50
12504-12454=50
12556-12506=50
12608-12558=50
12660-12610=50
12712-12662=50
12764-12714=50
12816-12766=50
12868-12818=50
12920-12870=50
12972-12922=50
13024-12974=50
13076-13026=50
13128-13078=50
13180-13130=50
13232-13182=50
13284-13234=50
13336-13286=50
13388-13338=50
13440-13390=50
13492-13442=50
13544-13494=50
13823-13546=277
13620-13570=50
Кажется, что большую часть времени это работает хорошо, но время от времени что-то странное происходит со значениями синхронизации. Я думаю, что это как-то связано с прерыванием, но я не уверен, что именно. Любая помощь была бы высоко оценена.
Комментарии:
1. Есть ли у вас какие-либо другие прерывания, которые вы обслуживаете?
2. Других прерываний быть не должно.