📄 traffic light firmware.asm
字号:
CHIP SN8P2604
//{{SONIX_CODE_OPTION
.Code_Option Noise_Filter Disable
.Code_Option Reset_Pin Reset
.Code_Option Watch_Dog Disable ; Disable Watchdog
.Code_Option High_Clk 4M_X'tal ; Crystal/Resonator: 2Mhz~10Mhz
.Code_Option Fcpu #2 ; Fcpu = High_Clk/4
.Code_Option Security Disable
//}}SONIX_CODE_OPTION
.DATA
DLY1 DS 02H
DLY2 DS 03H ;延时程序暂存器
TIMER00 EQU 04H ;tc1中断计数器
TIMER01 EQU 05H ;t0中断计数器
S_CNT EQU 06H
S_BIT EQU 07H
DISP1 EQU 0AH
DISP2 EQU 0BH
DISP3 EQU 0CH
DISP4 EQU 0DH
N_L EQU 10H ;北边显示器低位
N_H EQU 11H ;北边显示器高位
E_L EQU 12H ;东边显示器低位
E_H EQU 13H ;东边显示器高位
.CODE
ORG 00H
JMP MAIN
ORG 08H
JMP CYC
ORG 10H
;************************************
;主程序
;************************************
MAIN:
CALL INIT_IO
CALL INIT_DATA
CALL INIT_TIMER
CALL INIT_TC0
START:
CALL DATA_SHOW
CALL SCAN
JMP START
;************************************
;扫描
;************************************
SCAN:
MOV A,#04H
MOV S_CNT,A
MOV A,#11110111B
MOV S_BIT,A
CLR Y
MOV A,#0AH
MOV Z,A
SCAN_LP:
MOV A,@YZ
MOV P2,A
MOV A,S_BIT
MOV P5,A
CALL DELAY
DECMS S_CNT
JMP @F
RET
@@:
INCMS Z
NOP
B0BSET FC
RRCM S_BIT
MOV A,#0FFH
MOV P2,A
JMP SCAN_LP
;************************************
;显示
;************************************
DATA_SHOW:
MOV A,E_L
AND A,#00001111B ;取出秒的低四位元来做数据转换
CALL BCD_DISP
MOV DISP1,A ;把显示的值送到disp1
MOV A,E_H
AND A,#00001111B ;取出秒的高四位元来做数据转换
CALL BCD_DISP
MOV DISP2,A ;把显示的值送到disp2
MOV A,N_L
AND A,#00001111B ;取出秒的低四位元来做数据转换
CALL BCD_DISP
MOV DISP3,A ;把显示的值送到disp3
MOV A,N_H
AND A,#00001111B ;取出秒的高四位元来做数据转换
CALL BCD_DISP
MOV DISP4,A ;把显示的值送到disp4
RET
;************************************
;TC1中断
;************************************
MY_IRQ:
PUSH
B0BTS1 FTC1IRQ
JMP EXIT_IRQ ;检查中断
B0BCLR FTC1IRQ
MOV A,#61
MOV TC1C,A ;设定每50ms中断一次
DECMS TIMER00
JMP EXIT_IRQ
MOV A,#20
MOV TIMER00,A
//判断是否为00
CHECK00:
MOV A,#00H
CMPRS A,N_H ;yes,比较北边高位是否为00
JMP NORMAL00 ;no,减一秒
MOV A,#00H
CMPRS A,N_L
JMP CHECK42
JMP CHECK18 ;比较高位低位是否为00,用以隔开设定17s,正常计数。
CHECK18:
MOV A,#18H
CMPRS A,P1
JMP CHECK14 ;n=第一步,设定17s计数
JMP SET03 ;判断此时led显示是否为18h,y=第二步,03--00
CHECK14:
MOV A,#14H
CMPRS A,P1
JMP SET17
JMP SET20
CHECK42:
MOV A,#42H
CMPRS A,P1
JMP NORMAL00
MOV A,#04H
CMPRS A,N_L
JMP NORMAL00
JMP SET031
SET17:
MOV A,#18H
MOV P1,A
MOV A,#08
MOV N_L,A
MOV A,#01
MOV N_H,A ;北边赋值18
JMP NORMAL00
SET03:
MOV A,#14H
MOV P1,A
MOV A,#03
MOV N_L,A
MOV A,#00
MOV N_H,A ;北边赋值03
JMP NORMAL00
SET20:
MOV A,#42H
MOV P1,A
MOV A,#01
MOV N_L,A
MOV A,#02
MOV N_H,A
JMP NORMAL00
SET031:
MOV A,#22H
MOV P1,A
MOV A,#04
MOV N_L,A
MOV A,#00
MOV N_H,A ;北边赋值03
JMP NORMAL00
;*********************************
;TO中断
;*********************************
INTT0:
PUSH
B0BTS1 FT0IRQ
JMP EXIT_IRQ ;检查中断
B0BCLR FT0IRQ
MOV A,#61
MOV T0C,A ;设定每50ms中断一次
DECMS TIMER01
JMP EXIT_IRQ
MOV A,#20
MOV TIMER01,A
CHECKE00:
MOV A,#00H
CMPRS A,E_H
JMP NORMAL01
MOV A,#00H
CMPRS A,E_L
JMP NORMAL01 ;检查00,用以隔开东边计数
CHECKE18:
MOV A,#18H
CMPRS A,P1
JMP CHECKE14
JMP SETE20 ;检查led是否为18h,设定东边为20s
CHECKE14:
MOV A,#14H
CMPRS A,P1
JMP CHECKE42
JMP SETE03 ;检查led是否为14h,设定东边为03s
CHECKE42:
MOV A,#42H
CMPRS A,P1
JMP CHECKE22
JMP SETE17 ;检查led是否为14h,设定东边为17s
CHECKE22:
MOV A,#22H
CMPRS A,P1
JMP NORMAL01
JMP SETE03 ;检查led是否为22h,设定东边为03s
SETE20:
MOV A,#01
MOV E_L,A
MOV A,#02
MOV E_H,A
JMP NORMAL01
SETE03:
MOV A,#03
MOV E_L,A
MOV A,#00
MOV E_H,A
JMP NORMAL01
SETE17:
MOV A,#08
MOV E_L,A
MOV A,#01
MOV E_H,A
JMP NORMAL01
;*********************************
;北边减一秒
;*********************************
NORMAL00:
MOV A,N_L ;北边秒低位
SUB A,#01 ;减1
MOV N_L,A
MOV A,N_L
CMPRS A,#0FFH ;比较是否为FF
JMP EXIT_IRQ ;no,跳出中断
MOV A,#09 ;yes,赋值09
MOV N_L,A
MOV A,N_H ;北边秒高位
SUB A,#01 ;减1
MOV N_H,A
CMPRS A,#0FFH ;比较是否为FF
JMP EXIT_IRQ ;no,跳出中断
MOV A,#09 ;yes,赋值09
MOV N_H,A
JMP EXIT_IRQ ;跳出中断
;*********************************
;南边减一秒
;*********************************
NORMAL01:
MOV A,E_L ;东边秒低位
SUB A,#01 ;减1
MOV E_L,A
MOV A,E_L
CMPRS A,#0FFH ;比较是否为FF
JMP EXIT_IRQ ;no,跳出中断
MOV A,#09 ;yes,赋值09
MOV E_L,A
MOV A,E_H ;东边秒高位
SUB A,#01 ;减1
MOV E_H,A
CMPRS A,#0FFH ;比较是否为FF
JMP EXIT_IRQ ;no,跳出中断
MOV A,#09 ;yes,赋值09
MOV E_H,A
JMP EXIT_IRQ ;跳出中断
;*********************************
;选择中断
;*********************************
CYC:
B0BTS1 FTC1IEN
JMP @F
B0BTS0 FTC1IRQ
JMP MY_IRQ
@@:
B0BTS1 FT0IEN
JMP EXIT_IRQ
B0BTS0 FT0IRQ
JMP INTT0
RET
;*********************************
;初始化
;*********************************
INIT_IO:
MOV A,#0FFH
MOV P1M,A
MOV P2M,A
MOV P5M,A
MOV P2,A
CLR P1
RET
INIT_DATA:
CLR DLY1
CLR DLY2
CLR N_L
CLR N_H
CLR E_L
CLR E_H
RET
;初始化TC1
INIT_TIMER:
B0BCLR FTC1IEN ;关闭中断
B0BCLR FTC1ENB
MOV A,#00000100B
MOV TC1M,A ;设定tc1 clock=Fcpu/256
MOV A,#61
MOV TC1C,A ;设定每50ms中断一次
MOV A,#20
MOV TIMER00,A
B0BSET FTC1IEN
B0BCLR FTC1IRQ
B0BSET FTC1ENB
B0BSET FGIE
RET
;初始化T0
INIT_TC0:
B0BCLR FT0IEN ;关闭中断
B0BCLR FT0ENB
MOV A,#00000100B
MOV T0M,A ;设定tc1 clock=Fcpu/256
MOV A,#61
MOV T0C,A ;设定每50ms中断一次
MOV A,#20
MOV TIMER01,A
B0BSET FT0IEN
B0BCLR FT0IRQ
B0BSET FT0ENB
B0BSET FGIE
RET
EXIT_IRQ:
POP
RETI
;********************************
;查表
;********************************
BCD_DISP:
B0MOV Y,#TABLE$M
B0MOV Z,#TABLE$L
ADD A,Z
MOV Z,A
MOVC
RET
;********************************
;数据表
;********************************
TABLE:
DW 01C0H
DW 01F9H
DW 01A4H
DW 01B0H
DW 0199H
DW 0192H
DW 0182H
DW 01F8H
DW 0180H
DW 0190H
DELAY:
MOV A,#60H
MOV DLY1,A
MOV A,#04H
MOV DLY2,A
@@:
DECMS DLY1
JMP @B
DECMS DLY2
JMP @B
RET
ENDP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -