51单片机基础-动态数码管显示

第六章 动态数码管显示

1. 导入

在第五章中,我们学习了静态数码管显示,即每个数码管的段选线独立控制,优点是显示稳定、程序简单,但缺点是占用I/O资源多(每位需8个引脚)。当需要显示多位数字时,I/O口资源迅速耗尽。

本章将介绍动态数码管显示 技术,通过"扫描方式 "实现多位数码管的显示,显著减少I/O占用。其核心思想是:利用人眼视觉惰性,快速轮流点亮各个数码管,形成"同时显示"的错觉

本章目标:

  • 理解动态扫描原理;
  • 掌握位选与段选控制方法;
  • 实现多位数码管的数字显示;
  • 解决重影、亮度不均等问题;
  • 为后续实现电子钟、计数器等应用打下基础。

2. 硬件设计

2.1 动态数码管结构

多位数码管(如4位)内部由多个7段数码管组成,其特点是:

  • 段选线并联:所有数码管的a、b、c、d、e、f、g、dp分别连在一起;
  • 位选线独立:每个数码管的公共端(COM)单独引出,用于选择哪一位显示。

常见封装为12脚或16脚,如4位数码管通常为12脚:8根段选线 + 4根位选线。

2.2 数码管类型

仍分为:

  • 共阴极:位选线接GND使该位导通,段选线输出高电平点亮段;
  • 共阳极:位选线接VCC使该位导通,段选线输出低电平点亮段。

本章以共阴极4位数码管为例。

2.3 电路连接

功能 连接方式
段选线(a~g, dp) 接P0口(P0.0 ~ P0.7)
位选线(D1~D4) 接P2.0 ~ P2.3
P0口上拉电阻 外接10kΩ排阻(因P0为开漏)

说明:

  • 段选线控制显示内容;
  • 位选线控制哪一位被点亮;
  • 某一位被选中时,其COM端接地(通过三极管或直接I/O控制)。
位选驱动增强(可选)

若I/O驱动能力不足,可在位选线使用NPN三极管(如S8550)进行电流放大:

  • P2.0 → 三极管基极(通过1kΩ电阻)
  • 发射极 → VCC
  • 集电极 → 数码管COM端

此时为高电平有效位选。


3. 软件设计

3.1 段码表定义

复用第五章的共阴极段码表:

c 复制代码
#include <reg52.h>

unsigned char code seg_code[] = {
    0x3F, // 0
    0x06, // 1
    0x5B, // 2
    0x4F, // 3
    0x66, // 4
    0x6D, // 5
    0x7D, // 6
    0x07, // 7
    0x7F, // 8
    0x6F  // 9
};

3.2 位选控制

定义位选控制宏(共阴极,低电平有效):

c 复制代码
#define DIGIT1 P2 = P2 & 0xFE | 0x0E  // P2.0=0, P2.1~3=1 → 选中第1位
#define DIGIT2 P2 = P2 & 0xFD | 0x0D  // P2.1=0
#define DIGIT3 P2 = P2 & 0xFB | 0x0B  // P2.2=0
#define DIGIT4 P2 = P2 & 0xF7 | 0x07  // P2.3=0

更简洁方式:直接赋值

c 复制代码
void select_digit(unsigned char n) {
    switch(n) {
        case 1: P2 = (P2 & 0xF0) | 0x0E; break;
        case 2: P2 = (P2 & 0xF0) | 0x0D; break;
        case 3: P2 = (P2 & 0xF0) | 0x0B; break;
        case 4: P2 = (P2 & 0xF0) | 0x07; break;
        default: break;
    }
}

实际常用:P2.03 控制位选,P2.47 保留,故先清低4位再设置。


3.3 基本显示流程

动态扫描步骤:

  1. 关闭所有位选(可选);
  2. 输出当前位的段码;
  3. 选中该位;
  4. 延时1~5ms;
  5. 关闭该位;
  6. 切换到下一位,循环。
c 复制代码
void display(unsigned char *num, unsigned char len) {
    unsigned char i;
    for (i = 0; i < len; i++) {
        P0 = 0x00;                    // 消隐,防止重影
        P2 = (P2 & 0xF0) | 0x0F;      // 关闭所有位选(P2.0~3=1)

        P0 = seg_code[num[i]];        // 输出第i位的段码
        P2 = (P2 & 0xF0) | (0x0F & ~(1 << i)); // 选中第i位(低电平)

        delay_ms(1);                  // 显示1ms
    }
}

说明:~(1 << i) 生成第i位为0,其余为1。


3.4 显示多位数字(示例:显示1234)

c 复制代码
unsigned char show[] = {1, 2, 3, 4}; // 显示内容

void main() {
    while(1) {
        display(show, 4);
    }
}

注意:display函数需在主循环中持续调用,扫描频率建议 ≥ 50Hz,避免闪烁。


3.5 消除重影(Ghosting)

重影原因:前一位未完全关闭时,后一位已开启,导致两位列同时亮。

解决方法:

  1. 消隐法:在切换位前,先将段选线清零;
  2. 快速扫描:提高扫描频率;
  3. 关闭位选:切换时短暂关闭所有位选。

改进版扫描函数:

c 复制代码
void display(unsigned char *num, unsigned char len) {
    unsigned char i;
    for (i = 0; i < len; i++) {
        P0 = 0x00;                    // 消隐
        P2 = (P2 & 0xF0) | 0x0F;      // 关闭所有位选

        P0 = seg_code[num[i]];        // 设置段码
        P2 = (P2 & 0xF0) | (0x0F & ~(1 << i)); // 选中第i位

        delay_ms(1);
    }
}

3.6 显示小数点

若需在第2位显示小数点(如12.34),则:

c 复制代码
P0 = seg_code[num[i]] | 0x80;  // 仅在第2位加小数点

可在display函数中判断位数:

c 复制代码
if (i == 1) {  // 第2位(索引1)
    P0 = seg_code[num[i]] | 0x80;
} else {
    P0 = seg_code[num[i]];
}

3.7 使用定时器中断扫描(预告)

当前方法在主循环中扫描,若主程序有复杂逻辑,可能导致显示不稳定。后续可使用定时器中断

  • 定时器每1ms中断一次;
  • 在中断中切换数码管位;
  • 实现非阻塞、高稳定性显示。

留待"定时器"章节深入。


3.8 编译与下载

  • Keil中创建工程,写入代码;
  • 确保段选与位选连接正确;
  • 编译生成HEX;
  • 下载至单片机;
  • 观察是否显示1234,无闪烁、无重影。

若显示错乱:

  • 检查位选逻辑是否正确;
  • 确认段码表适用于共阴极;
  • 增加消隐步骤。

4. 小结

本章通过实现动态数码管显示,掌握了多位数字显示的核心技术,主要内容包括:

  • 硬件连接:理解段选与位选结构,正确连接共阴极数码管;
  • 扫描原理:利用视觉惰性实现"多路复用";
  • 软件实现:编写扫描函数,支持多位显示、小数点控制;
  • 问题解决:掌握消隐、防重影、亮度均衡等技巧;
  • 扩展能力:为实现计时器、频率计等应用奠定基础。

4.1 常见问题与解决

问题 原因 解决方法
显示闪烁 扫描频率太低 增加扫描次数或减少延时
重影 未消隐或切换太快 加入消隐步骤,短暂关闭所有位
某位不亮 位选线未导通 检查P2口输出与三极管驱动
亮度不均 各位显示时间不同 保证每位延时一致
显示乱码 段码表错误 确认数码管类型并重新编码

4.2 下一步学习建议

  • 使用定时器中断实现动态扫描,解放主程序;
  • 实现电子钟功能,显示时分秒;
  • 引入按键调节时间;
  • 学习矩阵键盘,扩展输入方式。

本章标志着你已掌握高效的多位显示技术,下一章将进入定时器/计数器模块的学习,实现精准时间控制与非阻塞操作。


相关推荐
小莞尔1 天前
【51单片机】【protues仿真】基于51单片机简易电子琴系统(8键)
c语言·单片机·嵌入式硬件·物联网·51单片机
盈创力和20071 天前
技术解析:CO与NO₂双气体监测如何构筑协同化安全防线
嵌入式硬件·安全·以太网温湿度传感器·多参量传感器·温湿度+气体智能传感器
平凡灵感码头1 天前
STM32 串口中断接收原理与实战详解:从配置到中断服务函数全流程解析
单片机·嵌入式硬件
切糕师学AI1 天前
MCU中的RC电路(Resistor-Capacitor Circuit)
单片机·嵌入式硬件
朱嘉鼎1 天前
KeilIDE背后的命令
c语言·嵌入式硬件·keilmdk
Jie_jiejiayou1 天前
STM32F10xxx启动模式配置与ISP一键下载
stm32·isp·烧录模式
GilgameshJSS1 天前
STM32H743-ARM例程33-TOUCH
c语言·arm开发·stm32·单片机·嵌入式硬件
我先去打把游戏先2 天前
ESP32开发指南(基于IDF):连接AWS,乐鑫官方esp-aws-iot-master例程实验、跑通
开发语言·笔记·单片机·物联网·学习·云计算·aws
hazy1k2 天前
51单片机基础-继电器实验
stm32·单片机·嵌入式硬件·51单片机·1024程序员节
美好的事情总会发生2 天前
FPGA的LVDS接口电压
嵌入式硬件·fpga开发·硬件工程·智能硬件