You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于8051的两位倒计时计时器启停按钮功能实现求助

基于8051的两位倒计时计时器启停按钮功能实现求助

嘿,我看了你这段8051汇编的倒计时代码,要给它加上P3.2端口的启停按钮功能,确实得调整原有的线性执行逻辑——毕竟原来的代码是一路跑到底,没留出处理按键输入的空间。咱们一步步来解决这个问题:

核心思路说明

要实现启停/暂停/继续的功能,需要三个关键环节:

  • 用一个状态寄存器记录当前计时器是「暂停」还是「运行」状态
  • 给按键加消抖处理,避免机械抖动导致的误触发
  • 把原有的线性倒计时逻辑改成循环检测结构,在每个计时周期前后检查按键状态

修改后的完整代码

$MOD51  ; This includes 8051 definitions for the Metalink assembler

; 状态定义:R3=0 代表暂停,R3=1 代表运行
STATE_PAUSE EQU 0
STATE_RUN   EQU 1

; 全局变量:存储当前倒计时的十位和个位数值
; R4 = 十位数字(初始9),R5 = 个位数字(初始9)
start:
    MOV R3, #STATE_PAUSE  ; 初始状态设为暂停
    MOV R4, #9            ; 初始化十位为9
    MOV R5, #9            ; 初始化个位为9
    LCALL UPDATE_DISPLAY  ; 显示初始值99

main_loop:
    LCALL CHECK_BUTTON    ; 每次循环先检查按键状态
    CJNE R3, #STATE_RUN, main_loop  ; 如果是暂停状态,循环等待按键

    ; 运行状态:执行倒计时逻辑
    LCALL WAIT            ; 等待一个计时周期
    LCALL DECREMENT_COUNT ; 递减倒计时数值
    LCALL UPDATE_DISPLAY  ; 更新显示
    SJMP main_loop        ; 回到主循环

; ---------------------------
; 按键检测与状态切换子程序
; 按键接P3.2,低电平有效(可根据硬件调整)
; ---------------------------
CHECK_BUTTON:
    JB P3.2, BUTTON_EXIT  ; 如果按键没按下(高电平),直接退出
    LCALL SHORT_DELAY     ; 消抖延迟
    JB P3.2, BUTTON_EXIT  ; 再次检查,确认真的按下
    ; 等待按键松开,避免持续触发
WAIT_RELEASE:
    JNB P3.2, WAIT_RELEASE
    LCALL SHORT_DELAY     ; 松开时也消抖
    ; 切换状态
    CPL R3
BUTTON_EXIT:
    RET

; ---------------------------
; 倒计时数值递减子程序
; ---------------------------
DECREMENT_COUNT:
    MOV A, R5
    CJNE A, #0, DEC_ONE   ; 如果个位不是0,直接减1
    ; 个位是0,十位减1,个位设为9
    MOV R5, #9
    MOV A, R4
    CJNE A, #0, DEC_TEN
    ; 十位也为0,倒计时结束,切换为暂停状态
    MOV R3, #STATE_PAUSE
    RET
DEC_ONE:
    DEC R5
    RET
DEC_TEN:
    DEC R4
    RET

; ---------------------------
; 更新显示子程序
; 控制数码管显示当前十位和个位数值
; ---------------------------
UPDATE_DISPLAY:
    ; 显示十位
    SETB P3.5
    MOV A, R4
    LCALL DISPLAY
    MOV P1, A
    CLR P3.5
    LCALL SHORT_DELAY     ; 数码管切换延迟

    ; 显示个位
    MOV A, R5
    LCALL DISPLAY
    MOV P1, A
    RET

; ---------------------------
; 原有的等待子程序(计时周期)
; ---------------------------
WAIT:
    MOV R0, #0
    MOV R2, #8
DELAY_LOOP:
    DJNZ R0, DELAY_LOOP
    DJNZ R2, DELAY_LOOP
    RET

; ---------------------------
; 短延迟子程序(用于按键消抖和数码管切换)
; ---------------------------
SHORT_DELAY:
    MOV R1, #255
SHORT_LOOP:
    DJNZ R1, SHORT_LOOP
    RET

; ---------------------------
; 数码管段码查找子程序
; ---------------------------
DISPLAY:
    INC A
    MOVC A, @A+PC
    RET
DB 0C0H ;0
DB 0F9H ;1
DB 0A4H ;2
DB 0B0H ;3
DB 99H ;4
DB 92H ;5
DB 82H ;6
DB 0F8H ;7
DB 80H ;8
DB 90H ;9
DB 88H ;A
DB 83H ;B
DB 0C6H ;C
DB 0A1H ;D
DB 86H ;E
DB 8EH ;F

END

关键部分解释

  1. 状态管理:用R3寄存器存储当前状态,初始为暂停,每次按键按下就切换状态(CPL R3)。主循环会根据状态决定是等待按键还是执行倒计时。
  2. 按键消抖:SHORT_DELAY子程序用来过滤机械按键的抖动,检测到按键按下后,先延迟再确认电平,还要等待按键松开才切换状态,避免一次按下触发多次切换。
  3. 倒计时逻辑重构:原来的硬编码倒计时被改成了用R4(十位)和R5(个位)存储数值,DECREMENT_COUNT子程序负责递减数值,到00时自动暂停。
  4. 显示更新:UPDATE_DISPLAY子程序负责轮流刷新十位和个位数码管,保证两位数字正常显示。

注意事项

  • 请确认你的按键硬件连接:如果按键是高电平有效,需要把JB P3.2, BUTTON_EXIT改成JNB P3.2, BUTTON_EXIT,相应的等待松开逻辑也要调整。
  • 如果计时速度不符合预期,可以调整WAIT子程序里的R0、R2数值,或者SHORT_DELAY的R1数值来改变延迟时长。

备注:内容来源于stack exchange,提问作者Linfoe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 14:24:32