;*********************** MJ_KEYSCAN.ASM ***************************
; f=4.00000MHZ Date:2005-08-30
; ID==050830 Checksum=xxxx
; TMR0 USED
;****************************************************************
LIST P=16f628A
INCLUDE "P16f628A.INC"
;-------------------------------------
;DEFINE PORTA.0 C011
;DEFINE PORTA.1 C012
;DEFINE PORTA.2 C013
;DEFINE PORTA.3 C014
;DEFINE PORTB.4 ROW1
;DEFINE PORTB.5 ROW2
;DEFINE PORTB.6 ROW3
;DEFINE PORTB.7 ROW4
;-------------------------------------
#define FOSC D'4000000' ;INTER CLOCK
;--------------------------------
OPTIONREG EQU 01H ;
PCL EQU 02H ;
TEMPC EQU 20H
TEMPD EQU 21H
TEMPE EQU 22H
PABUF EQU 23H
PBBUF EQU 24H
COUNT EQU 25H
MSDTIME EQU 26H
LSDTIME EQU 27H
KEYFLAG EQU 28H ;
DEBNCE EQU 29H
NEWKEY EQU 2AH ;
WBUFFER EQU 2BH ;
STATBUFFER EQU 2CH ;
;******************************************
;KEYFLAG EQU 28H ;
KEYHIT EQU 0 ;
DEBNCEON EQU 1 ;
NOENTRY EQU 2 ;
SERVKEY EQU 3 ;
;******************************************
PUSH MACRO
MOVWF WBUFFER ;将W 内容送至WBUFFER
SWAPF WBUFFER ;WBUFFER寄存器的高半字节和低半字节相互交换。
SWAPF STATUS,W
MOVWF STATBUFFER
ENDM
;
POP MACRO
SWAPF STATBUFFER,W
MOVWF STATUS
SWAPF WBUFFER,W
ENDM
;*************************************
ORG 0
GOTO START
;-------------------------------------
ORG 4
;****************************************
PICINT
PUSH
CALL SERVICEINTERRUPTS
POP
RETFIE
;***************************************************************************************************************
START ;主程序
CALL INITPORTS ;端口初始化
CALL INITTIMERS ;中断初始化
LOOP
BTFSC KEYFLAG,SERVKEY ;KEYFLAG.SERVKEY=0则跳过下一条指令。KEYFLAG.SERVKEY=1--有键
CALL SERVICEKEY ;调键盘服务
GOTO LOOP
;***************************************************************************************************************
SERVICEKEY ;键盘服务
MOVF NEWKEY,W ;将NEWKEY单元(2AH)键值内容传送到TEMPE单元(22H)
MOVWF TEMPE
SWAPF MSDTIME,W ;MSDTIME(26H)[MD7,MD6,MD5,MD4,MD3,MD2,MD1,MD0]--> MSDTIME[MD3,MD2,MD1,MD0,0,0,0,0]
ANDLW B'11110000'
MOVWF MSDTIME
SWAPF LSDTIME,W ;LSDTIME(27H)[LD7,LD6,LD5,LD4,LD3,LD2,LD1,LD0]--> W[0,0,0,0,LD7,LD6,LD5,LD4]
ANDLW B'00001111'
IORWF MSDTIME ;MSDTIME OR W--> MSDTIME[MD3,MD2,MD1,MD0,LD7,LD6,LD5,LD4]
SWAPF LSDTIME,W ;LSDTIME(27H)[[LD7,LD6,LD5,LD4,LD3,LD2,LD1,LD0]--> W[LD3,LD2,LD1,LD0,0,0,0,0]
ANDLW B'11110000'
IORWF TEMPE,W ;TEMPE(22H) OR W[LD3,LD2,LD1,LD0,0,0,0,0]--> LSDTIME
MOVWF LSDTIME
BCF KEYFLAG,SERVKEY ;KEYFLAG.SERVKEY=0
RETURN
;*************************************************************************************************************************
INITPORTS
CLRF PORTA ;立即数00000000----> PORTA锁存器
MOVLW 0X0E ;立即数00001110----> PORTB锁存器
MOVWF PORTB
BSF STATUS,RP0 ;STATUS状态寄存器RP0位置1(选择存储体BANK1)
MOVLW 0XF0 ;立即数11110000送TRISA,设置RA端口高四位输入,低四位输出
MOVWF TRISA
MOVLW 0XF1 ;立即数11110001送TRISB,设置RB端口高四位输入和最低位输入,RB1RB2RB3输出
MOVWF TRISB
BCF STATUS,RP0 ;STATUS状态寄存器RP0位置0(选择存储体BANK0)
RETURN
;-----------------------------------------
INITTIMERS ;允许RB口电平变化中断,允许TMR2对PR2匹配中断
CLRF MSDTIME
CLRF LSDTIME
CLRF KEYFLAG
;
MOVLW 0X07 ;关闭比较器的功能,RA端口设为数字口
MOVWF CMCON
;
BANKSEL PIE1 ;T2 20MS ;BANK存储块选择1
BSF PIE1,TMR2IE ; ;允许TMR2对PR2匹配中断
MOVLW 0X4E ; ;PR2寄存器赋值
MOVWF PR2 ;
MOVLW B'10000100' ;立即数10000100送OPTION_REG 寄存器(RBPU INTEDG T0CS T0SE PSA PS2 PS1 PS0)
MOVWF OPTIONREG ;RBPU=1---(PORTB 弱上拉使能位)禁止PORTB 弱上拉
;INTEDG=0---(中断触发边沿选择位)RB0/INT 引脚下降沿触发中断
;T0CS=0---(TMR0 时钟源选择位)内部指令周期时钟(CLKOUT)
;T0SE=0---(TMR0 计数脉冲边沿选择位)在RA4/T0CKI 引脚上的上升沿递增1
;PSA=0---(预分频器分配位)预分频器分配给Timer0 模块(=1 预分频器分配给WDT)
;PS2 PS1 PS0=100---(预分频器分频比选择位)TMR0 分频比1:32,WDT分频比1:16
BANKSEL PORTA ; ;BANK存储块选择0
MOVLW 0X7F ;立即数01111111送T2CON寄存器(— TOUTPS3 TOUTPS2 TOUTPS1 TOUTPS0 TMR2ON T2CKPS1 T2CKPS0)
MOVWF T2CON ;TOUTPS3 TOUTPS2 TOUTPS1 TOUTPS0(Timer2 输出后分频比选择位)=1111(1:16 后分频比)
;TMR2ON(Timer2 使能位)=1,使能
;T2CKPS1:T2CKPS0(Timer2时钟预分频比选择位)=11(预分频比为16)
MOVLW B'01001000' ;立即数01001000送中断控制寄存器INTCON(GIE PEIE T0IE INTE RBIE T0IF INTF RBIF)
MOVWF INTCON ;GIE=0---(全局中断使能位)禁止所有中断????????
;PEIE=1---(外设中断使能位)开放所有未被屏蔽的外设中断
;T0IE=0---(TMR0 溢出中断使能位)禁止TMR0 中断
;INTE=0---(RB0/INT 外部中断使能位)禁止RB0/INT 外部中断
;RBIE=1---(RB 口电平变化中断使能位)允许 RB 口电平变化中断
;T0IF=0---(计数器溢出标志软件清0)TMR0 计数器没有溢出
;INTF=0---(外部中断标志位)RB0/INT 引脚上没有外部中断发生
;RBIF=0---(RB 口电平变化中断标志位)RB7:RB4 引脚状态无变化
RETURN
;------------------------------------------
SERVICEINTERRUPTS
BTFSS PIR1,TMR2IF ;PIR1.TMR2IF=1则跳过下一条指令(RB口电平变化中断则返回,TIMER2定时中断则扫描键盘)
RETURN ;PIR1寄存器(包含各个外设的中断标志位。)
;TMR2IF---TMR2和PR2匹配中断标志位
;
NOP
BCF PIR1,TMR2IF ;如果TMR2和PR2匹配中断发生,清中断标志位
CALL SCANKEYS ;调键扫描
RETURN
;------------------------------------------
SCANKEYS
BTFSS KEYFLAG,DEBNCEON ;KEYFLAG.DEBNCEON=1则跳过下一条指令
GOTO SCAN1
DECFSZ DEBNCE ;DEBNCE-1----> DEBNCE=0则跳过下一条指令
RETURN
BCF KEYFLAG,DEBNCEON ;清KEYGLAG的DEBNCEON位
RETURN
;------------------------------------------
SCAN1
CALL SAVEPORTS
MOVLW B'11101111' ;立即数11101111----> TEMPD(21H)
MOVWF TEMPD
SCANNEXT
MOVF PORTB,W ;PORTB锁存器送W
BCF INTCON,RBIF ;清除RB口电平变化中断标志位
RRF TEMPD ;TEMPD单元带进位位右移
BTFSS STATUS,C ;STATUS.C标志为1则跳过下一条指令(顺序)
GOTO NOKEY
MOVF TEMPD,W ;TEMPD----> PORTB锁存器
MOVWF PORTB
NOP
BTFSS INTCON,RBIF ;判断RB口电平变化中断标志位,为1则跳过下一条指令(RB端口电平变化,不中断标志位也变化)
GOTO SCANNEXT
BTFSC KEYFLAG,KEYHIT ;KEYFLAG.KEYHIT=0则跳过下一条指令
GOTO SKRETURN
BSF KEYFLAG,KEYHIT ;KEYFLAG.KEYHIT位=1
SWAPF PORTB,W ;PORTB高4位,低4位互换送TEMPE(22H)
MOVWF TEMPE
CALL GETKEYvalue ;获取键值(在W中)
MOVWF NEWKEY ;W-----> NEWKEY(2AH)
BSF KEYFLAG,SERVKEY ;KEYFLAG.SERVKEY=1
BSF KEYFLAG,DEBNCEON ;KEYFLAG.DEBNCEON=1
MOVLW 4 ;4-----> DEBNCE(防抖计数器)
MOVWF DEBNCE
SKRETURN
CALL RESTOREPORTS
RETURN
NOKEY
BCF KEYFLAG,KEYHIT ;KEYFLAG.KEYHIT=0
GOTO SKRETURN
;------------------------------------------
GETKEYvalue
CLRF TEMPC ;TEMPC(20H)=0
BTFSS TEMPD,3 ;TEMPD.3=1则跳过下一条指令
GOTO ROWVALEND
INCF TEMPC ;TEMPC=TEMPC+1
BTFSS TEMPD,2 ;TEMPD.2=1则跳过下一条指令
GOTO ROWVALEND
INCF TEMPC ;TEMPC=TEMPC+1
BTFSS TEMPD,1 ;TEMPD.1=1则跳过下一条指令
GOTO ROWVALEND
INCF TEMPC ;TEMPC=TEMPC+1
ROWVALEND
BTFSS TEMPE,0 ;TEMPE.0=1则跳过下一条指令
GOTO GETVALCOM
BTFSS TEMPE,1 ;TEMPE.1=1则跳过下一条指令
GOTO GET4567
BTFSS TEMPE,2 ;TEMPE.2=1则跳过下一条指令
GOTO GET89AB
GETCDEF
BSF TEMPC,2 ;TEMPC.2=1
GET89AB
BSF TEMPE,3 ;TEMPE.3=1
GOTO GETVALCOM
GET4567
BSF TEMPC,2 ;TEMPC.2=1
GETVALCOM
MOVF TEMPC,W ;TEMPC----> W
ADDWF PCL ;W+PCL----> PCL;W+程序指针寄存器-----> 程序指针寄存器
RETLW 0
RETLW 1
RETLW 2
RETLW 3
RETLW 4
RETLW 5
RETLW 6
RETLW 7
RETLW 8
RETLW 9
RETLW 0A
RETLW 0B
RETLW 0C
RETLW 0D
RETLW 0E
RETLW 0F
;----------------------------------------
SAVEPORTS
; MOVF PORTA,W
; MOVWF PABUF
; CLRF PORTA
MOVF PORTB,W ;PORTB锁存器----> PBBUF(24H)
MOVWF PBBUF
MOVLW 0XFF ;11111111-----> PORTB锁存器
MOVWF PORTB
BSF STATUS,RP0 ;STATUS.RP0=1,选择BANK1
BCF OPTIONREG,7 ;OPTIONREG.7=0(PORTB 弱上拉由备用功能或TRISBn 位的值确定)
MOVLW B'11110000' ;11110000-----> TRISB,端口B高4位输入,低四位输出
MOVWF TRISB
BCF STATUS,RP0 ;STATUS.RP0=0,选择BANK0
RETURN
;-----------------------------------------
RESTOREPORTS
MOVF PBBUF,W ;PBBUF----> TRISB
MOVWF TRISB
MOVF PABUF,W ;PABUF----> PORTA
MOVWF PORTA
BSF STATUS,RP0 ;STATUS.RP0=1,选择BANK1
BSF OPTIONREG,7 ;OPTIONREG.7=1禁止PORTB 弱上拉
CLRF TRISA ;TRISA=0,PORTA引脚配置为输出(输出锁存器的内容输出到选定引脚)
;读PORTA寄存器即读相应引脚的状态,而写PORTA寄存器即写到端口锁存器。
CLRF TRISB ;TRISB=0,PORTB引脚配置为输出(输出锁存器的内容输出到选定引脚)
BCF STATUS,RP0 ;STATUS.RP0=0,选择BANK0
RETURN
;*****************************************
END