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
相关产品推荐
相关产品推荐

