Contents ...
udn網路城邦
使用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);        

}

限會員,要發表迴響,請先登入