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

基于AT89S52的8051汇编行人过街灯程序问题排查

AT89S52行人过街灯汇编程序错误排查

问题概述

使用MCU 8051 IDE编写AT89S52单片机的行人过街灯汇编程序,需求如下:

  • 系统初始处于STOP状态(对应P1.0连接的LED点亮,P1.1熄灭)
  • 按下按钮后,延迟切换至GO状态(P1.1点亮,P1.0熄灭)并保持更长时长,随后返回STOP状态循环

但当前代码运行异常:

  • 初始时P1.0、P1.1连接的LED均点亮
  • 按下按钮后P1.0熄灭且不再亮起,P1.1持续点亮

代码错误分析

1. 初始状态不符合需求

代码开头执行MOV P1,#00H,将P1口所有引脚置为低电平(假设LED为阴极接P1、阳极接VCC的共阳接法,低电平点亮),导致两个LED同时点亮,违背了初始STOP状态仅P1.0点亮的要求。

2. 按键检测逻辑完全颠倒

按键检测部分的条件判断逻辑错误:

  • JNB P2.0, BUTTON_RELEASED:若P2.0为低电平(按键按下状态,假设按键为下拉式,按下接地),直接跳转到重置计数器的分支,无法正确识别稳定的按键按下动作
  • 后续的JB P2.0, CHECK_BUTTON_STATE也对应错误,导致按键检测逻辑完全失效,实际是在等待按键释放而非按下

3. 延时函数不匹配需求

  • DELAY_SEC实际延时过短:该函数仅循环调用5次DELAY_MS,而DELAY_MS的实际延时远不到1秒,无法满足状态切换的时长要求
  • GO状态与STOP状态延时相同:需求中GO状态需保持更长时长,但当前代码中两者均调用DELAY_SEC,时长一致

4. 未处理按键释放,易触发重复执行

检测到按键按下后未等待按键释放,若按键长按会导致程序逻辑混乱,或单次按下触发多次状态切换

修正方案

1. 修正初始状态

将初始P1口设置为STOP状态:若采用共阳LED(低电平点亮),则设置MOV P1,#0FEH(二进制11111110,仅P1.0为低电平点亮,其余引脚高电平熄灭);若为共阴LED(高电平点亮),则设置MOV P1,#01H(仅P1.0为高电平点亮)。

2. 修正按键检测逻辑

调整按键检测的判断条件,确保正确识别稳定的按键按下动作(以下假设按键为下拉式,按下时P2.0为低电平):

  • 先检测按键是否按下(P2.0为低),再通过多次检测确认状态稳定,避免抖动
  • 检测到稳定按下后,等待按键释放再进入状态循环

3. 调整延时函数,区分GO/STOP时长

  • 修正DELAY_MS的参数,使其接近真实1ms延时(根据AT89S52的12MHz晶振调整)
  • 新增更长的延时函数DELAY_LONG_SEC,用于GO状态的长时长保持

4. 优化状态循环逻辑

确保进入循环后严格按照STOP→GO→STOP的顺序执行,且时长符合需求

修正后的完整代码

ORG 00H ; 程序起始地址
    
    ; 初始化端口:假设LED为共阳接法(低电平点亮)
    MOV P1,#0FEH  ; 初始STOP状态:P1.0亮,P1.1灭
    MOV P2,#0FFH  ; P2口设置为输入,上拉
    
WAIT_FOR_BUTTON_PRESS:
    MOV R2, #03H  ; 防抖计数器

CHECK_BUTTON_PRESSED:
    JNB P2.0, CONFIRM_PRESS  ; 检测到按键按下(P2.0低),进入确认
    MOV R2, #03H  ; 未按下,重置计数器
    SJMP WAIT_FOR_BUTTON_PRESS

CONFIRM_PRESS:
    CALL DELAY_MS  ; 防抖延时
    JNB P2.0, DEC_COUNT  ; 仍按下,计数器减1
    MOV R2, #03H  ; 已释放,重置计数器
    SJMP WAIT_FOR_BUTTON_PRESS

DEC_COUNT:
    DEC R2
    JNZ CONFIRM_PRESS  ; 未到稳定次数,继续检测

WAIT_RELEASE:
    JB P2.0, ENTER_LOOP  ; 等待按键释放
    SJMP WAIT_RELEASE

ENTER_LOOP:
    ; 按下后先保持STOP状态一段时间
    MOV P1,#0FEH
    CALL DELAY_SEC

TRAFFIC_LIGHT_LOOP:
    ; 切换到GO状态,保持更长时间
    MOV P1,#0FDH  ; P1.1亮,P1.0灭
    CALL DELAY_LONG_SEC

    ; 返回STOP状态
    MOV P1,#0FEH
    CALL DELAY_SEC

    SJMP TRAFFIC_LIGHT_LOOP ; 循环执行

; 约1ms延时(基于12MHz晶振)
DELAY_MS:
    MOV R1, #2
DELAY_MS_LOOP1:
    MOV R0, #248
DELAY_MS_LOOP2:
    DJNZ R0, DELAY_MS_LOOP2
    DJNZ R1, DELAY_MS_LOOP1
    RET

; 约1秒延时
DELAY_SEC:
    MOV R1, #200
DELAY_SEC_LOOP:
    CALL DELAY_MS
    DJNZ R1, DELAY_SEC_LOOP
    RET

; 约5秒延时(GO状态长时长)
DELAY_LONG_SEC:
    MOV R1, #1000
DELAY_LONG_SEC_LOOP:
    CALL DELAY_MS
    DJNZ R1, DELAY_LONG_SEC_LOOP
    RET

    END

说明

  • 若LED为共阴接法(高电平点亮),需将P1口的设置值对应修改:
    • STOP状态:MOV P1,#01H(P1.0高电平点亮)
    • GO状态:MOV P1,#02H(P1.1高电平点亮)
  • 延时函数参数可根据实际晶振频率微调,确保延时时长符合需求

内容的提问来源于stack exchange,提问作者Dennis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 23:43:11