Что то я заблудился в трех соснах. Тестовая задача: включить вачдог на Атмеге8 с максимальным периодом 2.2 сек и проверить как оно работает. Желательно без библиотеки, напрямую, так сказать. Сначала запуск программы с быстрым миганием, потом медленное мигание со сбросом вачдога, потом бесконечный цикл в котором вачдог наконец должен сработать и резетить МК. Код: Код (C++): // сброс вачдога #define wdt_reset() \ __asm__ __volatile__ ("wdr") void setup() { WDT_off(); pinMode(13, OUTPUT); // быстро мигаем при запуске for (int i = 0; i < 20; i++) { digitalWrite(13, !digitalRead(13)); delay(20); } WDT_on(); // вкл вачдог } void loop() { for (int i = 0; i < 20; i++) { // мигаем медленно со сбросом вачдога digitalWrite(13, !digitalRead(13)); wdt_reset(); delay(200); } while (true); // зависаем (через 2.2 сек должен быть резет) } inline void WDT_on(void) { // запуск вачдога с периодом 2.2с WDTCR = 0b00001111; // WDTCR = 0x00; // WDTCR |= ((1 << WDE) | (1 << WDP2) | (1 << WDP1) | (1 << WDP0)); } inline void WDT_off(void) { // выкл вачдога wdt_reset(); WDTCR |= (1 << WDCE) | (1 << WDE); WDTCR = 0x00; } На деле же после быстрого мигания МК сразу резетится не выждав ни фазы медленного мигания ни даже обещанных 2.2 сек. То есть он запускается, но как будь то с гораздо меньшим периодом или запускается не так. В чем причина?
Все, разобрался сам. Оказывается бит WDCE надо подпинывать не только при выключении собаки, но и при включении. Если кому интересно, то готовый код выглядит так: Код (C++): // сброс вачдога #define wdt_reset() \ __asm__ __volatile__ ("wdr") void setup() { WDT_off(); // выкл вачдог pinMode(13, OUTPUT); // быстро мигаем при запуске for (int i = 0; i < 20; i++) { digitalWrite(13, !digitalRead(13)); delay(50); } WDT_on(); // вкл вачдог } void loop() { for (int i = 0; i < 20; i++) { // мигаем медленно со сбросом вачдога digitalWrite(13, !digitalRead(13)); wdt_reset(); delay(250); } while (true); // зависаем (через 2.2 сек должен быть резет) } inline void WDT_on(void) { // запуск вачдога с периодом 2.2с WDTCR = 0x1F; WDTCR |= (1 << WDE) | (1 << WDP2) | (1 << WDP1) | (1 << WDP0); // то же самое побитно: // WDTCR = 0b00011111; // WDTCR = 0b00001111; } inline void WDT_off(void) { // выкл вачдога wdt_reset(); WDTCR |= (1 << WDCE) | (1 << WDE); WDTCR = 0x00; // побитно: // WDTCR = 0b00011000; // WDTCR = 0b00000000; }
Еще возник вот такой нестандартный вопрос: разумно ли сделать сброс ватчдога через прерывание по таймеру? Иными словами, в случае если МК зависает зависают ли таймеры или эти процессы никак не связаны и вачдог будет исправно сбрасываться на зависшем МК?
Интересный вопрос. Полагаю, сбрасывать собаку в прерывании не имеет смысла. Собака охраняет "весь дом". Но ничто не мешает поэкспериментировать. Сделайте в теле программы какую-нибудь безумную задержку, или, например, запись в массив с выходом за границы с задержкой и миганием диодом после записи каждого элемента, а собаку - в прервыание, и посмотрите что получится.
IMHO -- не разумно, хотя можно убедить в обратном. У watchdog'а свой таймер с прерыванием, зачем лепить еще один?