#include <avr/sleep.h>
#include <avr/interrupt.h>
#define INTERRUPT_PIN 2 // 选择一个支持中断的引脚
#define LED_PIN 13 // 用于指示状态的LED引脚
volatile bool shouldWakeUp = false; // 标志位,用于判断是否应该唤醒
void setup() {
pinMode(INTERRUPT_PIN, INPUT_PULLUP); // 设置中断引脚为输入模式,并启用内部上拉电阻
pinMode(LED_PIN, OUTPUT); // 设置LED引脚为输出模式
// 设置中断服务程序,当INTERRUPT_PIN发生变化时调用
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), wakeUp, FALLING);
// 设置睡眠模式为PWR_DOWN
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable(); // 启用睡眠模式
}
void loop() {
// 在这里,loop()函数实际上不会被执行,因为CPU已经停止运行
// 只有当外部中断触发时,才会执行wakeUp()函数
}
// 中断服务程序,当INTERRUPT_PIN引脚从高电平变为低电平时调用
void wakeUp() {
// 改变标志位,表示应该唤醒
shouldWakeUp = true;
handleWakeUp();
}
// 这是一个在ISR中不能调用的函数,因此我们需要一个额外的函数来实际执行唤醒后的操作
void handleWakeUp() {
// 当这个函数被调用时,说明我们已经从睡眠模式中唤醒
digitalWrite(LED_PIN, HIGH); // 点亮LED表示已唤醒
// 清除唤醒标志位
shouldWakeUp = false;
// 在这里可以添加其他你需要在唤醒后执行的代码
}
// 这是一个检查是否需要唤醒的函数,它可以在ISR之外调用
void checkWakeUp() {
Serial.println(F("c"));
if (shouldWakeUp) {
handleWakeUp();
sleep_disable(); // 禁用睡眠模式
}
}
// Arduino的ISR(中断服务程序)不能调用函数,所以我们需要使用这种方法来检查是否需要唤醒
ISR(INTERRUPT_VECTOR) {
checkWakeUp();
}
// 定义中断向量,这取决于你使用的Arduino板和引脚
#if defined(ARDUINO_AVR_UNO)
#define INTERRUPT_VECTOR INT2_vect
#else
// 对于其他Arduino板,你可能需要定义不同的中断向量
#error "Please define the correct interrupt vector for your board and pin"
#endif