使用timer中斷控制單科按鈕控制led左右方向,不使用loop迴圈
2025/01/09 17:13
瀏覽75
迴響0
推薦0
引用0
const byte forwardBtnPin = 3;
// 右到左,左到右
volatile bool forward = true;
int ledPins[] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; // The LED pins
int num = sizeof(ledPins) / sizeof(int);
// 目前在哪個 LED 上進行亮滅
volatile int ledIdx = 0;
void setup() {
// 設置 LED Pins
for (int i = 0; i < num; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW); // 確保所有 LED 初始熄滅
}
// 設置按鈕
pinMode(forwardBtnPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(forwardBtnPin), forwardInterrupt, FALLING);
// 設置 Timer1,使用 16-bit 硬體計時器
noInterrupts(); // 禁止中斷
TCCR1A = 0; // 清除 TCCR1A 設定
TCCR1B = 0; // 清除 TCCR1B 設定
TCNT1 = 0; // 計數器初始值
// F_CPU = 16 MHz, Prescaler = 1024 -> 計數間隔 = (1 / (16MHz / 1024)) ≈ 64µs
// 200ms = 500,000µs -> 500,000 / 64 ≈ 7812
OCR1A = 7812; // 設置比較寄存器值
TCCR1B |= (1 << WGM12); // CTC 模式 (Clear Timer on Compare Match)
TCCR1B |= (1 << CS12) | (1 << CS10); // 設置 Prescaler = 1024
TIMSK1 |= (1 << OCIE1A); // 啟用比較匹配中斷
interrupts(); // 啟用中斷
}
void loop() {
// loop 函式內容保持空
}
// Timer1 中斷服務例程 (ISR)
ISR(TIMER1_COMPA_vect) {
// 熄滅當前 LED
if (forward) {
ledIdx += 1;
if(ledIdx >= num) ledIdx = 0;
} else {
ledIdx -= 1;
if(ledIdx <= 0) ledIdx = num - 1;
}
blink();
}
// 按鈕中斷服務例程
void forwardInterrupt() {
forward = !forward; // 切換方向
}
void blink() {
digitalWrite(ledPins[ledIdx], HIGH); // 點亮 LED
delay(200); // 延遲 200 毫秒
digitalWrite(ledPins[ledIdx], LOW); // 熄滅 LED
delay(200);
}
限會員,要發表迴響,請先登入



