Arduino+数码管 = 量电压 | A+B problem | alphabet
材料
Arduino UNO R3、8041AS 七位数码管、若干导线、电阻、电位器、按钮、面包板。
量电压
从 A0 读入电压值,然后显示到数码管上即可。
voltage-display.ino
// https://www.lanpade.com/7-segment-led-dot-matrix/8041as.html
// === Pin Definitions ===
// Segments (a,b,c,d,e,f,g,dp) -> Arduino digital pins
const int segPins[8] = {3, 7, 11, 9, 8, 4, 12, 10};
// Digits (D1–D4, common cathode) -> Arduino pins
const int digitPins[4] = {2, 5, 6, 13};
// Segment map for numbers 0–9 (abcdefg, dp separate)
const byte numbers[10] = {
B11111100, // 0
B01100000, // 1
B11011010, // 2
B11110010, // 3
B01100110, // 4
B10110110, // 5
B10111110, // 6
B11100000, // 7
B11111110, // 8
B11110110 // 9
};
float voltage = 0.0; // measured voltage
// === Functions ===
void displayVoltage(float val) {
// Scale value: 0.000–5.000 -> up to 5000 (int)
int scaled = (int)(val * 1000);
int digits[4];
for (int i = 3; i >= 0; i--) {
digits[i] = scaled % 10;
scaled /= 10;
}
// Multiplex display
for (int d = 0; d < 4; d++) {
digitalWrite(digitPins[d], LOW); // enable digit
// set segments
for (int s = 0; s < 8; s++) {
bool on = bitRead(numbers[digits[d]], 7 - s);
digitalWrite(segPins[s], on ? HIGH : LOW);
}
// Add decimal point after first digit (x.xxx)
if (d == 0) digitalWrite(segPins[7], HIGH); // dp ON for digit 1
else digitalWrite(segPins[7], LOW);
delay(3);
digitalWrite(digitPins[d], HIGH); // disable digit
}
}
void setup() {
for (int i = 0; i < 8; i++) pinMode(segPins[i], OUTPUT);
for (int i = 0; i < 4; i++) {
pinMode(digitPins[i], OUTPUT);
digitalWrite(digitPins[i], HIGH); // all off initially
}
}
void loop() {
// Read analog input (0–5V → 0–1023)
int adcValue = analogRead(A0);
voltage = (adcValue * 5.0) / 1023.0;
// Refresh display continuously
displayVoltage(voltage);
}
可以进一步地,输出到 Serial,并取最近 \(10\) 次结果取平均值,以稳定测量结果。
voltage-display.ino
// https://www.lanpade.com/7-segment-led-dot-matrix/8041as.html
// === Pin Definitions ===
// Segments (a,b,c,d,e,f,g,dp) -> Arduino digital pins
const int segPins[8] = {3, 7, 11, 9, 8, 4, 12, 10};
// Digits (D1–D4, common cathode) -> Arduino pins
const int digitPins[4] = {2, 5, 6, 13};
// Segment map for numbers 0–9 (abcdefg, dp separate)
const byte numbers[10] = {
B11111100, // 0
B01100000, // 1
B11011010, // 2
B11110010, // 3
B01100110, // 4
B10110110, // 5
B10111110, // 6
B11100000, // 7
B11111110, // 8
B11110110 // 9
};
// === Functions ===
void displayVoltage(float val)
{
// Scale value: 0.000–5.000 -> up to 5000 (int)
int scaled = (int)(val * 1000);
int digits[4];
for (int i = 3; i >= 0; i--)
{
digits[i] = scaled % 10;
scaled /= 10;
}
// Multiplex display
for (int d = 0; d < 4; d++)
{
digitalWrite(digitPins[d], LOW); // enable digit
// set segments
for (int s = 0; s < 8; s++)
{
bool on = bitRead(numbers[digits[d]], 7 - s);
digitalWrite(segPins[s], on ? HIGH : LOW);
}
// Add decimal point after first digit (x.xxx)
if (d == 0)
digitalWrite(segPins[7], HIGH); // dp ON for digit 1
else
digitalWrite(segPins[7], LOW);
delay(3);
digitalWrite(digitPins[d], HIGH); // disable digit
}
}
const int NUM_SAMPLES = 10;
int samples[NUM_SAMPLES];
int sampleIndex = 0;
bool bufferFilled = false;
void setup()
{
for (int i = 0; i < 8; i++)
pinMode(segPins[i], OUTPUT);
for (int i = 0; i < 4; i++)
{
pinMode(digitPins[i], OUTPUT);
digitalWrite(digitPins[i], HIGH); // all off initially
}
pinMode(A0, INPUT);
Serial.begin(115200);
for (int i = 0; i < NUM_SAMPLES; i++)
{
samples[i] = 0;
}
}
void loop()
{
// Read analog input (0–5V → 0–1023)
int adcValue = analogRead(A0);
samples[sampleIndex] = adcValue;
sampleIndex++;
if (sampleIndex >= NUM_SAMPLES)
{
sampleIndex = 0;
bufferFilled = true;
}
float result = 0.0;
int total = bufferFilled ? NUM_SAMPLES : sampleIndex;
for (int i = 0; i < total; i++)
{
result += samples[i];
}
result *= 5. / 1023.;
result /= total;
Serial.print("Sensor reading: ");
Serial.print(adcValue);
Serial.print(" Voltage: ");
Serial.print((float)adcValue * 5. / 1023., 3);
Serial.print(" Average: ");
Serial.println(result, 3);
// Refresh display continuously
displayVoltage(result);
}

A+B problem
让我们先把操作数码管的代码简单封装一下,可以得到以下并不标准的 segment.cpp:
segment.cpp
#ifndef SEGMENT_H_
#define SEGMENT_H_
// https://www.lanpade.com/7-segment-led-dot-matrix/8041as.html
// === Pin Definitions ===
// Segments (a,b,c,d,e,f,g,dp) -> Arduino digital pins
const int segPins[8] = { 3, 7, 11, 9, 8, 4, 12, 10 };
// Digits (D1–D4, common cathode) -> Arduino pins
const int digitPins[4] = { 2, 5, 6, 13 };
// Segment map for numbers 0–9 (abcdefg, dp separate)
const byte numbers[10] = {
B11111100, // 0
B01100000, // 1
B11011010, // 2
B11110010, // 3
B01100110, // 4
B10110110, // 5
B10111110, // 6
B11100000, // 7
B11111110, // 8
B11110110 // 9
};
// Segment map for alphas a-z
const unsigned char alphas[26] = {
0xee, 0x3e, 0x9c, 0x7a, 0x9e, 0x8e, 0xbc, 0x6e, 0xf0, 0x70,
0xae, 0x1c, 0xec, 0x2a, 0x3a, 0xce, 0xe6, 0x8c, 0x92, 0x1e,
0x7c, 0x38, 0x7e, 0x26, 0x76, 0x5a
};
const unsigned long stayMillis = 3;
const unsigned long BATCHMILLIS = 500; // time for show four characters
const int strBufSize = 256;
const int shockShowMillis = 200;
const int shockHideMillis = 200;
byte getPattern(char c, bool dp) {
byte pattern = 0;
if (c >= '0' && c <= '9') {
pattern = numbers[c - '0'];
} else if (c >= 'A' && c <= 'Z') {
pattern = alphas[c - 'A'];
} else if (c >= 'a' && c <= 'z') {
pattern = alphas[c - 'a'];
}
if (dp) {
pattern |= B00000001;
}
return pattern;
}
void showSingle(byte pattern, int digit) {
if (!pattern) {
delay(stayMillis);
return;
}
digitalWrite(digitPins[digit], LOW);
for (int i = 0; i < 8; i++) {
digitalWrite(segPins[i], bitRead(pattern, 7 - i));
}
delay(stayMillis);
digitalWrite(digitPins[digit], HIGH);
}
int initStrDP(const char *str, const bool *DP, char *strBuf, bool *dpBuf) {
int bufLen = 0, strLen = strlen(str);
for (int i = 0; i < strLen; i++) {
if (str[i] == '.') {
if (bufLen > 0 && !dpBuf[bufLen - 1]) {
dpBuf[bufLen - 1] = true;
} else {
strBuf[bufLen] = ' ';
dpBuf[bufLen] = true;
bufLen++;
}
} else {
strBuf[bufLen] = str[i];
dpBuf[bufLen] = DP != NULL ? DP[i] : false;
bufLen++;
}
}
strBuf[bufLen] = '\0';
return bufLen;
}
struct displayLoopStateNode {
char strBuf[strBufSize];
bool dpBuf[strBufSize];
int bufLen;
unsigned long totalMillis;
unsigned long batchMillis;
unsigned long start;
unsigned long startBatch;
int currentRound;
int totalRounds;
bool active;
} _displayLoopState;
void displayLoopTaskInit(const char *str, const bool *DP = NULL, unsigned long totalMillis = 1000, unsigned long batchMillis = BATCHMILLIS) {
int strLen = strlen(str);
if (str == NULL || strLen == 0) return;
_displayLoopState.bufLen = initStrDP(str, DP, _displayLoopState.strBuf, _displayLoopState.dpBuf);
_displayLoopState.totalRounds = _displayLoopState.bufLen + 4;
_displayLoopState.batchMillis = batchMillis;
_displayLoopState.totalMillis = totalMillis;
unsigned long requiredTotal = _displayLoopState.totalRounds * batchMillis;
if (requiredTotal > totalMillis) {
_displayLoopState.batchMillis = totalMillis / _displayLoopState.totalRounds;
}
_displayLoopState.start = millis();
_displayLoopState.startBatch = _displayLoopState.start;
_displayLoopState.currentRound = 0;
_displayLoopState.active = true;
}
// return a bool, false for task ended
bool displayLoopTaskUpdate() {
if (!_displayLoopState.active) {
return false;
}
if (millis() - _displayLoopState.start >= _displayLoopState.totalMillis) {
_displayLoopState.active = false;
return false;
}
for (int digit = 0; digit < 4; digit++) {
int charPos = _displayLoopState.currentRound - 3 + digit;
char displayChar = ' ';
bool displayDP = false;
if (0 <= charPos && charPos < _displayLoopState.bufLen) {
displayChar = _displayLoopState.strBuf[charPos];
displayDP = _displayLoopState.dpBuf[charPos];
}
byte pattern = getPattern(displayChar, displayDP);
showSingle(pattern, digit);
}
unsigned long currentTime = millis();
while (currentTime - _displayLoopState.startBatch >= (_displayLoopState.currentRound + 1) * _displayLoopState.batchMillis) {
_displayLoopState.currentRound++;
if (_displayLoopState.currentRound >= _displayLoopState.totalRounds) {
_displayLoopState.currentRound = 0;
_displayLoopState.startBatch = currentTime;
}
}
return true;
}
/**
* 在四位数码管上滚动显示字符串
* @param str 要显示的字符串
* @param DP 小数点控制数组,与 str 等长
* @param totalMillis 总显示时间(毫秒)
* @param batchMillis 每四个字符的显示时间(毫秒)
*/
void displayLoop(const char *str, const bool *DP = NULL, unsigned long totalMillis = 1000, unsigned long batchMillis = BATCHMILLIS) {
displayLoopTaskInit(str, DP, totalMillis, batchMillis);
while (!displayLoopTaskUpdate())
continue;
}
void display(int value, unsigned int DP = B0000) {
int digits[4];
for (int i = 3; i >= 0; i--) {
digits[i] = value % 10;
value /= 10;
}
// Multiplex display
for (int d = 0; d < 4; d++) {
byte pattern = getPattern('0' + digits[d], DP & B1 << d ? true : false);
showSingle(pattern, d);
}
}
void display(const char* str, unsigned DP = B0000) {
for (int d = 0; d < 4; d++) {
byte pattern = getPattern(str[d], DP & B1 << d ? true : false);
showSingle(pattern, d);
}
}
#define __define_displayForMillis(TYPE) \
void displayForMillis(TYPE value, unsigned int DP = B0000, unsigned long millisCount = 1000) { \
unsigned long start = millis(); \
while (millis() - start < millisCount) { \
display(value, DP); \
} \
}
__define_displayForMillis(int)
__define_displayForMillis(const char*)
#undef __define_displayForMillis
#define __define_displayShock(TYPE) \
void displayShock(TYPE value, unsigned int DP = B0000, unsigned long millisCount = 1000) { \
unsigned long start = millis(); \
while (millis() - start < millisCount) { \
displayForMillis(value, DP, min(millisCount - (millis() - start), shockShowMillis)); \
delay(shockHideMillis); \
} \
}
__define_displayShock(int)
__define_displayShock(const char*)
#undef __define_displayShock
void segmentInit() {
for (int i = 0; i < 8; i++)
pinMode(segPins[i], OUTPUT);
for (int i = 0; i < 4; i++) {
pinMode(digitPins[i], OUTPUT);
digitalWrite(digitPins[i], HIGH); // all off initially
}
}
#endif
于是可以方便地写出如下程序:
aplusb.ino
#include "include/segment.cpp"
const int inputScale = 5;
const int inputPin = A0;
const int buttonPin = A1;
int readInt() {
while (true) {
int raw = analogRead(inputPin);
int value = raw / inputScale;
display(value);
if (digitalRead(buttonPin) == HIGH) {
displayForMillis(value, 0, 20);
while (digitalRead(buttonPin) == HIGH) {
display(value);
}
displayShock(value);
return value;
}
}
}
void setup() {
segmentInit();
pinMode(inputPin, INPUT);
pinMode(buttonPin, INPUT);
Serial.begin(115200);
}
void SerialPrintf(const char *fmt, ...) {
char buf[128];
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
Serial.print(buf);
}
void loop() {
int a = readInt();
SerialPrintf("Read a = %d\n", a);
int b = readInt();
SerialPrintf("Read b = %d\n", b);
int sum = a + b;
SerialPrintf("%d + %d = %d\n", a, b, sum);
displayForMillis(sum, B0111, 5000);
}

alphabet
我们已经封装好了,直接用就行了。
alphabet.ino
#include "include/segment.cpp"
void setup() {
segmentInit();
displayLoop(".0123456789.A...BCDEFGHIJKLMNOPQRSTUVWXYZ", NULL, 5000);
displayLoop("520", NULL, 5000);
displayLoop("520 1314", NULL, 8000);
displayLoop("i love you", NULL, 8000);
displayForMillis(" ADD", 0, 1000);
displayShock("F K", 0, 3000);
displayLoopTaskInit("F K YOU", NULL, 5000);
}
void loop() {
if (digitalRead(A1) == HIGH) {
while (digitalRead(A1) == HIGH)
continue;
displayShock("F K", 0, 3000);
}
if (!displayLoopTaskUpdate()) {
displayLoopTaskInit("F K ME. PLEASE", NULL, 5000);
}
}
接线同 aplusb。
本文作者:XuYueming,转载请注明原文链接:https://www.cnblogs.com/XuYueming/p/19117544。
若未作特殊说明,本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。

浙公网安备 33010602011771号