Bạn chắc chắn có thể. Theo biểu dữ liệu, bộ đếm thời gian theo dõi có thể được thiết lập để đặt lại MCU hoặc gây gián đoạn khi kích hoạt. Có vẻ như bạn quan tâm nhiều hơn đến khả năng ngắt.
WDT thực sự dễ cài đặt hơn Timer bình thường vì cùng lý do nó ít hữu ích hơn: ít tùy chọn hơn. Nó chạy trên đồng hồ 128kHz được hiệu chỉnh bên trong, có nghĩa là thời gian của nó không bị ảnh hưởng bởi tốc độ xung nhịp chính của MCU. Nó cũng có thể tiếp tục chạy trong các chế độ ngủ sâu nhất để cung cấp nguồn thức dậy.
Tôi sẽ xem qua một vài ví dụ về biểu dữ liệu cũng như một số mã tôi đã sử dụng (trong C).
Bao gồm các tệp và định nghĩa
Để bắt đầu, có lẽ bạn sẽ muốn bao gồm hai tệp tiêu đề sau để mọi thứ hoạt động:
#include <avr/wdt.h> // Supplied Watch Dog Timer Macros
#include <avr/sleep.h> // Supplied AVR Sleep Macros
Ngoài ra, tôi sử dụng Macro <_BV (BIT)> được xác định trong một trong các tiêu đề AVR tiêu chuẩn như sau (có thể quen thuộc với bạn hơn):
#define _BV(BIT) (1<<BIT)
Bắt đầu mã
Khi MCU được khởi động lần đầu tiên, bạn thường khởi tạo I / O, thiết lập bộ hẹn giờ, v.v ... Ở đây đây là thời điểm tốt để đảm bảo WDT không gây ra thiết lập lại vì nó có thể thực hiện lại, giữ chương trình của bạn một vòng lặp không ổn định.
if(MCUSR & _BV(WDRF)){ // If a reset was caused by the Watchdog Timer...
MCUSR &= ~_BV(WDRF); // Clear the WDT reset flag
WDTCSR |= (_BV(WDCE) | _BV(WDE)); // Enable the WD Change Bit
WDTCSR = 0x00; // Disable the WDT
}
Thiết lập WDT
Sau đó, sau khi bạn đã thiết lập phần còn lại của chip, hãy làm lại WDT. Thiết lập WDT yêu cầu "trình tự thời gian", nhưng thực sự rất dễ thực hiện ...
// Set up Watch Dog Timer for Inactivity
WDTCSR |= (_BV(WDCE) | _BV(WDE)); // Enable the WD Change Bit
WDTCSR = _BV(WDIE) | // Enable WDT Interrupt
_BV(WDP2) | _BV(WDP1); // Set Timeout to ~1 seconds
Tất nhiên, các ngắt của bạn sẽ bị vô hiệu hóa trong mã này. Hãy chắc chắn để kích hoạt lại chúng sau đó!
cli(); // Disable the Interrupts
sei(); // Enable the Interrupts
Thường trình dịch vụ ngắt WDT
Điều tiếp theo cần lo lắng là xử lý IST WDT. Điều này được thực hiện như vậy:
ISR(WDT_vect)
{
sleep_disable(); // Disable Sleep on Wakeup
// Your code goes here...
// Whatever needs to happen every 1 second
sleep_enable(); // Enable Sleep Mode
}
MCU ngủ
Thay vì đặt MCU để ngủ bên trong IST WDT, tôi khuyên bạn chỉ nên bật chế độ ngủ ở cuối ISR, sau đó yêu cầu chương trình MAIN đặt MCU vào chế độ ngủ. Theo cách đó, chương trình thực sự rời khỏi ISR trước khi đi ngủ, và nó sẽ thức dậy và quay trở lại vào WDT ISR.
// Enable Sleep Mode for Power Down
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set Sleep Mode: Power Down
sleep_enable(); // Enable Sleep Mode
sei(); // Enable Interrupts
/****************************
* Enter Main Program Loop *
****************************/
for(;;)
{
if (MCUCR & _BV(SE)){ // If Sleep is Enabled...
cli(); // Disable Interrupts
sleep_bod_disable(); // Disable BOD
sei(); // Enable Interrupts
sleep_cpu(); // Go to Sleep
/****************************
* Sleep Until WDT Times Out
* -> Go to WDT ISR
****************************/
}
}