📄 mplx.asm
字号:
;*********************************************************************
;This program is to demonstrate how to multiplex four 7 segment LED
;digits using a PIC16C71. The four digits will start at 0000 and
;increment at a 1 sec rate up to 9999.
;The LEDs are updated every 5 mS, for a multiplexing rate of 20 mS.
;The TMR0 timer is used in internal interrupt mode to generate the
;5 mS.
;
; Stan D'Souza 5/8/93
;
; Program: MPLX.ASM
; Revision Date:
; 1-15-97 Compatibility with MPASMWIN 1.40
;
;**********************************************************************
LIST P=16C71
ERRORLEVEL -302
;
include <p16c71.inc>
;
TempC equ 0x0c ;temp general purpose regs
TempD equ 0x0d
TempE equ 0x0e
Count equ 0x0f ;count
MsdTime equ 0x10 ;most significant Timer
LsdTime equ 0x11 ;Least significant Timer
OptionReg equ 1
PCL equ 2
BcdMsd equ 26
Bcd equ 27
;
org 0
goto Start ;skip over interrupt vector
;
org 4
goto ServiceInterrupts
;
Start
call InitPorts
call InitTimers
loop
goto loop
;
InitPorts
bsf STATUS,RP0 ;select pg 1
movlw 3 ;make RA0-3 digital I/O
movwf ADCON1 ; /
clrf TRISA ;make RA0-4 outputs
clrf TRISB ;make RB0-7 outputs
bcf STATUS,RP0 ;select page 0
clrf PORTA ;make all outputs low
clrf PORTB ; /
bsf PORTA,3 ;enable MSB digit sink
return
;
;
;The clock speed is 4.096Mhz. Dividing internal clk. by a 32 prescaler,
;the rtcc will be incremented every 31.25uS. If rtcc is preloaded
;with 96, it will take (256-96)*31.25uS to overflow i.e. 5mS. So the
;end result is that we get a rtcc interrupt every 5mS.
InitTimers
clrf MsdTime ;clr timers
clrf LsdTime ; /
bsf STATUS,RP0 ;select pg 1
movlw B'10000100' ;assign ps to rtcc
movwf OptionReg ;ps = 32
bcf STATUS,RP0 ;select pg 0
movlw B'00100000' ;enable rtcc interrupt
movwf INTCON ;
movlw .96 ;preload rtcc
movwf TMR0 ;start counter
retfie
;
ServiceInterrupts
btfsc INTCON,T0IF ;rtcc interrupt?
goto ServiceTMR0 ;yes then service
movlw B'00100000' ;else clr rest
movwf INTCON
retfie
;
ServiceTMR0
movlw .96 ;initialize rtcc
movwf TMR0
bcf INTCON,T0IF ;clr int flag
call IncTimer ;inc timer
call UpdateDisplay ;update display
retfie
;
;The display is incremented every 200*5mS = 1 Sec.
IncTimer
incf Count,W ;inc count
xorlw .200 ;= 200?
btfsc STATUS,Z ;no then skip
goto DoIncTime ;else inc time
incf Count, F
return
DoIncTime
clrf Count ;clr count
incf LsdTime,W ;get lsd
andlw 0x0F ;mask high nibble
xorlw 0x0a ; = 10?
btfsc STATUS,Z ;no then skip
goto IncSecondLsd ;inc next lsd
incf LsdTime, F ;else inc timer
return
IncSecondLsd
swapf LsdTime,W ;get hi in low nibble
andlw 0x0F ;mask hi nibble
addlw 1 ;inc it
movwf LsdTime ;restore back
swapf LsdTime, F ; /
xorlw 0x0a ; = 10?
btfsc STATUS,Z ;no then skip
goto IncThirdLsd ;else inc next lsd
return
IncThirdLsd
clrf LsdTime
incf MsdTime,W ;get 3rd lsd
andlw 0x0F ;mask hi nibble
xorlw 0x0a ;= 10?
btfsc STATUS,Z ;no then skip
goto IncMsd ;else Msd
incf MsdTime, F ;else inc timer
return
IncMsd
swapf MsdTime,W ;get hi in lo nibble
andlw 0x0F ;mask hi nibble
addlw 1 ;inc timer
movwf MsdTime ;restore back
swapf MsdTime, F ; /
xorlw 0x0a ;= 10?
btfsc STATUS,Z ;no then skip
clrf MsdTime ;clr msd
return
;
;
UpdateDisplay
movf PORTA,W ;present sink value in w
clrf PORTA ;disable all digits sinks
andlw 0x0f
movwf TempC ;save sink value in tempC
bsf TempC,4 ;preset for lsd sink
rrf TempC, F ;determine next sink value
btfss STATUS,C ;c=1?
bcf TempC,3 ;no then reset LSD sink
btfsc TempC,0 ;else see if Msd
goto UpdateMsd ;yes then do Msd
btfsc TempC,1 ;see if 3rdLsd
goto Update3rdLsd ;yes then do 3rd Lsd
btfsc TempC,2 ;see if 2nd Lsd
goto Update2ndLsd ;yes then do 2nd lsd
UpdateLsd
movf LsdTime,W ;get Lsd in w
andlw 0x0f ; /
goto DisplayOut ;enable display
Update2ndLsd
call Chk2LsdZero ;msd = 0 & 2 lsd 0?
btfss STATUS,Z ;yes then skip
swapf LsdTime,W ;get 2nd Lsd in w
andlw 0x0f ;mask rest
goto DisplayOut ;enable display
Update3rdLsd
call ChkMsdZero ;msd = 0?
btfss STATUS,Z ;yes then skip
movf MsdTime,W ;get 3rd Lsd in w
andlw 0x0f ;mask low nibble
goto DisplayOut ;enable display
UpdateMsd
swapf MsdTime,W ;get Msd in w
andlw 0x0f ;mask rest
btfsc STATUS,Z ;msd != 0 then skip
movlw 0x0a
DisplayOut
call LedTable ;get digit output
movwf PORTB ;drive leds
movf TempC,W ;get sink value in w
movwf PORTA
return
;
;
LedTable
addwf PCL, F ;add to PC low
retlw B'00111111' ;led drive for 0
retlw B'00000110' ;led drive for 1
retlw B'01011011' ;led drive for 2
retlw B'01001111' ;led drive for 3
retlw B'01100110' ;led drive for 4
retlw B'01101101' ;led drive for 5
retlw B'01111101' ;led drive for 6
retlw B'00000111' ;led drive for 7
retlw B'01111111' ;led drive for 8
retlw B'01100111' ;led drive for 9
retlw B'00000000' ;blank led drive
;
;
Chk2LsdZero
call ChkMsdZero ;msd = 0?
btfss STATUS,Z ;yes then skip
return ;else return
swapf LsdTime,W ;get 2nd lsd
andlw 0x0f ;mask of LSD
btfss STATUS,Z ;0? then skip
return
retlw .10 ;else return with 10
;
ChkMsdZero
movf MsdTime,W ;get Msd in w
btfss STATUS,Z ;= 0? skip
return ;else return
retlw .10 ;ret with 10
;
end
;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -