七日内新公告:全站维护公告
  • 你好~!欢迎来到萌娘百科镜像站!如需查看或编辑,请联系本站管理员注册账号。
  • 本镜像站和其他萌娘百科的镜像站无关,请注意分别。

User:日向 无境/testsandbox

贴贴♀百科,万娘皆可贴的百科全书!转载请标注来源页面的网页链接,并声明引自贴贴百科。内容不可商用。
跳到导航 跳到搜索

虚拟仿真·倒计时器

参见:https://wokwi.com/projects/464970327855306753

// Arduino UNO + 4x4键盘 + TM1637数码管 倒计时
// 完全无库,纯底层代码
// 支持 0~59分59秒(1小时内)
// # = 开始/暂停 * = 清零

// —————— 引脚定义 ——————
#define CLK 11 // 数码管时钟
#define DIO 12 // 数码管数据

// 键盘行引脚:R1 R2 R3 R4
int rowPins[4] = {9, 8, 7, 6};
// 键盘列引脚:C1 C2 C3 C4
int colPins[4] = {5, 4, 3, 2};

// —————— 全局变量 ——————
int min = 0, sec = 0;
bool isRun = false;
unsigned long lastTime = 0;

// 数码管 0~9 段码表
byte segCode[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

// —————— 初始化 ——————
void setup() {
  // 初始化键盘
  for(int i=0; i<4; i++) {
    pinMode(rowPins[i], INPUT_PULLUP);
    pinMode(colPins[i], OUTPUT);
    digitalWrite(colPins[i], HIGH);
  }
  // 初始化数码管
  pinMode(CLK, OUTPUT);
  pinMode(DIO, OUTPUT);
  tmInit();
  tmBright(5);
  showTime();
}

// —————— 主循环 ——————
void loop() {
  char key = readKey();

  // —————— 按键处理 ——————
  if(key != 0){
    if(key >= '0' && key <= '9'){
      // 输入时间
      min = min * 10 + (key - '0');
      if(min > 59) min = 59;
      showTime();
    }
    else if(key == '#'){
      // 【开始 / 暂停】
      if(min == 0 && sec == 0) return;
      isRun = !isRun;
      lastTime = millis();
    }
    else if(key == '*'){
      // 【清零】
      min = 0;
      sec = 0;
      isRun = false;
      showTime();
    }
  }

  // —————— 倒计时运行 ——————
  if(isRun) {
    if(millis() - lastTime >= 1000) {
      lastTime = millis();
      sec--;
      if(sec < 0) {
        sec = 59;
        min--;
      }
      // 倒计时结束
      if(min < 0) {
        min = 0; sec = 0;
        isRun = false;
        alarm();
      }
      showTime();
    }
  }
}

// —————— 键盘读取函数 ——————
char readKey() {
  char keys[4][4] = {
    {'1','2','3','A'},
    {'4','5','6','B'},
    {'7','8','9','C'},
    {'*','0','#','D'}
  };
  for(int c=0; c<4; c++) {
    digitalWrite(colPins[c], LOW);
    for(int r=0; r<4; r++) {
      if(digitalRead(rowPins[r]) == LOW) {
        delay(20);
        if(digitalRead(rowPins[r]) == LOW){
          while(digitalRead(rowPins[r])==LOW);
          digitalWrite(colPins[c], HIGH);
          return keys[r][c];
        }
      }
    }
    digitalWrite(colPins[c], HIGH);
  }
  return 0;
}

// —————— 数码管显示时间 MM:SS ——————
void showTime() {
  byte data[4];
  data[0] = segCode[min / 10];
  data[1] = segCode[min % 10] | 0x80; // 冒号
  data[2] = segCode[sec / 10];
  data[3] = segCode[sec % 10];

  tmStart();
  tmWrite(0xC0);
  for(int i=0; i<4; i++) tmWrite(data[i]);
  tmStop();
}

// —————— 结束提醒(闪烁)——————
void alarm() {
  for(int i=0; i<6; i++) {
    tmClear();
    delay(200);
    showTime();
    delay(200);
  }
}

// —————— TM1637 底层驱动(无库)——————
void tmStart() {
  digitalWrite(CLK, HIGH);
  digitalWrite(DIO, HIGH);
  digitalWrite(DIO, LOW);
  digitalWrite(CLK, LOW);
}
void tmStop() {
  digitalWrite(CLK, LOW);
  digitalWrite(DIO, LOW);
  digitalWrite(CLK, HIGH);
  digitalWrite(DIO, HIGH);
}
void tmWrite(byte b) {
  for(int i=0; i<8; i++) {
    digitalWrite(CLK, LOW);
    digitalWrite(DIO, b & 1);
    b >>= 1;
    digitalWrite(CLK, HIGH);
  }
  digitalWrite(CLK, LOW);
  digitalWrite(DIO, HIGH);
  digitalWrite(CLK, HIGH);
}
void tmInit() {
  tmStart(); tmWrite(0x40); tmStop();
}
void tmBright(byte b) {
  tmStart(); tmWrite(0x88 | b); tmStop();
}
void tmClear() {
  tmStart(); tmWrite(0xC0);
  for(int i=0; i<4; i++) tmWrite(0x00);
  tmStop();
}