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

PIC16F84A单片机门监控系统七段显示字符间1秒延时功能实现求助

PIC16F84A单片机门监控系统七段显示字符间1秒延时功能实现求助

嘿,我帮你梳理下当前代码里的问题,以及怎么实现字符间的1秒延时:

首先说下导致你卡住的核心问题:

  • 变量定义冲突:你用D1 EQU B'100'这类语句定义的是重复的常量地址(十进制4),三个延时计数器共用同一个寄存器,导致延时逻辑完全混乱,根本达不到预期时长,还会打乱程序执行流。
  • 延时子程序位置错误:你把Delay子程序嵌套在了S1分支里,还加了ORG 30H强行改变程序地址,程序执行到这里就会陷入错误循环,没法回到显示后续字符的逻辑。
  • 显示逻辑缺少延时调用:你现在是连续把多个字符的七段码写到PORTB,没有在每个字符之间插入延时,就算延时正常,也会因为刷新太快看不到单个字符,更别说当前延时本身就有问题。

下面是修改后的完整代码,我标注了关键修改点:

; 修正:把延时计数器定义为RAM中的不同空闲寄存器(PIC16F84A Bank0的0C-0E地址可用)
D1 EQU 0CH
D2 EQU 0DH
D3 EQU 0EH

LIST P=PIC16F84A
#INCLUDE<P16F84A.INC>

; 修正:指定程序起始地址为复位地址00H
ORG 00H

; 初始化端口
BSF STATUS,5          ; 切换到Bank1
MOVLW 0X0F
MOVWF TRISA           ; RA0-RA3设为输入
CLRF TRISB            ; RB0-RB7设为输出
BCF STATUS,5          ; 切回Bank0

; 主循环入口
MAIN
T1 BTFSS PORTA,0
GOTO T2
GOTO T4

T2 BTFSS PORTA,1
GOTO T3
GOTO T6

T3 BTFSS PORTA,2
GOTO S1               ; 仅D3开门
GOTO S2               ; 全关,显示NONE

T4 BTFSS PORTA,1
GOTO T7
GOTO T5

T5 BTFSS PORTA,2
GOTO S7               ; D1+D2开门
GOTO S8               ; 全开,显示ALL

T6 BTFSS PORTA,2
GOTO S3               ; D2+D3开门
GOTO S4               ; D2开门

T7 BTFSS PORTA,2
GOTO S5               ; D1+D3开门
GOTO S6               ; D1开门

; 仅D3开门,显示D3
S1 
MOVLW 0X37            ; D的七段码
MOVWF PORTB
CALL Delay            ; 延时1秒
MOVLW 0X06            ; 3的七段码
MOVWF PORTB
CALL Delay
GOTO MAIN_CHECK       ; 回到状态检测

; 全关,显示NONE
S2 
MOVLW 0X5E            ; N的七段码
MOVWF PORTB
CALL Delay
MOVLW 0X4F            ; O的七段码
MOVWF PORTB
CALL Delay
MOVLW 0X5E            ; N的七段码
MOVWF PORTB
CALL Delay
MOVLW 0X79            ; E的七段码
MOVWF PORTB
CALL Delay
GOTO MAIN_CHECK

; D2+D3开门,显示D2D3
S3 
MOVLW 0X37            ; D
MOVWF PORTB
CALL Delay
MOVLW 0X5B            ; 2
MOVWF PORTB
CALL Delay
MOVLW 0X37            ; D
MOVWF PORTB
CALL Delay
MOVLW 0X06            ; 3
MOVWF PORTB
CALL Delay
GOTO MAIN_CHECK

; D2开门,显示D2
S4 
MOVLW 0X37            ; D
MOVWF PORTB
CALL Delay
MOVLW 0X5B            ; 2
MOVWF PORTB
CALL Delay
GOTO MAIN_CHECK

; D1+D3开门,显示D1D3
S5 
MOVLW 0X37            ; D
MOVWF PORTB
CALL Delay
MOVLW 0X3F            ; 1
MOVWF PORTB
CALL Delay
MOVLW 0X37            ; D
MOVWF PORTB
CALL Delay
MOVLW 0X06            ; 3
MOVWF PORTB
CALL Delay
GOTO MAIN_CHECK

; D1开门,显示D1
S6 
MOVLW 0X37            ; D
MOVWF PORTB
CALL Delay
MOVLW 0X3F            ; 1
MOVWF PORTB
CALL Delay
GOTO MAIN_CHECK

; D1+D2开门,显示D1D2
S7 
MOVLW 0X37            ; D
MOVWF PORTB
CALL Delay
MOVLW 0X3F            ; 1
MOVWF PORTB
CALL Delay
MOVLW 0X37            ; D
MOVWF PORTB
CALL Delay
MOVLW 0X5B            ; 2
MOVWF PORTB
CALL Delay
GOTO MAIN_CHECK

; 全开,显示ALL
S8 
MOVLW 0X77            ; A
MOVWF PORTB
CALL Delay
MOVLW 0X38            ; L
MOVWF PORTB
CALL Delay
MOVLW 0X38            ; L
MOVWF PORTB
CALL Delay
GOTO MAIN_CHECK

; 状态检测分支,处理报警逻辑
MAIN_CHECK
BTFSC PORTA,3
BSF PORTA,4           ; RA3触发报警
BTFSS PORTA,3
BCF PORTA,4
GOTO MAIN

; 修正:独立的1秒延时子程序(基于4MHz晶振,指令周期1μs,计算后接近1秒)
Delay 
MOVLW D'200'
MOVWF D1
Delay_Outer
MOVLW D'200'
MOVWF D2
Delay_Mid
MOVLW D'25'
MOVWF D3
Delay_Inner
NOP
DECFSZ D3,1
GOTO Delay_Inner
DECFSZ D2,1
GOTO Delay_Mid
DECFSZ D1,1
GOTO Delay_Outer
RETURN

END

额外说明:

  • 我假设你用的是4MHz晶振,如果晶振频率不同,需要调整延时子程序里的循环数值来凑够1秒,你可以根据指令周期(Fosc/4)计算总循环次数。
  • 七段码沿用了你原来的定义,如果你的七段显示是共阳或共阴类型,可能需要调整码值,这个可以根据自己的硬件核对。
  • 主循环的状态检测逻辑我尽量保留了你原来的结构,你可以再核对下每个分支对应的门状态是否正确。

这样修改后,每个字符显示后都会调用1秒延时,程序也不会卡住,能正常循环检测门状态并更新显示~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 12:44:34