📄 elmp.asm
字号:
; ELMP PIC code *bugfixed version*
; cyrano@algonet.se
; This code will scan a 4x4 keypad and transmit "scan-codes" when a key is
; pressed or released (at 9600bps, 8N1). It will also handle the power relay
; when standby mode is used, and hopefully some day it will handle RC5 code
; for IR remote controls...
;
; No voltage converter (such as MAX232) is needed, a "1" is sent as 0v and
; a "0" is sent as 5v, this will be accepted by most modern motherboards..
; 9600bps serial send code: done!
; Keypad scanning code: done! and fixed :-)
; Standby handling code: not done
; IR remote code: not done
PROCESSOR 16C84
; pins...
#define serdatapin PORTA,3
#define IRdatapin PORTA,4
#define relaypin PORTA,2
#define trisb_keyrow1 H'EF'
#define trisb_keyrow2 H'DF'
#define trisb_keyrow3 H'BF'
#define trisb_keyrow4 H'7F'
#define keycol1 PORTB,0
#define keycol2 PORTB,1
#define keycol3 PORTB,2
#define keycol4 PORTB,3
; Standard Register Files...
TMR0 equ H'01'
PCL equ H'02'
STATUS equ H'03'
FSR equ H'04'
PORTA equ H'05'
PORTB equ H'06'
EEDATA equ H'08'
EEADR equ H'09'
PCLATH equ H'0A'
INTCON equ H'0B'
OPTION_ equ H'81'
TRISA equ H'85'
TRISB equ H'86'
EECON1 equ H'88'
EECON2 equ H'89'
; User defined variables...
W_TEMP equ H'0C'
S_TEMP equ H'0D'
BITCNT equ H'0E'
SERBYTE equ H'0F'
COUNT equ H'10'
KEYS1 equ H'11'
KEYS2 equ H'12'
TMPKEY equ H'13'
TEMP equ H'14'
TEMP2 equ H'15'
; Macros....
#define bank0 bcf STATUS,5 ;select bank 0 (clear bit 5 of STATUS reg.)
#define bank1 bsf STATUS,5 ;select bank 1 (set bit 5 of STATUS reg.)
; Code starts here ---------------------------------------------------
ORG 0 ; Main program start vector
GOTO start ; Jump to the code!
; ISR (Interrupt Service Routine)
ORG 4
MOVWF W_TEMP ; Save working reg. (W)
SWAPF STATUS, W ; Copy STATUS reg to W and swap nibbles
MOVWF S_TEMP ; Save STATUS register
bank0
MOVLW H'A0' ; load a "magic number" into TMR0
MOVWF TMR0
; BTFSC serdatapin ; this simple test code will generate
; GOTO clearit ; infinite "010101...". Good for testing
;setit BSF serdatapin ; If all settings are correct, this should
; GOTO done ; be recieved as a bunch of "U" at the PC.
;clearit BCF serdatapin ; If you get some "U" and some other chars,
;done ; baudrate is slightly off, adjust "magic"
; comment the code below if you uncomment the test code
MOVF BITCNT,W
BTFSC STATUS,2 ; test zero flag
GOTO done ; just skip ahead
SUBLW 1 ; is it time for the start bit (bit 0x01)?
BTFSC STATUS,2 ; let's find out!
GOTO strtbit
MOVF BITCNT,W
SUBLW H'A' ; is it time for the stop bit (bit 0x0A)?
BTFSC STATUS,2 ; let's find out!
GOTO stopbit
INCF BITCNT
RRF SERBYTE,F ; it's data byte time!
BTFSC STATUS,0 ; our data bit is now in the carry
GOTO clearit
GOTO setit
strtbit INCF BITCNT ; start bit done, next time data!
setit BSF serdatapin ; output 5v (RS-232 "0")
GOTO done
stopbit CLRF BITCNT ; we're ready for another byte
clearit BCF serdatapin ; output 0v (RS-232 "1")
done
; end comment
BCF INTCON,2 ; clear (timer) interrupt flag
SWAPF S_TEMP, W ; Swap saved STATUS back into W
MOVWF STATUS ; Put it back in STATUS reg.
SWAPF W_TEMP, F ; Swap nibbles of W_TEMP
SWAPF W_TEMP, W ; Again, this time placing the result in W
RETFIE ; Return from ISR
; XMIT
; Put a byte into W and call this to transmit it, check that BITCNT is 0 first
xmit MOVWF SERBYTE ; put the byte in the "buffer"
CLRF BITCNT
INCF BITCNT ; set BITCNT = 1 (start transmit!)
RETURN
start CLRF BITCNT ; don't send anything just yet...
bank1
CLRF TRISB^80H ; Make PORTB all outputs
DECF TRISB^80H ; Make PORTB all inputs
BCF serdatapin ; set serial data pin to output
BSF IRdatapin ; set IR remote pin to input
BCF relaypin ; power relay control pin = output!
bank0
MOVLW H'FF'
MOVWF PORTB ; Make PORTB all ones
BSF serdatapin ; idle state
BCF relaypin ; set it low to turn on the relay
bank1
MOVLW B'10001000'
MOVWF OPTION_^80H ; timer 0 internal clock 1:1, pullup disabled
bank0
BSF INTCON,5 ; enable timer interrupt
BSF INTCON,7 ; globally allow interrupts
CLRF KEYS1 ; All 16 keys released to start with
CLRF KEYS2
; Below comes some pretty ugly code, but it does work so I leave it alone :-)
loop
CLRF TMPKEY
CLRF TEMP
bank1
MOVLW trisb_keyrow1
MOVWF TRISB^80H ; row 1 of keypad active
bank0
BTFSC keycol1 ; check key (1,1)
BSF TMPKEY,0
BTFSC keycol2 ; check key (2,1)
BSF TMPKEY,1
BTFSC keycol3 ; etc...
BSF TMPKEY,2
BTFSC keycol4
BSF TMPKEY,3
bank1
MOVLW trisb_keyrow2
MOVWF TRISB^80H ; row 2 of keypad active
bank0
BTFSC keycol1 ; check key (1,2)
BSF TMPKEY,4
BTFSC keycol2 ; check key (2,2)
BSF TMPKEY,5
BTFSC keycol3 ; etc...
BSF TMPKEY,6
BTFSC keycol4
BSF TMPKEY,7
MOVF TMPKEY,W ; save the keys, so we can update KEYS1
MOVWF TEMP2
MOVF KEYS1,W
XORWF TMPKEY,F
BTFSC STATUS,2
GOTO same1 ; zero flag set = no change on first 8 keys
keylp1 RRF TMPKEY,F
BTFSS STATUS,0
GOTO skip1
RRF KEYS1,F
BTFSC STATUS,0
GOTO clear1
BSF STATUS,0
BSF TEMP,4
GOTO invdne1
clear1 BCF STATUS,0
invdne1 RLF KEYS1,F
wait1 MOVF BITCNT,W
BTFSS STATUS,2
GOTO wait1
MOVF TEMP,W
CALL xmit
BCF TEMP,4
skip1 RRF KEYS1,F
INCF TEMP
MOVLW 8
SUBWF TEMP,W
BTFSS STATUS,2
GOTO keylp1
MOVF TEMP2,W
MOVWF KEYS1
same1
MOVLW H'08'
MOVWF TEMP
CLRF TMPKEY
bank1
MOVLW trisb_keyrow3
MOVWF TRISB^80H ; row 3 of keypad active
bank0
BTFSC keycol1 ; check key (1,3)
BSF TMPKEY,0
BTFSC keycol2 ; check key (2,3)
BSF TMPKEY,1
BTFSC keycol3 ; etc...
BSF TMPKEY,2
BTFSC keycol4
BSF TMPKEY,3
bank1
MOVLW trisb_keyrow4
MOVWF TRISB^80H ; row 4 of keypad active
bank0
BTFSC keycol1 ; check key (1,4)
BSF TMPKEY,4
BTFSC keycol2 ; check key (2,4)
BSF TMPKEY,5
BTFSC keycol3 ; etc...
BSF TMPKEY,6
BTFSC keycol4
BSF TMPKEY,7
MOVF TMPKEY,W
MOVWF TEMP2
MOVF KEYS2,W
XORWF TMPKEY,F
BTFSC STATUS,2
GOTO same2
keylp2 RRF TMPKEY,F
BTFSS STATUS,0
GOTO skip2
RRF KEYS2,F
BTFSC STATUS,0
GOTO clear2
BSF STATUS,0
BSF TEMP,4
GOTO invdne2
clear2 BCF STATUS,0
invdne2 RLF KEYS2,F
wait2 MOVF BITCNT,W
BTFSS STATUS,2
GOTO wait2
MOVF TEMP,W
CALL xmit
BCF TEMP,4
skip2 RRF KEYS2,F
INCF TEMP
MOVLW 16
SUBWF TEMP,W
BTFSS STATUS,2
GOTO keylp2
MOVF TEMP2,W
MOVWF KEYS2
same2
goto loop
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -