HOWTO · Arduino

在 Arduino 中制作计数器

可以使用 Arduino 中的循环制作计数器。

本页内容

要用 Arduino 制作计数器,请将按钮连接到数字输入引脚和 GND,每次按下只读取一次,让变量递增,并将数值打印到串口监视器。下面的示例适用于兼容 Uno 的开发板,并会在达到可配置的上限后将计数归零。内置 LED 或外接 LED 可用于提示按钮已被识别,但不能显示计数数值。

Arduino 计数器的工作原理

计数器是一个用于存储数字的变量;事件发生时,它的值会改变。在这个项目中,事件就是按下按钮。Arduino 会反复运行 loop() 并检查输入;当按钮从松开变为按下时,计数值增加一次。短暂的消抖间隔可以过滤实体开关闭合时可能产生的快速电气变化。

循环也可以重复固定次数的操作。例如,for 循环可以让 LED 闪烁五次后停止,这就是有限循环;Arduino 的 loop() 则会持续运行。这里的主程序使用持续运行的循环来监测按钮。

连接按钮和 LED

使用 INPUT_PULLUP 时,将按钮的一端连接到数字引脚 2,另一端连接到 GND。开发板的内部上拉电阻会在按钮松开时使输入保持 HIGH;按下按钮后,引脚会接到 GND,读数变为 LOW。采用这种接线方式时,不需要外接上拉电阻。

如果使用外接 LED,请将数字引脚 13 通过限流电阻连接到 LED 的阳极(长脚),再将阴极(短脚)连接到 GND。Uno 的内置 LED 通常连接到引脚 13;使用其他开发板时,请先查看引脚图。程序使用 LED_BUILTIN,以调用开发板定义的内置 LED 引脚。LED 电路的电流必须保持在开发板引脚的限制范围内。

编写并上传按钮计数器程序

下面的完整 C++ 源代码可以作为 Arduino IDE 中的草图使用。在桌面 C++ 构建中,随附的测试框架会提供三次按钮按下输入,让计数逻辑产生可见结果。将 resetAt 设为计数器应归零的第一个计数值;消抖间隔为 30 毫秒。

#ifdef ARDUINO
#include <Arduino.h>
#else
// Desktop harness for a deterministic button sequence.
#include <iostream>
using byte = unsigned char;
const int HIGH = 1, LOW = 0, INPUT_PULLUP = 2, OUTPUT = 3;
const int LED_BUILTIN = 13;
unsigned long mockNow = 0;
void pinMode(byte, int) {}
void digitalWrite(byte, int) {}
unsigned long millis() { return mockNow; }
int digitalRead(byte) {
  bool pressed = (mockNow >= 10 && mockNow < 50) ||
                 (mockNow >= 100 && mockNow < 140) ||
                 (mockNow >= 190 && mockNow < 230);
  return pressed ? LOW : HIGH;
}
struct MockSerial {
  void begin(int) {}
  void println(int value) { std::cout << value << '\n'; }
  void println(const char* value) { std::cout << value << '\n'; }
} Serial;
#endif

const byte buttonPin = 2;
const byte ledPin = LED_BUILTIN;
const unsigned long debounceMs = 30;
const int resetAt = 3;

int counter = 0;
int lastRawReading = HIGH;
int stableReading = HIGH;
unsigned long lastChangeTime = 0;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int reading = digitalRead(buttonPin);
  unsigned long now = millis();

  if (reading != lastRawReading) {
    lastRawReading = reading;
    lastChangeTime = now;
  }

  if (now - lastChangeTime >= debounceMs && reading != stableReading) {
    stableReading = reading;
    if (stableReading == LOW) {
      counter++;
      digitalWrite(ledPin, HIGH);
      Serial.println(counter);
      if (counter >= resetAt) {
        counter = 0;
        Serial.println("Counter reset");
      }
    } else {
      digitalWrite(ledPin, LOW);
    }
  }
}

#ifndef ARDUINO
int main() {
  setup();
  for (mockNow = 0; mockNow <= 230; mockNow += 10) loop();
}
#endif
1
2
3
Counter reset

在桌面测试框架中,提供的三次按下输入会达到 resetAt,因此输出会先显示每次计数,随后显示重置消息。

在 Arduino IDE 中,选择已连接的开发板和端口并上传草图,然后打开 Tools > Serial Monitor,将波特率设为 9600。每次计数时按下并松开按钮。串口监视器会打印 1、2 和 3;第三次按下后会打印 Counter reset,下一次按下则会打印 1。按钮保持稳定按下时 LED 会亮起,松开后熄灭。在硬件上,setup() 和 loop() 使用 Arduino 核心库;桌面测试框架则为相同的计数逻辑提供固定输入序列。

显示并重置计数

这个示例使用串口监视器显示数字。单个 LED 可以提示按钮按下已被识别,但无法显示计数值。若要在设备上显示数字,可以使用七段显示模块或 LCD,并接好所需线路、使用相应库;本草图没有实现这些显示功能。

计数器会在达到 resetAt 时自动重置:草图先打印达到的阈值,再将存储的计数值设为零并继续运行。将 resetAt 改为另一个正整数即可设置不同的上限。代码没有使用单独的重置按钮。如果要添加重置按钮,请为它分配独立输入,并明确说明接线和行为,不要依赖未使用的引脚。

常见问题

需要哪些组件?

一块兼容 Uno 的开发板、一个按钮、跳线和一根 USB 线,就足以统计按钮按下次数并在电脑上查看结果。可以使用内置 LED,也可以添加带限流电阻的外接 LED 来提供视觉反馈。

可以使用其他显示屏吗?

可以。LCD 或七段显示器都能显示数字,但两者都需要合适的接线和显示代码。上面的示例会将数字发送到串口监视器,并且只用 LED 提示按钮按下。

如何更改重置上限?

编辑草图开头附近的 resetAt。计数器会在打印达到上限的数值后立即重置。

计数器可以递减吗?

可以。要制作递减计数器,可在识别到按钮按下时减一,并决定计数到达下限时应如何处理。上面的草图没有实现这一改动。

可以添加更多按钮吗?

可以。为每个额外按钮分配一个引脚、配置其输入,并设置不同的操作,例如递减或手动重置。根据所选的输入模式为每个按钮接线;主示例只处理一个按钮。