📄 mplxad.asm
字号:
;*********************************************************************
;This program is to demonstrate how to multiplex four 7 segment LED
;digits and a 4X4 keypad along with 4 A/D inputs using a PIC16C71.
;The four digits will first display the decimal a/d value of ch0.
;When keys from 0 - 3 are hit the corresponding channel's a/d value
;is displayed in decimal.
;The LEDs are updated every 20mS, the keypad is scanned at a rate of 20 mS.
;All 4 channels are scanned at 20mS rate, so each channel gets scanned
;every 80mS. A faster rate of scanning is possible as required by
;the users application.
;The RTCC timer is used in internal interrupt mode to generate the
;5 mS.
;
; Stan D'Souza 5/8/93
;
;Corrected error in display routine.
; Stan D'Souza 2/27/94
;
; Program: MPLXAD.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
PABuf equ 0x20
PBBuf equ 0x21
Count equ 0x0f ;count
MsdTime equ 0x10 ;most significant Timer
LsdTime equ 0x11 ;Least significant Timer
;
Flag equ 0x12 ;general purpose flag reg
#define keyhit Flag,0 ;bit 0 --> key-press on
#define DebnceOn Flag,1 ;bit 1 -> debounce on
#define noentry Flag,2 ;no key entry = 0
#define ServKey Flag,3 ;bit 3 --> service key
#define ADOver Flag,4 ;bit 4 --> a/d conv. over
;
Debnce equ 0x13 ;debounce counter
NewKey equ 0x14
DisplayCh equ 0x15 ;channel to be displayed
;
ADTABLE equ 0x16 ;4 locations are reserved here
;from 0x16 to 0x19
;
WBuffer equ 0x2f
StatBuffer equ 0x2e
OptionReg equ 1
PCL equ 2
;
;
push macro
movwf WBuffer ;save w reg in Buffer
swapf WBuffer, F ;swap it
swapf STATUS,W ;get status
movwf StatBuffer ;save it
endm
;
pop macro
swapf StatBuffer,W ;restore status
movwf STATUS ; /
swapf WBuffer,W ;restore W reg
endm
;
org 0
goto Start ;skip over interrupt vector
;
org 4
;It is always a good practice to save and restore the w reg,
;and the status reg during a interrupt.
push
call ServiceInterrupts
pop
retfie
;
Start
call InitPorts
call InitAd
call InitTimers
loop
btfsc ServKey ;key service pending
call ServiceKey ;yes then service
btfsc ADOver ;a/d pending?
call ServiceAD ;yes the service a/d
goto loop
;
;ServiceKey, does the software service for a keyhit. After a key service,
;the ServKey flag is reset, to denote a completed operation.
ServiceKey
bcf ServKey ;reset service flag
movf NewKey,W ;get key value
sublw 3 ;key > 3?
btfss STATUS,C ;no then skip
return ;else ignore key
movf NewKey,W
movwf DisplayCh ;load new channel
;
LoadAD
movlw ADTABLE ;get top of table
addwf DisplayCh,W ;add offset
movwf FSR ;init FSR
movf 0,W ;get a/d value
movwf L_byte
clrf H_byte
call B2_BCD
movf R2,W ;get LSd
movwf LsdTime ;save in LSD
movf R1,W ;get Msd
movwf MsdTime ;save in Msd
return
;
;This rountine essentially loads the ADRES value in the table location
;determined by the channel offset. If channel 0 then ADRES is saved
;in location ADTABLE. If channel 1 then ADRES is saved at ADTABLE + 1.
;and so on.
ServiceAD
movf ADCON0,W ;get adcon0
movwf TempC ;save in temp
movlw B'00001000' ;select next channel
addwf ADCON0,W ; /
btfsc ADCON0,5 ;if <= ch3
movlw B'11000001' ;select ch0
movwf ADCON0
;now load adres in the table
movlw ADTABLE
movwf FSR ;load FSR with top
rrf TempC, F
rrf TempC, F
rrf TempC,W ;get in w reg
andlw 3 ;mask off all but last 2
addwf FSR, F ;add offset to table
movf ADRES,W ;get a/d value
movwf 0 ;load indirectly
bcf ADOver ;clear flag
call LoadAD ;load a/d value in display reg.
return
;
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 ; /
clrf DisplayCh ;show channel 0
clrf Flag ;clr all flags
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
clrf INTCON ;else clr all int
bsf INTCON,T0IE
return
;
ServiceTMR0
movlw .96 ;initialize rtcc
movwf TMR0
bcf INTCON,T0IF ;clr int flag
btfsc PORTA,0 ;scan keys every 20 mS
call ScanKeys ;when digit 1 is on
btfsc PORTA,3 ;scan a/d every 20mS
call SampleAd ;when digit 4 is on
call UpdateDisplay ;update display
return
;
;
;ScanKeys, scans the 4X4 keypad matrix and returns a key value in
;NewKey (0 - F) if a key is pressed, if not it clears the keyhit flag.
;Debounce for a given keyhit is also taken care of.
;The rate of key scan is 20mS with a 4.096Mhz clock.
ScanKeys
btfss DebnceOn ;debounce on?
goto Scan1 ;no then scan keypad
decfsz Debnce, F ;else dec debounce time
return ;not over then return
bcf DebnceOn ;over, clr debounce flag
return ;and return
Scan1
call SavePorts ;save port values
movlw B'11101111' ;init TempD
movwf TempD
ScanNext
movf PORTB,W ;read to init port
bcf INTCON,RBIF ;clr flag
rrf TempD, F ;get correct column
btfss STATUS,C ;if carry set?
goto NoKey ;no then end
movf TempD,W ;else output
movwf PORTB ;low column scan line
nop
btfss INTCON,RBIF ;flag set?
goto ScanNext ;no then next
btfsc keyhit ;last key released?
goto SKreturn ;no then exit
bsf keyhit ;set new key hit
swapf PORTB,W ;read port
movwf TempE ;save in TempE
call GetKeyValue ;get key value 0 - F
movwf NewKey ;save as New key
bsf ServKey ;set service flag
bsf DebnceOn ;set flag
movlw 4
movwf Debnce ;load debounce time
SKreturn
call RestorePorts ;restore ports
return
;
NoKey
bcf keyhit ;clr flag
goto SKreturn
;
;GetKeyValue gets the key as per the following layout
;
; Col1 Col2 Col3 Col3
; (RB3) (RB2) (RB1) (RB0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -