蓝桥杯单片机组备赛指南·第三讲 -数码管
·
蓝桥杯单片机组备赛指南·第三讲 -数码管
数码管显示技术全攻略:共阴段码表 + 锁存器驱动 + 静态显示 + 定时器动态扫描(省赛、国赛常考模块)
本讲系统讲解蓝桥杯指定开发板(CT107D)数码管完整驱动方式,涵盖静态显示与中断动态扫描两大核心技术。近五年国赛、省赛中,数码管模块几乎每场必出,且常与按键、定时器、矩阵键盘联合考察,是中后期综合系统的核心显示单元。学完本讲,你将能够独立完成6位数字显示、倒计时、电子钟等经典题目。
一、数码管硬件原理
开发板采用6位共阴数码管 + 74HC573锁存器方案:
| 项目 | 连接方式 | 说明 |
|---|---|---|
| 段码输出 | P0口 → 74HC573 → a~g、dp | P2_6 为段锁存使能(上升沿锁存) |
| 位选输出 | P0口 → 74HC573 → 6位共阴 | P2_7 为位锁存使能(上升沿锁存) |
共阴数码管段码表(0~9 + 熄灭,直接背):
| 数字 | 段码(十六进制) | 二进制 |
|---|---|---|
| 0 | 0x3F | 0011 1111 |
| 1 | 0x06 | 0000 0110 |
| 2 | 0x5B | 0101 1011 |
| 3 | 0x4F | 0100 1111 |
| 4 | 0x66 | 0110 0110 |
| 5 | 0x6D | 0110 1101 |
| 6 | 0x7D | 0111 1101 |
| 7 | 0x07 | 0000 0111 |
| 8 | 0x7F | 0111 1111 |
| 9 | 0x6F | 0110 1111 |
| 熄灭 | 0x00 | 0000 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]改数组内容即可实时更新 |
继续加油,我们一步步向国奖迈进!
更多推荐
所有评论(0)