数码管动态显示 · 10 大经典实训
本项目围绕七段数码管显示展开,从单个共阳数码管静态显示、段码查表,到多位动态扫描、按键交互、八位共阴数码管流水与时分秒计时器,系统训练单片机显示接口设计与编程能力。
10 大经典玩法一览
由简到难,循序渐进掌握数码管显示 · 点击任意卡片开始学习
单个共阳数码管静态显示固定数字
段码输出 · 静态锁存
单个共阳数码管静态循环显示 0~9
段码表 · 循环延时
两位共阳数码管静态同时显示数字59
双位静态驱动 · 独立段口
两位共阳数码管动态扫描显示59
视觉暂留 · 动态扫描
2个按键加减1两位数码管同步显示
按键消抖 · 计数显示
八位共阴数码管全动态扫描基础实训
共阴段码 · 多路扫描
8位共阴数码管动态显示数字1-8
位选映射 · 静态数据
8位共阴数码管广告流水灯效果
边框跑灯 · 循环转动
8位共阴数码管时分秒简易计时器
定时器中断 · 时分秒显示
8位共阴数码管时分秒可调计时器
按键设置 · 闪烁校时
单个共阳数码管静态显示固定数字
基础实训1 项目简介
本项目是数码管显示入门的第一个实验,通过向共阳数码管的段码线输出固定段码,使数码管稳定显示一个数字(例如 6)。学生将理解共阳数码管“低电平点亮段”的工作原理,并掌握 8051 单片机端口输出的基本方法。
掌握本项目后,学生将能够根据显示数字计算或查表得到对应的共阳段码,并正确连接段码线与位选线,为后续多位动态扫描显示打下坚实基础。
2 电路图
电路说明
- • P0 口连接共阳数码管段码线 a~g、dp,低电平点亮对应段
- • P2.0 连接数码管公共端,高电平选通,公共端接 VCC
- • 采用共阳接法,段码线为 0 时对应段点亮
- • 每段串联限流电阻(220Ω~1kΩ),防止数码管过流损坏
3 仿真演示
仿真说明
- • 上电后程序向P0口输出固定段码并选通数码管
- • 数码管持续稳定显示数字6,字形不闪烁不变化
4 程序内容(汇编语言)
;==================================================
; 项目名称:单个共阳数码管静态显示固定数字
; 芯片型号:STC89C52RC
; 时钟频率:12MHz
; 段码线:P0 口连接 a~g、dp(低电平点亮段)
; 位选线:P2.0 连接数码管公共端(高电平选通)
; 显示内容:固定数字 6
;==================================================
ORG 0000H ; 程序从复位向量 0000H 开始
LJMP MAIN ; 跳转到主程序入口
; 主程序入口
; 功能:输出数字 6 的共阳段码,并选通数码管
MAIN: MOV P0, #82H ; 共阳段码 82H = 数字 6(a,f,e,d,c,g 亮,b,dp 灭)
SETB P2.0 ; P2.0=1,选通共阳数码管公共端
; 静态显示,进入无限循环保持输出
LOOP: SJMP LOOP ; 持续保持段码与位选,稳定显示
END ; 程序结束
5 评分标准
| 评分项 | 分值 | 评分标准 |
|---|---|---|
| 电路连接 | 30分 | 段码线、位选线连接正确,共阳公共端接 VCC |
| 程序编写 | 40分 | 代码正确、规范,段码计算正确,注释清晰 |
| 功能实现 | 20分 | 数码管稳定显示指定数字 |
| 实训报告 | 10分 | 报告内容完整、整洁 |
6 注意事项与安全规范
共阳段码
共阳数码管段码为低电平点亮,与共阴段码互为反码
限流电阻
每段需串联 220Ω~1kΩ 限流电阻,防止数码管过流损坏
位选电平
共阳数码管公共端接 VCC,位选晶体管低电平导通
单个共阳数码管静态循环显示 0~9 数字
基础实训1 项目简介
本项目学习使用查表法让单个共阳数码管循环显示 0~9 十个数字。通过建立共阳段码表,程序按顺序读取段码并输出,配合延时子程序实现数字切换效果。
掌握段码表的建立与 MOVC 查表指令的使用方法,理解查表法在数码管显示中的重要作用,为后续多位显示和动态扫描提供基础。
2 电路图
电路说明
- • P0 口连接共阳数码管段码线 a~g、dp,低电平点亮对应段
- • P2.0 连接数码管公共端,高电平选通,公共端接 VCC
- • 程序通过查表法依次输出 0~9 共阳段码
- • 每段串联限流电阻,延时子程序控制切换速度
3 仿真演示
仿真说明
- • 程序按顺序查表输出段码,每隔约500ms切换数字
- • 数码管依次显示0至9,到9后返回0循环往复
4 程序内容(汇编语言)
;==================================================
; 项目名称:单个共阳数码管静态循环显示 0~9 数字
; 芯片型号:STC89C52RC
; 时钟频率:12MHz
; 段码线:P0 口连接 a~g、dp(低电平点亮段)
; 位选线:P2.0 连接数码管公共端(高电平选通)
; 功能说明:每隔约 500ms 循环显示 0~9
;==================================================
ORG 0000H ; 程序从复位向量 0000H 开始
LJMP MAIN ; 跳转到主程序入口
; 共阳数码管段码表 0~9
; 说明:共阳数码管公共端接高电平,段码中为 0 的位点亮对应段
ORG 0100H
SEGTAB: DB 0C0H,0F9H,0A4H,0B0H,099H
DB 092H,082H,0F8H,080H,090H
; 主程序入口
; 主循环功能:依次查表并输出 0~9 段码,每个数字保持约 500ms
MAIN: SETB P2.0 ; 选通共阳数码管
MOV R0, #0 ; R0 作为段码表索引,初始显示 0
; 循环显示 0~9
DISP_LP:
MOV A, R0 ; A = 当前数字索引
MOV DPTR, #SEGTAB ; DPTR 指向共阳段码表
MOVC A, @A+DPTR ; 查表得到对应数字的段码
MOV P0, A ; 输出段码到 P0 口
LCALL DELAY500 ; 延时约 500ms,保持当前显示
INC R0 ; 索引加 1,准备显示下一个数字
MOV A, R0
CJNE A, #10, DISP_LP ; 未到 10 则继续循环显示
MOV R0, #0 ; 索引清零,重新从 0 开始
SJMP DISP_LP ; 继续循环
; 约 500ms 延时子程序:控制数字切换速度
; 参数:无;返回:无
DELAY500: MOV R7, #250
D500_1: MOV R6, #250
D500_2: NOP
DJNZ R6, D500_2
DJNZ R7, D500_1
RET ; 子程序返回
END ; 程序结束
5 评分标准
| 评分项 | 分值 | 评分标准 |
|---|---|---|
| 段码表 | 30分 | 0~9 共阳段码表正确无误 |
| 程序编写 | 40分 | 代码正确、规范,查表逻辑清晰 |
| 功能实现 | 20分 | 数码管按 0~9 顺序循环显示 |
| 实训报告 | 10分 | 报告内容完整、整洁 |
6 注意事项与安全规范
段码索引
索引范围必须为 0~9,超出范围会导致查表错误
切换速度
延时时间不宜过短,否则数字切换太快无法看清
两位共阳数码管静态同时显示数字59
进阶实训1 项目简介
本项目通过为两位共阳数码管分别提供独立的段码端口,实现十位与个位同时显示不同数字(59)。十位数码管由 P0 口驱动显示 5,个位数码管由 P1 口驱动显示 9,两个位选端同时选通。
掌握多位数码管静态显示方式,理解独立段码端口与共享段码端口的区别,为学习动态扫描显示做铺垫。
2 电路图
电路说明
- • 十位数码管段码线由 P0 口驱动,显示数字 5
- • 个位数码管段码线由 P1 口驱动,显示数字 9
- • 十位位选接 P2.0,个位位选接 P2.1,高电平选通
- • 两位数码管公共端均接 VCC,同时选通实现静态显示
3 仿真演示
仿真说明
- • P0、P1口分别输出十位与个位段码,两位同时选通
- • 两位数码管持续常亮,稳定显示数字59
4 程序内容(汇编语言)
;==================================================
; 项目名称:两位共阳数码管静态同时显示数字59
; 芯片型号:STC89C52RC
; 时钟频率:12MHz
; 十位段码:P0 口(连接十位数码管 a~g、dp)
; 个位段码:P1 口(连接个位数码管 a~g、dp)
; 十位位选:P2.0(高电平选通十位)
; 个位位选:P2.1(高电平选通个位)
; 显示内容:十位 5,个位 9
;==================================================
ORG 0000H ; 程序从复位向量 0000H 开始
LJMP MAIN ; 跳转到主程序入口
; 共阳数码管段码表 0~9
ORG 0100H
SEGTAB: DB 0C0H,0F9H,0A4H,0B0H,099H
DB 092H,082H,0F8H,080H,090H
; 主程序入口
; 功能:P0 输出数字 5 段码,P1 输出数字 9 段码,同时选通两位
MAIN: MOV DPTR, #SEGTAB ; DPTR 指向段码表
MOV A, #5 ; 十位显示 5
MOVC A, @A+DPTR ; 查表得 5 的共阳段码
MOV P0, A ; 输出到十位段码口 P0
MOV A, #9 ; 个位显示 9
MOVC A, @A+DPTR ; 查表得 9 的共阳段码
MOV P1, A ; 输出到个位段码口 P1
SETB P2.0 ; 选通十位数码管
SETB P2.1 ; 选通个位数码管
; 静态保持显示
LOOP: SJMP LOOP ; 无限循环保持输出
END ; 程序结束
5 评分标准
| 评分项 | 分值 | 评分标准 |
|---|---|---|
| 双段口输出 | 30分 | P0、P1 分别输出十位与个位段码,连线正确 |
| 程序编写 | 40分 | 代码正确、规范,注释清晰 |
| 功能实现 | 20分 | 两位数码管同时稳定显示 59 |
| 实训报告 | 10分 | 报告内容完整、整洁 |
6 注意事项与安全规范
端口占用
静态多位显示需要多个段码端口,会占用较多 IO 资源
静态 vs 动态
理解静态显示亮度高但 IO 占用多,动态显示可节省 IO
两位共阳数码管动态扫描显示59
进阶实训1 项目简介
本项目学习两位共阳数码管的动态扫描显示技术。两位数码管共享 P0 段码线,通过快速交替选通十位和个位,并输出对应段码,利用人眼视觉暂留效应实现“同时”显示 59 的效果。
掌握动态扫描的基本原理,理解扫描频率、占空比与显示亮度的关系,学会使用延时控制每位数码管的点亮时间。
2 电路图
电路说明
- • 两位数码管共享 P0 口段码线 a~g、dp
- • 十位位选接 P2.0,个位位选接 P2.1,高电平选通
- • 快速轮流选通十位和个位,利用视觉暂留显示 59
- • 公共端由 P2.0/P2.1 控制电平,高电平选中该位(共阳方式)
3 仿真演示
仿真说明
- • 程序轮流选通十位和个位,每位点亮约2ms
- • 两位数码管看似同时显示59,无明显闪烁
4 程序内容(汇编语言)
;==================================================
; 项目名称:两位共阳数码管动态扫描显示59
; 芯片型号:STC89C52RC
; 时钟频率:12MHz(机器周期=1μs)
; 段码线:P0 口(a~g、dp,低电平点亮段)
; 位选线:P2.0=十位公共端,P2.1=个位公共端(高电平选中)
; 显示内容:十位 5,个位 9
; 消隐:每位切换前先 P2=00H 关闭两位,段码稳定后再选通
; 杜绝拖影/鬼影;延时只用 R1、R2
;==================================================
ORG 0000H ; 程序从复位向量 0000H 开始
LJMP MAIN ; 跳转到主程序入口
; 共阳数码管段码表 0~9(段码中为 0 的位点亮对应段)
ORG 0100H
SEGTAB: DB 0C0H,0F9H,0A4H,0B0H,099H
DB 092H,082H,0F8H,080H,090H
; 主程序:端口初始化
MAIN: MOV P0, #0FFH ; 段码全高,数码管初始全灭
MOV P2, #00H ; 两个公共端低电平,两位均关闭
MOV DPTR, #SEGTAB ; DPTR 指向共阳段码表
; 动态扫描循环
SCAN: ; 显示十位 5:消隐→输出段码→选通十位→保持→消隐
MOV P2, #00H ; 关闭两位,切换前先消隐
MOV A, #5 ; 十位数字 5
MOVC A, @A+DPTR ; 查表得十位段码 92H
MOV P0, A ; 输出段码到 P0
MOV P2, #01H ; 00000001,仅 P2.0 高,选通十位
LCALL DELAY2 ; 保持约 2ms
MOV P2, #00H ; 关闭十位,下一段前消隐
; 显示个位 9:输出段码→选通个位→保持→消隐
MOV A, #9 ; 个位数字 9
MOVC A, @A+DPTR ; 查表得个位段码 90H
MOV P0, A ; 输出段码到 P0
MOV P2, #02H ; 00000010,仅 P2.1 高,选通个位
LCALL DELAY2 ; 保持约 2ms
MOV P2, #00H ; 关闭个位
SJMP SCAN ; 返回继续扫描
; 约 2ms 动态扫描延时子程序:控制每位点亮时间
DELAY2: MOV R2, #23
D2_1: MOV R1, #28
D2_2: NOP
DJNZ R1, D2_2 ; 内层 28×(1+2)=84 周期
DJNZ R2, D2_1 ; 23×(1+84+2)=2001 周期
RET ; 合计约 2002μs ≈ 2ms
END ; 程序结束
5 评分标准
| 评分项 | 分值 | 评分标准 |
|---|---|---|
| 动态扫描 | 30分 | 位选切换正确,无重影、无闪烁 |
| 程序编写 | 40分 | 代码正确、规范,注释清晰 |
| 功能实现 | 20分 | 两位数码管稳定显示 59 |
| 实训报告 | 10分 | 报告内容完整、整洁 |
6 注意事项与安全规范
消隐处理
切换位选前建议先关闭当前位,避免切换瞬间出现残影
刷新频率
整体刷新频率应高于 50Hz,否则肉眼会观察到闪烁
2个按键加减1两位数码管同步显示
进阶实训1 项目简介
本项目通过两个独立按键分别对 0~99 计数器进行加 1 和减 1 操作,并将当前数值实时显示在两位共阳数码管上。当数值超过 99 时回到 0,当数值为 0 时减 1 保持为 0。
掌握按键消抖、计数器边界处理、BCD 拆分与动态扫描显示的综合应用,理解按键事件与显示刷新如何协同工作。
2 电路图
电路说明
- • P0 口连接两位共阳数码管共享段码线 a~g、dp
- • P2.0 选通十位,P2.1 选通个位,高电平有效
- • 加键 S1 接 P3.0,减键 S2 接 P3.1,低电平有效
- • 利用 P3 口内部上拉,按下时端口被拉低
3 仿真演示
仿真说明
- • 按下加键或减键时,计数值相应加1或减1
- • 两位数码管实时显示当前数值,范围为0至99
4 程序内容(汇编语言)
;==================================================
; 项目名称:2个按键加减1两位数码管同步显示
; 芯片型号:STC89C52RC
; 时钟频率:12MHz(机器周期=1μs)
; 段码线:P0 口(a~g、dp,低电平点亮段)
; 位选线:P2.0=十位公共端,P2.1=个位公共端(高电平选中)
; 加键 S1:P3.0,减键 S2:P3.1(按下为低电平)
; 计数:30H 单元保存数值 0~99(不占用工作寄存器)
; R5=十位数字,R6=个位数字,延时只用 R1~R4
; 消隐:每位切换前先 P2=00H 关闭两位,杜绝拖影
;==================================================
ORG 0000H ; 程序从复位向量 0000H 开始
LJMP MAIN ; 跳转到主程序入口
; 共阳数码管段码表 0~9
ORG 0100H
SEGTAB: DB 0C0H,0F9H,0A4H,0B0H,099H
DB 092H,082H,0F8H,080H,090H
; 主程序入口
; 主循环功能:刷新显示,同时扫描加减键
MAIN: MOV 30H, #0 ; 计数单元初始为 0
MOV P0, #0FFH ; 段码全高,数码管初始全灭
MOV P2, #00H ; 两个公共端低电平,两位均关闭
MOV P3, #0FFH ; P3 写 1,P3.0/P3.1 配置为输入
; 主循环:执行一次按键扫描和一次动态显示刷新
LOOP: LCALL KEY_SCAN ; 扫描加、减按键
LCALL DISP ; 动态显示当前计数
SJMP LOOP ; 继续循环
; 按键扫描子程序(只修改 30H 计数单元)
KEY_SCAN:
JB P3.0, CHECK_DEC ; P3.0=1 无加键,转检测减键
LCALL DELAY10 ; 约 10ms 按下消抖
JB P3.0, CHECK_DEC ; 再次确认
MOV A, 30H
CJNE A, #99, INC_NUM ; 未到 99 则加 1
MOV 30H, #0 ; 99 再加归零
SJMP WAIT_ADD
INC_NUM:
INC 30H ; 计数加 1
WAIT_ADD:
JNB P3.0, WAIT_ADD ; 等待加键释放,一次按放只加一次
CHECK_DEC:
JB P3.1, KEY_EXIT ; P3.1=1 无减键,退出
LCALL DELAY10 ; 约 10ms 按下消抖
JB P3.1, KEY_EXIT ; 再次确认
MOV A, 30H
JZ WAIT_DEC ; 当前为 0 则保持 0 不减
DEC 30H ; 计数减 1
WAIT_DEC:
JNB P3.1, WAIT_DEC ; 等待减键释放
KEY_EXIT:
RET
; 动态显示子程序:将 30H 拆分为十位和个位扫描显示
DISP: MOV A, 30H
MOV B, #10
DIV AB ; A=十位商,B=个位余数
MOV R5, A ; R5 暂存十位
MOV R6, B ; R6 暂存个位
MOV DPTR, #SEGTAB ; DPTR 指向段码表
; 十位:消隐→段码→选通→保持→消隐
MOV P2, #00H ; 关闭两位,切换前消隐
MOV A, R5
MOVC A, @A+DPTR ; 查十位段码
MOV P0, A ; 输出十位段码
MOV P2, #01H ; 仅 P2.0 高,选通十位
LCALL DELAY2 ; 保持约 2ms
MOV P2, #00H ; 关闭十位
; 个位:段码→选通→保持→消隐
MOV A, R6
MOVC A, @A+DPTR ; 查个位段码
MOV P0, A ; 输出个位段码
MOV P2, #02H ; 仅 P2.1 高,选通个位
LCALL DELAY2 ; 保持约 2ms
MOV P2, #00H ; 关闭个位
RET
; 约 10ms 消抖延时(使用 R4、R3,不碰计数与 R5/R6)
DELAY10: MOV R4, #33
D10_1: MOV R3, #100
D10_2: NOP
DJNZ R3, D10_2 ; 内层 100×(1+2)=300 周期
DJNZ R4, D10_1 ; 33×(1+300+2)=9999 周期
RET ; 合计约 10000μs = 10ms
; 约 2ms 动态扫描延时(使用 R2、R1,不碰计数与 R5/R6)
DELAY2: MOV R2, #23
D2_1: MOV R1, #28
D2_2: NOP
DJNZ R1, D2_2 ; 内层 28×(1+2)=84 周期
DJNZ R2, D2_1 ; 23×(1+84+2)=2001 周期
RET ; 合计约 2002μs ≈ 2ms
END
5 评分标准
| 评分项 | 分值 | 评分标准 |
|---|---|---|
| 按键消抖 | 30分 | 加减键响应稳定,无连跳、无误触发 |
| 程序编写 | 40分 | 代码正确、规范,注释清晰 |
| 功能实现 | 20分 | 加减 1 与两位数码管显示同步,边界处理正确 |
| 实训报告 | 10分 | 报告内容完整、整洁 |
6 注意事项与安全规范
边界处理
加至 99 后归零,减至 0 后保持不变,避免计数溢出
显示与按键平衡
按键扫描与显示刷新需轮流执行,避免长时间阻塞导致显示熄灭
八位共阴数码管全动态扫描基础实训
综合实训1 项目简介
本项目学习八位共阴数码管的全动态扫描基础方法。八位数码管共享 P0 段码线,位选由 74HC138 三八译码器驱动,仅占用 P2.2、P2.3、P2.4 三根线,通过轮流选通每一位并输出段码,让所有数码管同时亮起。
掌握共阴数码管“高电平点亮段、低电平选通位”的特性,理解 74HC138 译码器的工作原理与动态扫描时序,学会用位索引×4 生成译码选择码的编程方法。
2 电路图
电路说明
- • P0 口连接 8 位共阴数码管共享段码线 a~g、dp,高电平点亮段
- • P2.2、P2.3、P2.4 接 74HC138 的 A、B、C 选择端
- • 138 的 E1 接 VCC、E2、E3 接地,Y0~Y7 低电平有效接各位公共端(Y7 为第 1 位最左,Y0 为第 8 位最右)
- • P2.2~P2.4 依次输出 000~111 选通各位,每位约 2ms
3 仿真演示
仿真说明
- • P2.2~P2.4 输出 000~111,经138依次选通Y0~Y7
- • 八位数码管同时稳定显示数字0,亮度均匀
4 程序内容(汇编语言)
;==================================================
; 项目名称:八位共阴数码管全动态扫描基础实训
; 芯片型号:STC89C52RC
; 时钟频率:12MHz(机器周期=1μs)
; 段码线:P0 口(a~g、dp,高电平点亮段)
; 位选:74HC138 译码器,A/B/C 接 P2.2/P2.3/P2.4
; E1 接 VCC,E2、E3 接地,译码器常使能
; Y0~Y7 低电平有效,分别接8位数码管公共端
; 显示内容:所有 8 位数码管显示数字 0
; 扫描方式:P2.2~P2.4 依次输出 000~111,每位约 2ms
;==================================================
ORG 0000H ; 程序从复位向量 0000H 开始
LJMP MAIN ; 跳转到主程序入口
; 共阴数码管段码表 0~9(段码中为 1 的位点亮对应段)
ORG 0100H
SEGTAB: DB 03FH,006H,05BH,04FH,066H
DB 06DH,07DH,007H,07FH,06FH
; 主程序:初始化
MAIN: MOV R0, #0 ; R0 = 位索引 0~7
MOV P0, #00H ; 段码全低,初始所有段熄灭
MOV P2, #00H ; 138 选择码 000,初始选通 Y0(第 1 位)
; 扫描循环:先输出段码,再切换 138 选通对应位
SCAN8: MOV A, #0 ; 显示数字 0
MOV DPTR, #SEGTAB
MOVC A, @A+DPTR ; 查表得共阴段码 3FH
MOV P0, A ; ①先输出段码(段码稳定后再换位)
MOV A, R0
RL A
RL A ; ②位索引×4,形成 P2.2~P2.4 的 138 选择码
MOV P2, A ; ③切换译码器:旧位公共端变高熄灭,
; 新位公共端变低点亮(段码已稳定)
LCALL DELAY2 ; 保持约 2ms
INC R0
CJNE R0, #8, SCAN8 ; 8 位未扫完继续
MOV R0, #0 ; 索引归零,循环往复
SJMP SCAN8
; 约 2ms 延时子程序:控制每位点亮时间(只用 R7、R6,不碰 R0)
DELAY2: MOV R7, #23
D2_1: MOV R6, #28
D2_2: NOP
DJNZ R6, D2_2 ; 内层 28×(1+2)=84 周期
DJNZ R7, D2_1 ; 23×(1+84+2)=2001 周期
RET ; 合计约 2002μs ≈ 2ms
END
5 评分标准
| 评分项 | 分值 | 评分标准 |
|---|---|---|
| 位选扫描 | 30分 | 8 位位选依次选通,扫描无遗漏 |
| 程序编写 | 40分 | 代码正确、规范,共阴段码使用正确 |
| 功能实现 | 20分 | 8 位数码管均稳定显示数字 0 |
| 实训报告 | 10分 | 报告内容完整、整洁 |
6 注意事项与安全规范
共阴段码
共阴数码管段码与共阳段码互为反码,不可混用
扫描频率
8 位总刷新周期控制在 16ms 以内,保证整体刷新频率高于 60Hz,避免肉眼闪烁
8位共阴数码管动态显示数字1-8
综合实训1 项目简介
本项目在八位共阴数码管上同时显示数字 1~8,即从右到左(或从左到右)8 个数码管分别显示 1、2、3、4、5、6、7、8。通过查表法获取不同数字的段码,配合位选扫描实现多位不同数字的显示。
掌握多位数码管显示不同内容的实现方法,理解位索引与段码表的联合使用,学会用 R0 索引位、用 DPTR 查表获取对应段码。
2 电路图
电路说明
- • P0 口连接 8 位共阴数码管共享段码线 a~g、dp,高电平点亮段
- • P2.2、P2.3、P2.4 接 74HC138 的 A、B、C 选择端
- • 138 的 E1 接 VCC、E2、E3 接地,Y0~Y7 低电平有效接各位公共端
- • 接线顺序:Y0 接最右侧第 8 位,Y7 接最左侧第 1 位
- • 采用查表法获取共阴段码,动态扫描刷新显示
3 仿真演示
仿真说明
- • 每轮先 MOV P0,#00H 真消隐,再切换 138 并输出段码,无串影
- • 因 Y0 接最右位、Y7 接最左位,选通位按 7-位索引 计算
- • 八位数码管从左到右依次显示数字1至8
4 程序内容(汇编语言)
;==================================================
; 项目名称:8位共阴数码管动态显示数字1-8
; 芯片型号:STC89C52RC
; 时钟频率:12MHz(机器周期=1μs)
; 段码线:P0 口(a~g、dp,高电平点亮段)
; 位选:74HC138 译码器,A/B/C 接 P2.2/P2.3/P2.4
; E1 接 VCC,E2、E3 接地,Y0~Y7 低电平有效
; 接线:Y0 接最右位、Y7 接最左位
; 显示内容:8 位数码管从左到右依次显示 1~8
; 扫描方式:P0=0 真消隐 → 选 7-位索引对应位 → 出段码,每位约 2ms
;==================================================
ORG 0000H ; 程序从复位向量 0000H 开始
LJMP MAIN ; 跳转到主程序入口
; 共阴数码管段码表 0~9(段码中为 1 的位点亮对应段)
ORG 0100H
SEGTAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
; 主程序:初始化
MAIN: MOV R0, #0 ; R0 = 位索引 0~7
MOV P0, #00H ; 段码全低,初始所有段熄灭
MOV P2, #00H ; 138 初始选择码 000
; 扫描循环:P0=0 真消隐;数字=位索引+1;选通 7-位索引 对应的物理位
SCAN8: MOV P0, #00H ; ①真消隐:段全灭,切换位选时不产生串影
MOV A, R0
INC A ; ②数字 = 位索引 + 1(1~8)
MOV DPTR, #SEGTAB
MOVC A, @A+DPTR ; ③查表得段码
MOV R1, A ; 暂存段码到 R1
MOV A, #7
CLR C
SUBB A, R0 ; ④物理位索引 = 7 - 位索引(Y7=最左第1位)
RL A
RL A ; ⑤×4 形成 P2.2~P2.4 选择码
MOV P2, A ; ⑥切换 138(此刻 P0 仍全灭)
MOV P0, R1 ; ⑦段码稳定输出,点亮该位
LCALL DELAY2 ; 保持约 2ms
INC R0
CJNE R0, #8, SCAN8 ; 8 位未扫完继续
MOV R0, #0 ; 索引归零,循环往复
SJMP SCAN8
; 约 2ms 延时子程序:控制每位点亮时间(只用 R7、R6,不碰 R0)
DELAY2: MOV R7, #23
D2_1: MOV R6, #28
D2_2: NOP
DJNZ R6, D2_2 ; 内层 28×(1+2)=84 周期
DJNZ R7, D2_1 ; 23×(1+84+2)=2001 周期
RET ; 合计约 2002μs ≈ 2ms
END
5 评分标准
| 评分项 | 分值 | 评分标准 |
|---|---|---|
| 位选与段码配合 | 30分 | 8 位位选与 1~8 数字一一对应,无错位 |
| 程序编写 | 40分 | 代码正确、规范,注释清晰 |
| 功能实现 | 20分 | 8 位数码管稳定显示 1~8 |
| 实训报告 | 10分 | 报告内容完整、整洁 |
6 注意事项与安全规范
查表索引
段码表索引 0 对应数字 0,显示 1~8 时索引应为 1~8
显示稳定性
每位点亮时间保持一致,避免亮度不均
8位共阴数码管广告流水灯效果
进阶实训1 项目简介
本项目在八位共阴数码管上实现广告流水灯效果:一个光点沿显示屏边框顺时针循环跑动——先从第 1 位到第 8 位依次点亮 a 段(上边),再经第 8 位 b、c 段转弯(右边),沿第 8 位到第 1 位依次点亮 d 段(下边),最后经第 1 位 e、f 段回到起点(左边),共 20 步闭环,每步约 0.16 秒,如同广告灯箱上绕圈跑动的光点。程序用路径表存放 20 步的位序号与段码,通过 RAM 缓冲区保存显示内容,更新与扫描分离。
掌握显示缓冲区的概念,理解动态扫描与内容更新的分离,学会使用定时器或软件延时控制流水速度。
2 电路图
电路说明
- • P0 口连接 8 位共阴数码管共享段码线 a~g、dp,高电平点亮段
- • P2.2、P2.3、P2.4 接 74HC138 的 A、B、C 选择端
- • 138 的 E1 接 VCC、E2、E3 接地,Y0~Y7 低电平有效接各位公共端(Y7 为第 1 位最左,Y0 为第 8 位最右)
- • RAM 显示缓冲区保存各位段码,光点约每 0.16 秒沿边框走一步
- • 扫描与数据更新分离,保证显示稳定无闪烁
3 仿真演示
仿真说明
- • 任一时刻只有一段点亮,光点沿显示屏边框顺时针走动
- • 光点从第 1 位(最左)出发:上边从左往右依次点亮 1~8 位 a 段 → 第 8 位 b、c 段 → 下边从右往左依次点亮 8~1 位 d 段 → 第 1 位 e、f 段,每步约 0.16 秒循环
4 程序内容(汇编语言)
;==================================================
; 项目名称:8位共阴数码管广告流水灯效果(边框跑灯)
; 芯片型号:STC89C52RC
; 时钟频率:12MHz(机器周期=1μs)
; 段码线:P0 口(a~g、dp,高电平点亮段)
; 位选:74HC138 译码器,A/B/C 接 P2.2/P2.3/P2.4
; E1 接 VCC,E2、E3 接地,Y0~Y7 低电平有效
; (Y7 接第 1 位最左,Y0 接第 8 位最右)
; 显示缓冲区:内部 RAM 30H~37H 存各位段码(仅光点位非 0)
; 30H 为第 1 位(最左),37H 为第 8 位(最右)
; 38H 存当前步序号(0~19)
; 显示效果:一个光点沿显示屏边框顺时针循环跑动:
; 上边第 1~8 位 a 段 → 第 8 位 b、c 段(右边)→
; 下边第 8~1 位 d 段 → 第 1 位 e、f 段(左边),
; 共 20 步闭环,每步约 0.16 秒
; 程序结构:主程序 + 4 个模块(初始化/更新/显示/延时)
; + 1 张路径表 TAB(每步 2 字节:位序号、段码)
;==================================================
ORG 0000H ; 程序从复位向量 0000H 开始
LJMP MAIN ; 跳转到主程序入口
;==================================================
; 路径表 TAB:光点沿边框顺时针走的 20 步路径
; 每步 2 字节:第 1 字节 = 位序号(0=第 1 位最左,7=第 8 位最右)
; 第 2 字节 = 段码(a=01H b=02H c=04H
; d=08H e=10H f=20H)
;==================================================
TAB: DB 0, 01H ; 第 1 位 a 段
DB 1, 01H ; 第 2 位 a 段
DB 2, 01H ; 第 3 位 a 段
DB 3, 01H ; 第 4 位 a 段
DB 4, 01H ; 第 5 位 a 段
DB 5, 01H ; 第 6 位 a 段
DB 6, 01H ; 第 7 位 a 段
DB 7, 01H ; 第 8 位 a 段
DB 7, 02H ; 第 8 位 b 段(右上角转弯)
DB 7, 04H ; 第 8 位 c 段
DB 7, 08H ; 第 8 位 d 段
DB 6, 08H ; 第 7 位 d 段
DB 5, 08H ; 第 6 位 d 段
DB 4, 08H ; 第 5 位 d 段
DB 3, 08H ; 第 4 位 d 段
DB 2, 08H ; 第 3 位 d 段
DB 1, 08H ; 第 2 位 d 段
DB 0, 08H ; 第 1 位 d 段
DB 0, 10H ; 第 1 位 e 段(左下角转弯)
DB 0, 20H ; 第 1 位 f 段(回到起点)
;==================================================
; 主程序:初始化 → 每 0.16s 光点走一步 → 循环
;==================================================
MAIN: LCALL INIT ; ① 初始化缓冲区与端口
MAINLP: MOV R5, #10 ; ② 扫描 10 遍:10×8位×2ms=0.16s
REFRESH:LCALL DISP8 ; 刷新一整屏(8 位各亮 2ms)
DJNZ R5, REFRESH
LCALL STEP ; ③ 光点沿边框走一步
SJMP MAINLP ; ④ 循环,形成边框跑灯
;==================================================
; 模块1:初始化子程序 INIT
; 功能:缓冲区 30H~37H 清零(全灭),按第 0 步把光点
; (第 1 位 a 段)写入缓冲区,步序号清零
;==================================================
INIT: MOV R0, #30H ; R0 指向缓冲区首单元
MOV R2, #8 ; 共 8 个单元
CLRBUF: MOV @R0, #00H ; 各位段码清零(全灭)
INC R0
DJNZ R2, CLRBUF ; 清完 8 个单元
MOV 30H, #01H ; 上电光点在第 1 位 a 段
MOV 38H, #0 ; 步序号 = 0
MOV P0, #00H ; 段码初始全灭
MOV P2, #00H ; 138 初始选择码 000
RET
;==================================================
; 模块2:更新子程序 STEP —— 光点沿边框走一步
; 功能:先清空缓冲区(熄灭上一步的段),再按步序号查
; 路径表 TAB,把新位序号、新段码写入缓冲区;
; 步序号 0~19 循环
;==================================================
STEP: MOV R0, #30H ; R0 指向缓冲区首单元
MOV R2, #8
CLRLP: MOV @R0, #00H ; 清缓冲区 = 熄灭上一步的段
INC R0
DJNZ R2, CLRLP
MOV DPTR, #TAB ; DPTR 指向路径表
MOV A, 38H ; 取步序号
RL A ; ×2 得表内偏移(每步 2 字节)
MOVC A, @A+DPTR ; 读第 1 字节:位序号
ADD A, #30H
MOV R0, A ; R0 指向光点所在缓冲单元
MOV A, 38H
RL A
INC A ; 偏移 + 1
MOVC A, @A+DPTR ; 读第 2 字节:段码
MOV @R0, A ; 光点段码写入缓冲区
INC 38H ; 步序号加 1,走向下一步
MOV A, 38H
CJNE A, #20, STEPEND ; 未走满 20 步,继续
MOV 38H, #0 ; 走满 20 步,回到第 1 步
STEPEND:RET
;==================================================
; 模块3:显示子程序 DISP8 —— 动态扫描一整屏
; 时序:每位先送缓冲区段码,再切 138 位选,亮约 2ms
;==================================================
DISP8: MOV R0, #30H ; R0 指向缓冲区首单元
MOV R2, #0 ; R2 = 当前位序号 0~7
DISPLP: MOV A, @R0 ; 取当前位段码(仅光点位非 0)
MOV P0, A ; ① 先输出段码
MOV A, R2
CPL A
ANL A, #07H ; ② 选择码=7-位序号(Y7=第1位最左)
RL A
RL A ; ③ 选择码×4 → P2.4~P2.2 接 138 C.B.A
MOV P2, A ; ④ 切换 138 选通对应位
LCALL DELAY2 ; ⑤ 点亮约 2ms
INC R0 ; 指向下一位(向右)
INC R2
CJNE R2, #8, DISPLP ; 8 位未扫完继续
RET
;==================================================
; 模块4:延时子程序 DELAY2 —— 约 2ms(只用 R7、R6)
;==================================================
DELAY2: MOV R7, #23
D2_1: MOV R6, #28
D2_2: NOP
DJNZ R6, D2_2 ; 内层 28×(1+2)=84 周期
DJNZ R7, D2_1 ; 23×(1+84+2)=2001 周期
RET ; 合计约 2002μs ≈ 2ms
END
5 评分标准
| 评分项 | 分值 | 评分标准 |
|---|---|---|
| 缓冲区管理 | 30分 | 使用 RAM 缓冲区保存显示内容,更新与扫描分离 |
| 程序编写 | 40分 | 代码正确、规范,注释清晰 |
| 功能实现 | 20分 | 光点沿边框顺时针循环跑动,20 步路径正确、速度均匀 |
| 实训报告 | 10分 | 报告内容完整、整洁 |
6 注意事项与安全规范
缓冲区更新
更新缓冲区时避免正在扫描读取,防止显示撕裂
流水速度
移动间隔约为 100~300ms(本项目约 160ms),过快无法看清,过慢显得卡顿
8位共阴数码管时分秒简易计时器
进阶实训1 项目简介
本项目利用 8051 定时器 0 产生 50ms 定时中断,在中断中累计秒、分、时,并通过八位共阴数码管动态扫描显示当前时间,格式为 HH-MM-SS(时-分-秒)。
掌握定时器中断配置与时间累计方法,理解中断服务程序与主程序的分工,学会将 BCD 码拆分后显示到多位数码管。
2 电路图
电路说明
- • P0 口连接 8 位共阴数码管共享段码线 a~g、dp,高电平点亮段
- • P2.2、P2.3、P2.4 接 74HC138 的 A、B、C 选择端
- • 138 的 E1 接 VCC、E2、E3 接地,Y0~Y7 低电平有效接各位公共端(Y7 为第 1 位最左,Y0 为第 8 位最右)
- • 显示格式为 HH-MM-SS,时、分、秒各占 2 位,中间以横杠分隔
- • 定时器 0 提供 50ms 中断时基,动态扫描保持显示
3 仿真演示
仿真说明
- • 定时器每50ms中断一次,累计秒、分、时并进位
- • 数码管按时分秒格式走时,秒位每秒加1
4 程序内容(汇编语言)
;==================================================
; 项目名称:8位共阴数码管时分秒简易计时器
; 芯片型号:STC89C52RC
; 时钟频率:12MHz(机器周期=1μs)
; 段码线:P0 口(a~g、dp,高电平点亮段)
; 位选:74HC138,A/B/C 接 P2.2/P2.3/P2.4
; E1 接 VCC,E2、E3 接地,Y0~Y7 低电平有效
; (Y7 接第 1 位最左,Y0 接第 8 位最右)
; 定时器:T0 模式 1,50ms 中断一次,累计 20 次为 1 秒
; 变量:30H 秒、31H 分、32H 时(BCD 码),33H 50ms 计数
; 显示:缓冲 40H~47H(40H 为第 1 位最左),格式 HH-MM-SS
;==================================================
ORG 0000H ; 程序从复位向量 0000H 开始
LJMP MAIN ; 跳转到主程序入口
ORG 000BH ; T0 中断入口
LJMP T0_ISR ; 跳转到 T0 中断服务程序
; 共阴数码管段码表 0~9(段码中为 1 的位点亮对应段)
ORG 0100H
SEGTAB: DB 03FH,006H,05BH,04FH,066H
DB 06DH,07DH,007H,07FH,06FH
; 时间变量定义在内部 RAM(BCD 码),不占用 ROM
SECOND DATA 30H ; 秒 00~59
MINUTE DATA 31H ; 分 00~59
HOUR DATA 32H ; 时 00~23
TICK50 DATA 33H ; 50ms 计数 0~20
; 主程序:清零变量、初始化定时器 0 与端口
MAIN: MOV SP, #60H ; 设置堆栈指针
MOV SECOND, #0
MOV MINUTE, #0
MOV HOUR, #0
MOV TICK50, #0 ; 时间变量全部清零
MOV P0, #00H ; 段码初始全灭
MOV P2, #00H ; 138 初始选择码 000
MOV TMOD, #01H ; T0 模式 1,16 位定时器
MOV TH0, #3CH ; 50ms 初值高字节(65536-50000)
MOV TL0, #0B0H ; 50ms 初值低字节
SETB ET0 ; 允许 T0 中断
SETB EA ; 开总中断
SETB TR0 ; 启动 T0
; 主循环:先组织显示缓冲,再扫描刷新一遍
MAINLP: LCALL BUILD_BUF
LCALL DISP_TIME
SJMP MAINLP
; T0 中断服务程序:每 50ms 进入一次,累计 20 次为 1 秒
T0_ISR: PUSH ACC ; 保护现场
PUSH PSW
MOV TH0, #3CH ; 重装初值
MOV TL0, #0B0H
INC TICK50 ; 50ms 计数加 1
MOV A, TICK50
CJNE A, #20, T0_EXIT; 未到 20 次(1 秒)退出
MOV TICK50, #0 ; 清零 50ms 计数器
LCALL ADD1SEC ; 时间加 1 秒
T0_EXIT:POP PSW ; 恢复现场
POP ACC
RETI
; 时间加 1 秒子程序
ADD1SEC:MOV A, SECOND
ADD A, #1
DA A ; 十进制调整
MOV SECOND, A
CJNE A, #60H, A1S_END; 秒未到 60 退出
MOV SECOND, #0
MOV A, MINUTE
ADD A, #1
DA A
MOV MINUTE, A
CJNE A, #60H, A1S_END; 分未到 60 退出
MOV MINUTE, #0
MOV A, HOUR
ADD A, #1
DA A
MOV HOUR, A
CJNE A, #24H, A1S_END; 时未到 24 退出
MOV HOUR, #0
A1S_END:RET
; 组织显示缓冲 40H~47H
; 布局:H十 H个 横杠 M十 M个 横杠 S十 S个(0AH=横杠标记)
BUILD_BUF:
MOV A, HOUR
SWAP A
ANL A, #0FH
MOV 40H, A ; 时十位
MOV A, HOUR
ANL A, #0FH
MOV 41H, A ; 时个位
MOV 42H, #0AH ; 横杠标记
MOV A, MINUTE
SWAP A
ANL A, #0FH
MOV 43H, A ; 分十位
MOV A, MINUTE
ANL A, #0FH
MOV 44H, A ; 分个位
MOV 45H, #0AH ; 横杠标记
MOV A, SECOND
SWAP A
ANL A, #0FH
MOV 46H, A ; 秒十位
MOV A, SECOND
ANL A, #0FH
MOV 47H, A ; 秒个位
RET
; 扫描显示子程序:依次扫描缓冲 40H~47H 到 8 位数码管
; 时序:P0=0 真消隐 → 选 7-位索引对应位 → 出段码,每位约 2ms
DISP_TIME:
MOV R0, #40H ; R0 指向缓冲区首单元(第 1 位)
MOV R2, #0 ; R2 = 位索引 0~7
DT_LP:
MOV P0, #00H ; ①真消隐:段全灭,切位时不串影
MOV A, @R0 ; 取数字或横杠标记 0AH
CJNE A, #0AH, DT_DIG; 非 0AH 按数字查表
MOV R1, #40H ; 横杠:仅 g 段(bit6)亮
SJMP DT_SEL
DT_DIG:
MOV DPTR, #SEGTAB
MOVC A, @A+DPTR ; 查数字段码
MOV R1, A ; 段码暂存 R1
DT_SEL:
MOV A, #7
CLR C
SUBB A, R2 ; ②选择码=7-位索引(Y7=第1位最左)
RL A
RL A ; 选择码×4 → P2.4~P2.2 接 C.B.A
MOV P2, A ; ③先切换 138(此刻 P0 仍全灭)
MOV P0, R1 ; ④再输出段码,点亮该位
LCALL DELAY2 ; 保持约 2ms
INC R0
INC R2
CJNE R2, #8, DT_LP ; 8 位未扫完继续
RET
; 约 2ms 延时子程序(只用 R7、R6,不碰时间变量)
DELAY2: MOV R7, #23
D2_1: MOV R6, #28
D2_2: NOP
DJNZ R6, D2_2 ; 内层 28×(1+2)=84 周期
DJNZ R7, D2_1 ; 23×(1+84+2)=2001 周期
RET ; 合计约 2002μs ≈ 2ms
END
5 评分标准
| 评分项 | 分值 | 评分标准 |
|---|---|---|
| 定时器配置 | 30分 | T0 正确配置为 50ms 中断,初值计算正确 |
| 程序编写 | 40分 | 代码正确、规范,时间累计与显示分离 |
| 功能实现 | 20分 | 计时器走时准确,数码管稳定显示时分秒 |
| 实训报告 | 10分 | 报告内容完整、整洁 |
6 注意事项与安全规范
中断保护
中断服务程序中必须保护 ACC 和 PSW,避免主循环显示被干扰
BCD 调整
时间累加后使用 DA 指令进行十进制调整,确保显示为 60 进制
8位共阴数码管时分秒可调计时器
综合实训1 项目简介
本项目在简易计时器基础上增加 3 个按键完成时间调校:S3 为“设置”键,按下后走时暂停、先选中“秒”,秒的两位以 0.5 秒闪烁提示;再按 S3 依次移到“分”、“时”,第四次按下“确定”退出并恢复自动走时。在设置状态下,S1 对被选中的项加 1、S2 减 1(分、秒在 00~59 之间、时在 00~23 之间循环)。时间格式仍为 HH-MM-SS。
掌握定时器中断、按键消抖、状态切换与多位动态扫描的综合应用,理解设置状态下用闪烁标志提示被调字段、以及暂停走时与按键修改时间变量的协同方法。
2 电路图
电路说明
- • P0 口连接 8 位共阴数码管共享段码线 a~g、dp,高电平点亮段
- • P2.2、P2.3、P2.4 接 74HC138 的 A、B、C 选择端
- • 138 的 E1 接 VCC、E2、E3 接地,Y0~Y7 低电平有效接各位公共端(Y7 为第 1 位最左,Y0 为第 8 位最右)
- • 三个按键低电平有效:S1 加1 接 P3.0,S2 减1 接 P3.1,S3 设置(移位/确定)接 P3.2
- • 定时器中断负责走时与闪烁计时,主循环负责按键扫描与动态显示
3 仿真演示
仿真说明
- • 上电自动从 00-00-00 走时;按 S3 走时暂停、秒两位闪烁,再按依次切换到分、时,第四次按确定恢复走时
- • 设置状态下 S1 加 1、S2 减 1,时 00~23、分秒 00~59 循环,调校时走时暂停,确定后继续走时
4 程序内容(汇编语言)
;==================================================
; 项目名称:8位共阴数码管时分秒可调计时器
; 芯片型号:STC89C52RC
; 时钟频率:12MHz(机器周期=1μs)
; 段码线:P0 口(a~g、dp,高电平点亮段)
; 位选:74HC138,A/B/C 接 P2.2/P2.3/P2.4
; E1 接 VCC,E2、E3 接地,Y0~Y7 低电平有效
; (Y7 接第 1 位最左,Y0 接第 8 位最右)
; 按键(低电平有效):S1=加1 接 P3.0,S2=减1 接 P3.1
; S3=设置(移位/确定)接 P3.2
; 定时器:T0 模式 1,50ms 中断一次,累计 20 次为 1 秒
; 变量(内部 RAM):30H 秒、31H 分、32H 时(BCD)
; 33H 50ms 计数、34H 设置状态、35H 闪烁计数
; 位 00H(20H.0)=闪烁亮灭标志
; 设置状态 34H:0=正常走时,1=调秒,2=调分,3=调时
; 操作:按 S3 依次 秒→分→时→确定退出;被选项每 0.5s
; 闪烁;设置期间 S1 加 1、S2 减 1,走时暂停
; 显示:缓冲 40H~47H(40H 为第 1 位最左),格式 HH-MM-SS
;==================================================
ORG 0000H ; 程序从复位向量 0000H 开始
LJMP MAIN ; 跳转到主程序入口
ORG 000BH ; T0 中断入口
LJMP T0_ISR ; 跳转到 T0 中断服务程序
; 共阴数码管段码表 0~9(段码中为 1 的位点亮对应段)
ORG 0100H
SEGTAB: DB 03FH,006H,05BH,04FH,066H
DB 06DH,07DH,007H,07FH,06FH
; 时间与状态变量定义在内部 RAM(BCD 码),不占用 ROM
SECOND DATA 30H ; 秒 00~59
MINUTE DATA 31H ; 分 00~59
HOUR DATA 32H ; 时 00~23
TICK50 DATA 33H ; 50ms 计数 0~20
SETMD DATA 34H ; 设置状态 0走时/1时/2分/3秒
BLINKC DATA 35H ; 闪烁 50ms 计数 0~10
BLINKF BIT 00H ; 闪烁标志:1 显示,0 熄灭
; 主程序:清零变量、初始化端口与定时器 0
MAIN: MOV SP, #60H ; 设置堆栈指针
MOV SECOND, #0
MOV MINUTE, #0
MOV HOUR, #0
MOV TICK50, #0
MOV SETMD, #0 ; 上电为正常走时状态
MOV BLINKC, #0
CLR BLINKF ; 变量与标志全部清零
MOV P0, #00H ; 段码初始全灭
MOV P2, #00H ; 138 初始选择码 000
MOV P3, #0FFH ; P3 口置 1,配置为按键输入
MOV TMOD, #01H ; T0 模式 1,16 位定时器
MOV TH0, #3CH ; 50ms 初值高字节(65536-50000)
MOV TL0, #0B0H ; 50ms 初值低字节
SETB ET0 ; 允许 T0 中断
SETB EA ; 开总中断
SETB TR0 ; 启动 T0
; 主循环:按键处理 → 组织缓冲 → 扫描刷新
MAINLP: LCALL KEY
LCALL BUILD
LCALL SCAN
SJMP MAINLP
;==================================================
; T0 中断服务程序:每 50ms 进入一次
; 走时状态:累计 20 次为 1 秒;设置状态:闪烁计数
;==================================================
T0_ISR: PUSH ACC ; 保护现场
PUSH PSW
MOV TH0, #3CH ; 重装初值
MOV TL0, #0B0H
MOV A, SETMD
JZ TI_RUN ; 状态 0:正常走时
INC BLINKC ; 设置状态:只做闪烁计时
MOV A, BLINKC
CJNE A, #10, TI_EXIT; 未满 10 次(0.5s)退出
MOV BLINKC, #0
CPL BLINKF ; 每 0.5s 翻转亮灭
SJMP TI_EXIT
TI_RUN: INC TICK50 ; 50ms 计数加 1
MOV A, TICK50
CJNE A, #20, TI_EXIT; 未到 20 次(1 秒)退出
MOV TICK50, #0
LCALL ADD1SEC ; 时间加 1 秒
TI_EXIT:POP PSW ; 恢复现场
POP ACC
RETI
;==================================================
; 时间加 1 秒子程序(秒→分→时,BCD 进位)
; 注意:此处为原始进位判断,不能调用带循环的 ADD_SEC
;==================================================
ADD1SEC:MOV A, SECOND
ADD A, #1
DA A
MOV SECOND, A
CJNE A, #60H, A1S_END; 秒未到 60 退出
MOV SECOND, #0
MOV A, MINUTE
ADD A, #1
DA A
MOV MINUTE, A
CJNE A, #60H, A1S_END; 分未到 60 退出
MOV MINUTE, #0
MOV A, HOUR
ADD A, #1
DA A
MOV HOUR, A
CJNE A, #24H, A1S_END; 时未到 24 退出
MOV HOUR, #0 ; 24 时归零
A1S_END:RET
;==================================================
; 模块3:按键处理 KEY
; KEY_RD:读键并消抖,A=键码(0无/1加/2减/3设置)
; 按设置键状态依次为 秒(1)→分(2)→时(3)→走时(0);
; 走时状态下加、减键无效;动作后等键松开,期间持续刷新
;==================================================
KEY: LCALL KEY_RD
JZ KEY_END ; 无键按下,退出
CJNE A, #3, KEY_ADJ ; 非设置键,转加减处理
MOV A, SETMD ; 设置键:状态加 1
INC A
CJNE A, #4, KEY_S1
MOV A, #0 ; 第 4 次按下:确定,恢复走时
KEY_S1: MOV SETMD, A
MOV BLINKC, #0 ; 切换后先亮 0.5s
SETB BLINKF
SJMP KEY_WAIT
KEY_ADJ:
MOV R5, A ; R5 暂存键码(1 加 / 2 减)
MOV A, SETMD
JZ KEY_WAIT ; 走时状态:加减键无效
MOV A, R5
CJNE A, #2, KEY_ADD
LCALL SUB_ONE ; 当前项减 1
SJMP KEY_WAIT
KEY_ADD:LCALL ADD_ONE ; 当前项加 1
KEY_WAIT:
LCALL BUILD ; 等待松开期间持续刷新,
LCALL SCAN ; 数码管不黑屏
MOV A, P3
CPL A
ANL A, #07H
JNZ KEY_WAIT
KEY_END:RET
; 读键子模块:P3.0/P3.1/P3.2 低电平=按下
; 返回 A=3(S3)/2(S2)/1(S1)/0(无键),带 10ms 消抖
KEY_RD: MOV A, P3
CPL A
ANL A, #07H
JZ KR_END ; 全为高,无键
LCALL DELAY10 ; 消抖
MOV A, P3
CPL A
ANL A, #07H
JZ KR_END
JB ACC.2, KR_S3 ; P3.2=设置键
JB ACC.1, KR_S2 ; P3.1=减 1 键
MOV A, #1 ; P3.0=加 1 键
RET
KR_S3: MOV A, #3
RET
KR_S2: MOV A, #2
KR_END: RET
;==================================================
; 模块4:当前项加 1 / 减 1(按 SETMD 选字段,BCD)
; 秒、分在 00~59 之间循环,时在 00~23 之间循环
;==================================================
ADD_ONE:
MOV A, SETMD
CJNE A, #2, AO1
MOV A, MINUTE ; 状态 2:分加 1
ADD A, #1
DA A
CJNE A, #60H, AOM
MOV A, #0
AOM: MOV MINUTE, A
RET
AO1: CJNE A, #3, AO0
MOV A, HOUR ; 状态 3:时加 1
ADD A, #1
DA A
CJNE A, #24H, AOH
MOV A, #0
AOH: MOV HOUR, A
RET
AO0: MOV A, SECOND ; 状态 1:秒加 1
ADD A, #1
DA A
CJNE A, #60H, AOS
MOV A, #0
AOS: MOV SECOND, A
RET
SUB_ONE:
MOV A, SETMD
CJNE A, #2, SO1
MOV A, MINUTE ; 状态 2:分减 1,00→59
JZ SO_M59
ADD A, #99H ; BCD 减 1
DA A
SJMP SOM
SO_M59: MOV A, #59H
SOM: MOV MINUTE, A
RET
SO1: CJNE A, #3, SO0
MOV A, HOUR ; 状态 3:时减 1,00→23
JZ SO_H23
ADD A, #99H
DA A
SJMP SOH
SO_H23: MOV A, #23H
SOH: MOV HOUR, A
RET
SO0: MOV A, SECOND ; 状态 1:秒减 1,00→59
JZ SO_S59
ADD A, #99H
DA A
SJMP SOS
SO_S59: MOV A, #59H
SOS: MOV SECOND, A
RET
;==================================================
; 模块5:组织显示缓冲 BUILD(40H~47H)
; 布局:H十 H个 横杠 M十 M个 横杠 S十 S个
; 0AH=横杠(段码 40H),0BH=闪烁熄灭
;==================================================
BUILD: MOV R0, #40H
MOV A, HOUR
LCALL SPLIT ; 拆时两位 → 40H、41H
MOV @R0, #0AH ; 横杠 → 42H
INC R0
MOV A, MINUTE
LCALL SPLIT ; 拆分两位 → 43H、44H
MOV @R0, #0AH ; 横杠 → 45H
INC R0
MOV A, SECOND
LCALL SPLIT ; 拆秒两位 → 46H、47H
MOV A, SETMD ; 走时状态不闪烁
JZ BL_END
JB BLINKF, BL_END ; 亮半秒照常显示
CJNE A, #1, BL1
MOV 46H, #0BH ; 调秒:秒两位熄灭
MOV 47H, #0BH
SJMP BL_END
BL1: CJNE A, #2, BL2
MOV 43H, #0BH ; 调分:分两位熄灭
MOV 44H, #0BH
SJMP BL_END
BL2: MOV 40H, #0BH ; 调时:时两位熄灭
MOV 41H, #0BH
BL_END: RET
; BCD 拆分子模块:A=BCD 值,拆成十位、个位写入 R0 所指两单元
SPLIT: MOV B, A
SWAP A
ANL A, #0FH
MOV @R0, A ; 十位
INC R0
MOV A, B
ANL A, #0FH
MOV @R0, A ; 个位
INC R0
RET
;==================================================
; 模块6:动态扫描 SCAN(P0=0 消隐 → 选位 → 出段码)
;==================================================
SCAN: MOV R0, #40H
MOV R2, #0
SLP: MOV P0, #00H ; ①消隐:切位时不串影
MOV A, @R0
CJNE A, #0AH, SN1
MOV R1, #40H ; 横杠:仅 g 段亮
SJMP SSEL
SN1: CJNE A, #0BH, SN2
MOV R1, #00H ; 闪烁:该位熄灭
SJMP SSEL
SN2: MOV DPTR, #SEGTAB
MOVC A, @A+DPTR ; 数字查段码
MOV R1, A
SSEL: MOV A, #7
CLR C
SUBB A, R2 ; ②选择码=7-位索引(Y7=第1位)
RL A
RL A
MOV P2, A ; ③先选位(P0 仍全灭)
MOV P0, R1 ; ④再出段码
LCALL DELAY2
INC R0
INC R2
CJNE R2, #8, SLP
RET
;==================================================
; 模块7:约 10ms 按键消抖延时(只用 R3、R4)
;==================================================
DELAY10:MOV R3, #10
D10_1: MOV R4, #248
D10_2: NOP
DJNZ R4, D10_2
DJNZ R3, D10_1
RET
;==================================================
; 模块8:约 2ms 动态扫描延时(只用 R7、R6)
;==================================================
DELAY2: MOV R7, #23
D2_1: MOV R6, #28
D2_2: NOP
DJNZ R6, D2_2
DJNZ R7, D2_1
RET
END
5 评分标准
| 评分项 | 分值 | 评分标准 |
|---|---|---|
| 按键调时 | 30分 | S3 移位/确定逻辑正确,被选项闪烁提示;S1/S2 加减有效,带消抖 |
| 程序编写 | 40分 | 代码正确、规范,定时器、按键、显示协调 |
| 功能实现 | 20分 | 可调计时器走时准确,按键调时即时生效 |
| 实训报告 | 10分 | 报告内容完整、整洁 |
6 注意事项与安全规范
按键消抖
调时按键必须进行软件消抖,并在释放前保持单次触发
中断安全
调时修改时间变量时,中断仍在运行,建议短暂关中断或确保操作原子性
项目导航
学习要点
实训目标
通过本项目学习,学生将掌握共阳、共阴数码管的驱动原理,理解静态显示与动态扫描的区别,能够使用查表法实现数字显示,并综合运用定时器中断和按键完成可调计时器项目。