arduino四位共阴极数码管按键计时器
·
一·所需材料
二·接线图
三·代码
四·实物效果
图
五·拓展
一·所需材料
Arduino Uno控制器:1块
四位共阴数码管:1个(关键点:讲义教程多为共阳,如果你手头的是共阴,必须修改代码逻辑!)
按键开关:1个
10kΩ 电阻:1个(下拉电阻)
面包板及跳线:若干
二·接线图
三·代码
/*
* 项目名称:Arduino四位数码管计时系统 (初代共阴极版)
* 硬件配置:
* - 段选 A-H: D2-D9
* - 位选 COM1-4: D10-D13
* - 按键: D1
* 状态:存在阻塞Bug
* 说明:按住按键不放时,数码管会熄灭
*/
// 按键定义
#define KEY_PIN 1
// 数码管段选引脚 (a, b, c, d, e, f, g, dp) -> (2, 3, 4, 5, 6, 7, 8, 9)
int ledPins[] = {2, 3, 4, 5, 6, 7, 8, 9};
// 数码管位选引脚 (千, 百, 十, 个) -> (COM1, COM2, COM3, COM4) -> (10, 11, 12, 13)
int segPins[] = {10, 11, 12, 13};
// 共阴极段码表 (0-9)
// 1(HIGH) 亮
const unsigned char DuanMa[10] = {
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f
};
unsigned char displayTemp[4];
bool countEnable = false;
int currentNumber = 0;
// 按键状态记录
bool lastKeyState = LOW;
bool currentKeyState = LOW;
void setup() {
// 初始化段选
for (int i = 0; i < 8; i++) pinMode(ledPins[i], OUTPUT);
// 初始化位选
for (int i = 0; i < 4; i++) {
pinMode(segPins[i], OUTPUT);
digitalWrite(segPins[i], HIGH); // 共阴初始关闭
}
pinMode(KEY_PIN, INPUT);
updateDisplayBuffer(0);
}
// ❌ 存在问题的按键处理函数
void handleKeyPress() {
currentKeyState = digitalRead(KEY_PIN);
// 检测按下瞬间
if (currentKeyState == HIGH && lastKeyState == LOW) {
delay(20); // 阻塞1:延时消抖
// 再次确认
if (digitalRead(KEY_PIN) == HIGH) {
countEnable = !countEnable;
// ☠️ 阻塞2:死循环等待按键松开
// 只要你不松手,程序就永远卡在这里,回不到 loop()
while(digitalRead(KEY_PIN) == HIGH);
}
}
lastKeyState = currentKeyState;
}
void loop() {
// 1. 处理按键
handleKeyPress();
// 2. 计时逻辑
static unsigned long lastTimerTime = 0;
if(countEnable && millis() - lastTimerTime >= 1000) {
lastTimerTime = millis();
currentNumber = (currentNumber + 1) % 10000;
updateDisplayBuffer(currentNumber);
}
// 3. 动态扫描
// 如果 handleKeyPress 卡住了,这里就不会执行 -> 数码管熄灭
refreshDisplay();
}
void updateDisplayBuffer(int num) {
displayTemp[0] = DuanMa[num / 1000];
displayTemp[1] = DuanMa[(num % 1000) / 100];
displayTemp[2] = DuanMa[(num % 100) / 10];
displayTemp[3] = DuanMa[num % 10];
}
void refreshDisplay() {
static unsigned long lastScanTime = 0;
static int currentDigit = 0;
if(millis() - lastScanTime >= 3) {
lastScanTime = millis();
// 消影
for(int i=0; i<8; i++) digitalWrite(ledPins[i], LOW);
digitalWrite(segPins[currentDigit], HIGH); // 关位选
currentDigit = (currentDigit + 1) % 4;
digitalWrite(segPins[currentDigit], LOW); // 开新位选
for(int i=0; i<8; i++) digitalWrite(ledPins[i], bitRead(displayTemp[currentDigit], i));
}
}
四·实物效果
图
五·拓展
for 循环最常用,但理解 while 和 do...while 的执行流程同样重要。
以上为for循环
for(int ledpin = 0; ledpin < ledCount; ledpin++) {
pinMode(ledPins[ledpin], OUTPUT);
}
改为while循环便是:
int ledpin = 0;
while(ledpin < ledCount) {
pinMode(ledPins[ledpin], OUTPUT);
ledpin++;
}
但如果是do...while的话
int ledpin = 0;
do {
pinMode(ledPins[ledpin], OUTPUT);
ledpin++;
} while(ledpin < ledCount);
以上不同语句的代码各有优势,
for循环
· 优势:最适合已知循环次数的场景
· 特点:将初始化、条件判断、迭代更新集中在一行,结构紧凑
· 典型场景:遍历数组、固定次数的计算
while循环
· 优势:最适合“先判断后执行”的逻辑
· 特点:条件检查在前,可能一次都不执行
· 典型场景:读取输入直到特定值、条件驱动的循环
do...while循环
· 优势:确保至少执行一次
· 特点:先执行循环体,后检查条件
· 典型场景:菜单显示、至少需要执行一次的操作
选择建议:
· 明确次数 → 用for
· 条件先行 → 用while
· 至少一次 → 用do...while
更多推荐
所有评论(0)