导航: 老古网老古论坛XMOS公共讨论区XMOS开源项目区单片机程序设计嵌入式系统广告区域
→第一次搞PIC,帮忙看看这段键盘程序[cq2000]

 *第34141篇: 第一次搞PIC,帮忙看看这段键盘程序

  
楼 主:cq2000 2005年9月5日22:09
 第一次搞PIC,帮忙看看这段键盘程序
为看得明白指令,把指令注释都加上了
这段程序的键盘扫描看不懂,好像有定时中断又有PORTB电平变化中断

;*********************** 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



>>>>>>对该主题发表你的看法

本主题贴数1,分页: [第1页]


[上一篇主题]:s3c44b0x01 和 s3c44b0x01-EDRO的区别?[求助]

[下一篇主题]:电子竞赛群欢迎加入