目录
一. 所需硬件
Arduino Uno控制器
1个四位共阴数码管
1个10k 欧姆电阻
1个按键
1个面包版
条线若干
二. 连接示意图
三. 程序
// 数码管a,b,c,d,e,f,g,dp对应引脚
#define SEG_A 7
#define SEG_B 8
#define SEG_C 9
#define SEG_D 10
#define SEG_E 11
#define SEG_F 12
#define SEG_G 13
#define SEG_H A0
#define COM1 2
#define COM2 3
#define COM3 5
#define COM4 6
#define KEY_PIN 4
int ledcount = 8;
int segCount = 4;
long previousMillis = 0;
// 数码管段码表(0-9,共阴极)
const unsigned char DuanMa[10] = {
0x3f, // 0: 00111111
0x06, // 1: 00000110
0x5b, // 2: 01011011
0x4f, // 3: 01001111
0x66, // 4: 01100110
0x6d, // 5: 01101101
0x7d, // 6: 01111101
0x07, // 7: 00000111
0x7f, // 8: 01111111
0x6f // 9: 01101111
};
int ledPins[] = {7,8,9,10,11,12,13,A0};
int segPins[] = {2,3,5,6};
// 显示缓冲区:存储四位数码管的段码
unsigned char displayTemp[4];
// 全局变量:计数启停标志、按键状态(消抖)、计数使能
bool countEnable = false;
bool lastkeystate = LOW;
bool currentkeystate = LOW;
// 数码管段码输出函数(消影处理)
void deal(unsigned char value) {
// 关闭所有段,消影
for(int i=0; i<8; i++) {
digitalWrite(ledPins[i], LOW);
}
delayMicroseconds(100); // 100微秒消影
// 输出段码
for(int i=0; i<8; i++) {
digitalWrite(ledPins[i], bitRead(value, i));
}
}
// 按键处理函数:检测按键状态,控制计数启停(消抖处理)
void handleKeyPress() {
// 读取当前按键状态(按下为高电平,需外接上拉/下拉匹配)
currentkeystate = digitalRead(KEY_PIN);
// 按键消抖:当前状态与上一次不同,且稳定为高电平(按下)
if(currentkeystate == HIGH && lastkeystate == LOW) {
delay(20); // 消抖延迟20ms
// 再次确认按键按下(避免误触)
if(digitalRead(KEY_PIN) == HIGH) {
countEnable = !countEnable; // 翻转计数使能状态
// 等待按键释放(避免重复触发)
while(digitalRead(KEY_PIN) == HIGH);
}
}
// 更新上一次按键状态
lastkeystate = currentkeystate;
}
void setup() {
// 初始化数码管段引脚
for(int ledpin = 0; ledpin<ledcount; ledpin++) {
pinMode(ledPins[ledpin], OUTPUT);
}
// 初始化数码管位引脚
for(int segpin = 0; segpin<segCount; segpin++) {
pinMode(segPins[segpin], OUTPUT);
}
// 初始化按键引脚(默认输入,需外接上拉电阻,按下为高电平)
pinMode(KEY_PIN, INPUT);
// 初始化显示缓冲区为0
displayTemp[0] = DuanMa[0];
displayTemp[1] = DuanMa[0];
displayTemp[2] = DuanMa[0];
displayTemp[3] = DuanMa[0];
}
void loop() {
static unsigned int num = 0;
static unsigned long lastupdateTime = 0;
static unsigned long lastscanTime = 0;
static int currentDigit = 0;
// 1. 处理按键逻辑(每次循环检测)
handleKeyPress();
// 2. 仅当计数使能时,更新数字(1秒加1)
if(countEnable && millis() - lastupdateTime >= 1000) {
lastupdateTime = millis();
num = (num + 1) % 10000; // 四位数码管,计数0-9999循环
// 更新显示缓冲区
displayTemp[0] = DuanMa[num / 1000]; // 千位
displayTemp[1] = DuanMa[(num % 1000) / 100]; // 百位
displayTemp[2] = DuanMa[(num % 100) / 10]; // 十位
displayTemp[3] = DuanMa[num % 10]; // 个位
}
// 3. 数码管动态扫描(每3ms扫描一位,保证显示稳定)
if(millis() - lastscanTime >= 3) {
lastscanTime = millis();
// 步骤1:关闭当前数码管(消影)
deal(0x00); // 关闭所有段
digitalWrite(segPins[currentDigit], HIGH); // 关闭当前位选
// 步骤2:切换到下一个数码管
currentDigit = (currentDigit + 1) % 4;
// 步骤3:打开新数码管并显示内容
digitalWrite(segPins[currentDigit], LOW); // 打开新位选
deal(displayTemp[currentDigit]); // 显示对应段码
}
}
1. 引脚与常量定义
这部分用 #define 和数组定义了数码管段引脚(SEG_A~SEG_H)、位选引脚(COM1~COM4)、按键引脚(KEY_PIN),以及段码表 DuanMa (存储0-9的共阴极数码管段码),同时定义了数码管段数、位数等常量,方便后续修改硬件引脚。
2. 全局变量声明
声明了显示缓冲区 displayTemp (存储四位数码管要显示的段码)、计数使能标志 countEnable (控制计数启停)、按键状态变量 lastkeystate/currentkeystate (用于按键消抖),还有计时相关的 previousMillis 等变量,全局变量可在多个函数中共享数据。
3. 段码输出函数 deal()
这是数码管消影和段码输出的核心函数,先关闭所有段引脚消去残影,再根据传入的段码值,通过 bitRead 函数控制每个段引脚的高低电平,实现对应数字的显示。
4. 按键处理函数 handleKeyPress()
实现按键消抖和计数启停控制:先读取当前按键状态,对比上一次状态,若检测到按键按下则延迟20ms二次确认,确认后翻转 countEnable 的状态,同时等待按键释放避免重复触发,最后更新上一次按键状态。
5. 初始化函数 setup()
在Arduino上电后只执行一次,功能是将数码管段引脚、位选引脚设为输出模式,按键引脚设为输入模式,同时把显示缓冲区初始化为全0,确保开机时数码管显示 0000 。
6. 主循环函数 loop()
Arduino会反复执行这个函数,包含三个核心逻辑:调用 handleKeyPress() 检测按键状态;若 countEnable 为真且间隔1秒,计数器 num 加1并对10000取模(限制0-9999),再拆分 num 的千、百、十、个位,更新显示缓冲区;每3ms执行一次数码管动态扫描,依次切换四位数码管的位选引脚,调用 deal() 输出对应段码,利用人眼视觉暂留实现四位同时显示的效果。
四.功能
这份代码是基于Arduino的四位数码管按键启停计数器程序,核心实现数码管动态扫描显示、按键消抖控制计数启停的功能:
1. 数码管动态扫描:
通过快速切换四位数码管的位选引脚,配合段码输出,利用人眼视觉暂留实现“同时显示”效果,每3ms扫描一位保证显示无闪烁。
2. 按键消抖:
通过20ms延迟和二次检测,避免机械按键的抖动导致误触发,同时等待按键释放防止重复触发。
3. 计数逻辑:
计数使能时,每1秒数字加1,模10000实现0-9999循环,通过取模和除法拆分千、百、十、个位数字并转换为段码。
6565

被折叠的 条评论
为什么被折叠?



