Обработчик прерывания 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;
Ещё раз спасибо, помогли разобраться.