電路接線圖

millis()函式:從開機後到當下所經歷的毫秒時間。
例:LED燈每秒改變一次狀態。
const int ledPin = 15; // LED接腳
unsigned long previousMillis = 0; // 前一次的millis()時間
const long interval = 1000; // 預設計時的時間
bool state = HIGH; // LED狀態,初始值為HIGH(OFF)
void setup() {
pinMode(ledPin, OUTPUT); // 宣告ledPin為輸出腳
digitalWrite(ledPin, state); // 輸出狀態
}
void loop() {
unsigned long currentMillis = millis(); // 當前的millis()時間
if (currentMillis - previousMillis >= interval) // 若達到預設計時的時間
{
//---------------------------------------------------------------------
// 每經過一個interval的時間,要做的事
//---------------------------------------------------------------------
state = !state; // 改變LED狀態
digitalWrite(ledPin, state); // 輸出狀態
//---------------------------------------------------------------------
previousMillis = currentMillis; // 更新前一次的millis()時間
}
}
按鈕開關若使用delay()做為防彈跳延遲時間,程式會暫停一段時間,為避免造成阻塞,可改用millis()的方式計算防彈跳延遲時間,基本做法如下:
const int pb = 25; // 按鈕開關接腳
bool lastButtonState = HIGH; // 按鈕開關前一次的狀態
unsigned long lastDebounceTime = 0; // 按鈕開關前一次狀態改變時的millis()時間
int debounceDelay = 80; // 防彈跳預設的延遲時間
void setup() {
Serial.begin(9600); // 啟用串列埠監看視窗
pinMode(pb, INPUT); // 宣告pb為輸入腳,並使用外部拉上電阻
}
void loop() {
unsigned long currentTime = millis(); // 當前的millis()時間
bool buttonState = digitalRead(pb); // 當前的按鈕開關狀態:未按下(HIGH),按下(LOW)
// 若按鈕開關狀態發生變化,且超過防彈跳預設的延遲時間
if ((buttonState != lastButtonState) && (currentTime - lastDebounceTime) > debounceDelay)
{
// --------------------------------------------------------------------------------------
if (lastButtonState == HIGH && buttonState == LOW) // 若按鈕從未按下(HIGH)到按下(LOW)
{
// 按鈕按下時,想做的事
Serial.println("Button pressed.");
}
else if (lastButtonState == LOW && buttonState == HIGH) // 若按鈕從按下(LOW)到未按下(HIGH)
{
// 按鈕放開時,想做的事
Serial.println("Button released.");
}
lastButtonState = buttonState; // 更新按鈕狀態
// --------------------------------------------------------------------------------------
lastDebounceTime = currentTime; // 更新前一次狀態改變時的millis()時間
}
}
若要判斷按鈕開關是否被長按,可參考下列程式:
const int pb = 25; // 按鈕開關接腳
bool lastButtonState = HIGH; // 按鈕開關前一次的狀態
unsigned long lastDebounceTime = 0; // 按鈕開關前一次狀態改變時的millis()時間
int debounceDelay = 80; // 防彈跳預設的延遲時間
unsigned long buttonDownTime = 0; // 按鈕開關被按下的時間
unsigned long longPressTime = 1500; // 長按時間
int count = 0; // 按鈕計數器
void setup() {
Serial.begin(9600); // 啟用串列埠監看視窗
pinMode(pb, INPUT); // 宣告pb為輸入腳,並使用外部拉上電阻
}
void loop() {
unsigned long currentTime = millis(); // 當前的millis()時間
bool buttonState = digitalRead(pb); // 當前的按鈕開關狀態:未按下(HIGH),按下(LOW)
// 若按鈕開關狀態發生變化,且超過防彈跳預設的延遲時間
if ((buttonState != lastButtonState) && (currentTime - lastDebounceTime) > debounceDelay)
{
// --------------------------------------------------------------------------------------
if (lastButtonState == HIGH && buttonState == LOW) // 若按鈕從未按下(HIGH)到按下(LOW)
{
// 按鈕按下時,想做的事
Serial.println("Button pressed.");
buttonDownTime = currentTime; //記錄按鈕按下的時間
count++; // 計數器加1
Serial.print("Button pressed count: "); // 印出計數器內容
Serial.println(count); // 印出計數器內容
}
else if (lastButtonState == LOW && buttonState == HIGH) // 若按鈕從按下(LOW)到未按下(HIGH)
{
// 按鈕放開時,想做的事
Serial.println("Button released.");
if((currentTime - buttonDownTime) >= longPressTime)
{
Serial.println("Long press detected, count reset.");
count=0; // 清空計數器
Serial.print("Button pressed count: "); // 印出計數器內容
Serial.println(count); // 印出計數器內容
}
}
lastButtonState = buttonState; // 更新按鈕狀態
// --------------------------------------------------------------------------------------
lastDebounceTime = currentTime; // 更新前一次狀態改變時的millis()時間
}
}
作業練習:
- 開機後,8個LED燈全亮,1秒後全滅。
- 每按一下按鈕開關,從自LED0到LED7依序增加點亮1個燈,8個燈全亮後全滅後,循環顯示。
- 任何狀態下,只要長按按鈕開關1.5秒以上,8個燈全滅。
- 各種燈亮的狀態必須顯示在監看視窗上。
- 在Wokwi網站上進行模擬,並完成實體接線。