蓝桥杯单片机组备赛指南·第三讲 -数码管

数码管显示技术全攻略:共阴段码表 + 锁存器驱动 + 静态显示 + 定时器动态扫描(省赛、国赛常考模块)

本讲系统讲解蓝桥杯指定开发板(CT107D)数码管完整驱动方式,涵盖静态显示与中断动态扫描两大核心技术。近五年国赛、省赛中,数码管模块几乎每场必出,且常与按键、定时器、矩阵键盘联合考察,是中后期综合系统的核心显示单元。学完本讲,你将能够独立完成6位数字显示、倒计时、电子钟等经典题目。

一、数码管硬件原理

开发板采用6位共阴数码管 + 74HC573锁存器方案:

项目连接方式说明
段码输出P0口 → 74HC573 → a~g、dpP2_6 为段锁存使能(上升沿锁存)
位选输出P0口 → 74HC573 → 6位共阴P2_7 为位锁存使能(上升沿锁存)

共阴数码管段码表(0~9 + 熄灭,直接背):

数字段码(十六进制)二进制
00x3F0011 1111
10x060000 0110
20x5B0101 1011
30x4F0100 1111
40x660110 0110
50x6D0110 1101
60x7D0111 1101
70x070000 0111
80x7F0111 1111
90x6F0110 1111
熄灭0x000000 0000

6位位选码(从左到右):

位置位码(十六进制)
第1位0xFE
第2位0xFD
第3位0xFB
第4位0xF7
第5位0xEF
第6位0xDF

二、静态数码管显示

// 头文件
#include <REGX52.H>

// 类型定义(提高代码可读性)
typedef unsigned char u8;
typedef unsigned int  u16;

// 数码管编码表(共阴)
u8 Seg_Dula[11] = {0x3F,0x06,0x5B,0x4F,0x66,
                   0x6D,0x7D,0x07,0x7F,0x6F,0x00};
// 位选编码表:对应6个数码管
u8 Seg_Wela[6] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF};

/**
 * 数码管显示函数
 * @param Wela 位选参数(0-5,选择第几个数码管)
 * @param Dula 段选参数(0-9,显示的数字)
 */
void Seg_Dis(u8 Wela, u8 Dula)
{
    // 第一步:消影处理(防止显示重影)
    P0 = 0x00;      // 将P0口清零
    P2_6 = 1;       // 产生上升沿,将0x00锁存到段码锁存器
    P2_6 = 0;
   
    // 第二步:位选(选择要显示的数码管)
    P0 = Seg_Wela[Wela]; // 输出位选信号
    P2_7 = 1;            // 产生上升沿,将位选信号锁存
    P2_7 = 0;
   
    // 第三步:段选(输出要显示的内容)
    P0 = Seg_Dula[Dula]; // 输出段选信号
    P2_6 = 1;            // 产生上升沿,将段选信号锁存
    P2_6 = 0;
}

// 主函数
void main()
{
    while(1)
    {
        Seg_Dis(1,1);   // 在第二个数码管上稳定显示数字1
    }
}

三、动态数码管显示

// 头文件
#include <REGX52.H>

typedef unsigned char   u8;
typedef unsigned int u16;

// 数码管编码表(与静态完全一致)
u8 Seg_Dula[11] = {0x3F,0x06,0x5B,0x4F,0x66,
                   0x6D,0x7D,0x07,0x7F,0x6F,0x00};
u8 Seg_Wela[6] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF};

// 显示缓冲区:存放6个数码管要显示的内容
u8 Seg_Buf[6] = {1,2,3,4,5,6};
// 数码管索引:当前要显示的数码管编号(0-5)
u8 Seg_Index = 0;

/* 定时器0初始化:1ms中断一次(12MHz晶振) */
void Timer0_Init(void)
{
    TMOD &= 0xF0;   // 清除定时器0模式位
    TMOD |= 0x01;   // 设为16位定时器模式1
    
    TL0 = 0x20;     // 初值低8位
    TH0 = 0xD1;     // 初值高8位  (65536-1000 ≈ 1ms)
    
    TF0 = 0;
    TR0 = 1;
    
    ET0 = 1;        // 允许定时器0中断
    EA  = 1;        // 开总中断
}

/* 与静态完全相同的显示函数 */
void Seg_Dis(u8 Wela, u8 Dula)
{
    P0 = 0x00; P2_6 = 1; P2_6 = 0;          // 消影
    
    P0 = Seg_Wela[Wela]; P2_7 = 1; P2_7 = 0; // 位选
    
    P0 = Seg_Dula[Dula]; P2_6 = 1; P2_6 = 0; // 段选
}

void main()
{
    Timer0_Init();      // 启动定时器
    while(1)
    {
        // 主循环空闲,可放其他任务(如按键扫描)
    }
}

/* 定时器0中断服务函数:每1ms执行一次 */
void Timer0_Routine() interrupt 1
{
    TL0 = 0x20;         // 重装初值
    TH0 = 0xD1;
    
    if(++Seg_Index == 6)    // 6位轮流显示
        Seg_Index = 0;
        
    Seg_Dis(Seg_Index, Seg_Buf[Seg_Index]); // 显示当前位
}

实板效果:6个数码管同时稳定显示 123456,无闪烁。

四、本讲总结

模块关键技巧
共阴段码表0x3F~0x6F 十个数直接背
锁存器驱动P0送数据 → P2_6/P2_7上升沿锁存
消影处理每次显示前先P0=0x00清段
静态显示直接调用Seg_Dis一次即可
动态扫描1ms定时中断 + 轮流刷新6位
显示缓冲区Seg_Buf[6]改数组内容即可实时更新

继续加油,我们一步步向国奖迈进!

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐