Обработчик прерывания WDT
- Войдите на сайт для отправки комментариев
Пт, 26/08/2022 - 02:29
Всем привет!
В ходе разбора работы таймера WD, наткнулся на не понятную мне вещь.
Код почему-то работает корректно, несмотря на то, что в обработчике, я перед изменением регистра
(WDTCSR = 0), не устанавливал в 1 биты WDCE и WDE , как в примере из даташита:
WDTCSR |= (1 < WDCE) | (1 << WDE); И не обнулял перед этим бит WDRF в MCUSR
Если кто знает, объясните пжлст, почему всё-таки останавливается таймер, хотя вроде-как не должен?
Это такая особенность работы в прерывании? В даташите про это не нашёл.
Или просто где- то протупил?
//== Прерывание от WDT ========
void setup() {
Serial.begin(9600);
delay(300);
cli(); //==== НАСТРОЙКА WD таймера =======
// MCUSR &= ~(1<<WDRF); // необязательно
WDTCSR |= (1 << WDCE) | (1 << WDE);//разрешаем изменения в настройке WDT
WDTCSR = 0x47; //WDIE = 1(разреш. прерыван от WDT),WDE = 0(прерывание без сброса)
// делитель на 2 сек тайм-аут
sei();
}
ISR( WDT_vect ) {//если не был сброшен WDT
// asm volatile("wdr\n\t");
// MCUSR &= ~(1<<WDRF);
// WDTCSR |= (1<<WDCE) | (1<<WDE); эти строчки оказались ненужными))
WDTCSR = 0x00; //выключаем WDT
sei();
Serial.println("ERROR"); //здесь остановить мотор
while (1);
}
void loop() {
int a = 1;
int b = 3;
int m = 0;
Serial.print(a);
Serial.print(" ");
Serial.println(b);
Serial.println(" ");
//asm volatile("wdr\n\t"); //комментируем для проверки
for(int r = 0; r < 1001; r++){
for(int c = 0; c < 1001; c++){
m = a;
a = b;
b = m;
}
}
Serial.print(a);
Serial.print(" ");
Serial.println(b);
Serial.println(" ");
}
P.S. Если что плата Pro Mini, с загрузчиком от Uno (optiboot_atmega328) 16MHz
У вас WDT в режиме прерываний. Записью WDTCSR = 0 вы запрещаете прерывания записывая WDIE=0 (для этого WDCE не важен).
Выведите значение WDTCSR после ERROR и посмотрите.
Serial.println(WDTCSR,HEX);
У вас WDT в режиме прерываний. Записью WDTCSR = 0 вы запрещаете прерывания записывая WDIE=0 (для этого WDCE не важен).
Выводил WDTCSR в сериал , сразу после входа в обработчик (sei() добавил конечно) WDTCSR = 71;
(0x47 как в Сетапе), а после ERROR WDTCSR= 7;
P.S. Спасибо, что разъяснили, почему программа работает - т.к. WDIE=0 это теперь понятно, но почему WDTCSR = 7; ?
P.P.S. Ещё раз спасибо, во всём разобрался. Так и должно работать.Теперь всё ясно
P.P.P.S. Что интересно, про WDIE в даташите написано, что
Выполнение соответствующего вектора прерывания автоматически очистит WDIE и WDIF аппаратно
Но, видимо это происходит уже после выхода из обработчика.
P.P.P.S. Что интересно, про WDIE в даташите написано, что
Выполнение соответствующего вектора прерывания автоматически очистит WDIE и WDIF аппаратно
Но, видимо это происходит уже после выхода из обработчика.
Видимо это справедливо для режима "Interrupt and System Reset" т.е. когда WDE=1
Видимо это справедливо для режима "Interrupt and System Reset" т.е. когда WDE=1
Вы правы. Если в Сетапе установить WDE = 1, то , как и положено, сначала отрабатывает прерывание, а затем ресет и так по кругу. В обработчик приходит и уходит WDTCSR = 15; (В1111), что значит ,что WDIE = 0;(хотя в сетапе было WDIE = 1).
В Сетап же ,естественно, после ресета, приходит до настройки WDTCRS = 0;
Ещё раз спасибо, помогли разобраться.