LIST P=16C71
TEMPC EQU0CH;定義通用寄存器
TEMPD EQU0DH
TEMPE EQU0EH
PABUF EQU20H
PBBUF EQU21H
COUNT EQU0FH;計數寄存器
MSDTIME EQU10H;高2位顯示數寄存器
LSDTIME EQU11H;低2位顯示數寄存器
;
FLAG EQU12H;定義FLAG寄存器位
KEYHIT EQU0
DEBNCEON EQU1
NOENTER EQU2
SERVKEY EQU3
ADOVER EQU4;A/D轉換溢出標志位
;
DEBNCE EQU13H;去抖動計數器
EQU14H
EQU15H;放通道數
EQU16H;4通道A/D結果地址(16H-19H);
H-BYTE EQU20H;二進制結果高位寄存器
L-BYTE EQU21H;二進制結果低位寄存器
R0EQU22H;最高位BCD數寄存器
R1EQU23H
R2EQU24H;最低位BCD數寄存器
COUNT EQU26H
TEMP EQU27H
WBUFFER EQU2FH;W緩沖寄存器
SBUFFER EQU2EH;STATUS緩沖寄器
PCL EQU2
;
INCLUDE"P16CXX,EQU"
;
ORG0
GOTO START
;
ORG4;中斷向量
MOVWF WBUFFER;將W內容存入緩沖器(保護現場)
SWAPF WBUFFER
SWAPF STATUS,W
MOVWF SBUFFER;將STATUS內容存入緩沖器
CALL SERV-INT;進行中斷處理
SWAPF SBUFFER,W
MOVWF STATUS;恢復STATUS(恢復現場)
SWAPF WBUFFER,W;恢復W內容
RETFIE
;
START;主程序開始
CALL INPORTS;I/O口初始化
CALL INAD;A/D初始化
CALL INTIMERS;定時器初始化
LOOP BTFSC FLAG,;要進行鍵處理否?
CALL SERVICEKEY;是,進行鍵處理
BTFSC FLAG,ADOVER;A/D轉換完否?
CALL SERVICEAD;是,進行A/D數據處理
GOTO LOOP;否,循環等待
;
SERVICEKEY;鍵處理子程序
BCF FLAG,;清按鍵標志
MOVF NEWKEY,W;取鍵值
SUBLW3;判健值>3否?
BTFSS STATUS,C;小於3則跳轉
RETURN;大於3返回
MOVF NEWKEY,W
MOVWF DISPCH;更新通道
LOAD
MOVLW ADTABLE;取A/D結果數據表的首地址
ADDWF NEWKEY,W;加偏移量
MOVWF FSR;存入FSR寄存器
MOVF INDF,W;取A/D值
MOVWF L-BYTE
CLRF H-BYTE
CALL B2-BCD
MOVF R2,W取低兩位顯示值
MOVWF LSDTIME;存入低2位顯示數寄存器
MOVF R1,W取高兩位顯示值
MOVWF MSDTIME;存入高2位顯示數寄存器
RETURN
;
SERVICEAD
;存A/D結果(0通道->ADTABLE,1通道->工ADTABLE+1,…)
MOVF ADCON0,W;讀ADCON0
MOVWF TEMPC;存入TEMPC
MOVLW B'00001000';選下一個通道
ADDWF ADCON0,W
BTFSC ADCON0,5;通道數<=3否?
MOVLW B'11000000';否,重選0通道
MOVWF ADCON0
MOVLW ADTABLE
MOVWF FSR;A/D結果數據表首址-->FSR
RRF TEMPC
RRF TEMPC
RRF TEMPC,W;通道數-->W
ANDLW3;屏蔽高6位
ADDWF FSR;加偏移量至數據表
MOVF ADRES,W;取A/D結果
MOVWF INDF;存入FSR指定的寄存器
BCF FLAG,ADOVER;清A/D溢出標志
CALL LOAD RETURN ;
INPORTS
;I/O 口初始化BSF STATUS,RP0;選寄存器區1MOVLW 3MOVWF ADCON1;設置RA <0~3>為數字 I /O 口CLRF TRISA ;設置RA <0~4>為輸出CLRF TRISB ;設置RB <0~7>為輸出BCF STATUS,RP0;選寄存器區0CLRF RA CLRF RB ;置所有輸出口為低□電平BSF RA,3;使能最高顯示數字位RETURN ;
CLRF MSDTIME ;清高位寄存器CLRF LSDTIME ;清低位寄存器CLRF DISPCH ;選通道0CLRF FLAG ;清標志BSF STATUS,RP0;選寄存器區1MOVLW B'0000100'MOVWF OPTION_R ;設RTCC 分頻比為1:32BCF STATUS,RP0;選寄存器區0MOVLW B'00100000';允許RTCC 中斷MOVWF INTCON MOVLW .96;設RTCC 初值MOVWF RTCC ;開始計時RETFIE ;
SERV_INT
BTFSC INTCON,RTIF ;是RTCC 中斷否?GOTO SERVRTCC ;是,進行中斷處理CLRF INTCON ;清中斷寄存器BSF INTCON,RTIF RETURN ;
SERVRTCC
MOVLW .96MOVWF RTCC ;設RTCC 初值BCF INTCON,RTIF ;清中斷標志BTFSC RA,0CALL SCANKEYS ;掃描鍵盤BTFSC RA,3CALL SAMPLEAD CALL DISPLAY ;進行數據顯示RETURN ;
BTFSS FLAG,DEBNCEO N ;清抖動否?
GOTO SCAN1;否,轉SCAN1
INTIMERS ;
內部振蕩,RTCC 預分頻比1:32,RTCC 每5ms 中斷一次SCANKEYS ;4*4鍵盤矩陣掃描,鍵值(0~F)-->NEWKEY,掃描速率
DECFSZ DEBNCE;DEBNCE內容減1 RETURN
BSF FLAG,DEBNCEO
N ;清DEBNCEON位
RETURN
SCAN1CALL SAVEPORTS;存I/O口值
MOVLW B'11101111'
MOVWF TEMPD
SCANNEXT MOVF RB,W;讀RB口值
BCF INTCON,RBIF;清RB口中斷標志位
RRF TEMPD;TEMPD內容右移
BTFSS STATUS,C;是否有進位位?
GOTO NOKEY;無,轉NOKEY
MOVF TEMPD,W;有,讀輸出數
MOVWF RB;送RB口輸出
NOP
BTFSS INTCON,RBIF;RB口電平變化否?
GOTO SCANNEXT;無,轉SCANNEXT
BTFSC FLAG,KEYHIT;有,鍵釋放否?
GOTO SKRETURN;沒有,轉SKRETURN
BSF FLAG,KEYHIT;是,設釋放標志位
SWAPF RB,W;取RB口數
MOVWF TEMPE;存入TEMPE寄存器
CALL KEYVALUE;取健值
MOVWF NEWKEY;鍵值存入NEWKEY寄存器
BSF FLAG,SERVKEY
BSF FLAG,DEBNCEO
N ;設置FLAG的標志位
MOVLW4
MOVWF DEBNCE;裝入消抖動初值SKRETURN CALL RESPORTS;存儲 I/O口值
RETURN
;
NOKEY BCF FLAG,KEYHIT;清KEYHIT標志位
GOTO SKRETURN
KEYVALUE
CLRF TEMPC
BTFSS TEMPD,3;檢測第一列
GOTO ROWVALEND
INCF TEMPC
BTFSS TEMP,2;檢測第二列
GOTO ROWVALEND
INCF TEMPC
BTFSS TEMPD,1;檢測第三列
GOTO ROWVALEND
INCF TEMPC
ROWVALEND
BTFSS TEMPE,0;是第一行否?
GOTO GETVALCOM;是,取0,1,2,3
BTFSS TEMP,1;是第二行否?
GOTO GET4567;是,取4,5,6,7
BTFSS TEMPE,2;是第三行否?
GOTO GET89AB;是,取8,9,A,B
GETCDEF BSF TEMPC,2;設置最高位
GET89AB BSF TEMPC,3
GOTO GETVALCOM
GET4567BSF TEMPC,2
GETVALCOM MOVF TEMPC,W
ADDWF PCL
RETLW0H
RETLW1H
RETLW2H
RETLW3H
RETLW4H
RETLW5H
RETLW6H
RETLW7H
RETLW8H
RETLW9H
RETLW0AH
RETLW0BH
RETLW0CH
RETLW0DH
RETLW0EH
RETLW0FH
SAVEPORTS ;在鍵盤掃描期間保存RA口和RB口狀態
MOVF RA,W;讀RA口數值
MOVWF PABUF;存入緩沖器
CLRF RA;禁止所有的接收
MOVF RB,W;讀RB口數值
MOVWF PBBUF;存入緩沖器
MOVLW0FFH;使RB口全部輸出高電平
MOVWF RB
BSF STATUS,RP0;選寄存器區1
BCF OPTION R,7;RB口弱上拉使能
MOVLW B'11110000'
MOVWF TRISB;設置RB口高4位輸入,低4位輸出
BCF STATUS,RP0;選寄存器區0
RETURN
RESPORTS ;在鍵盤掃描後恢復RA口和RB口狀態
MOVF PBBUF,W;取RB口數值
MOVWF RB
MOVF PABUF,W;取RA口數值
MOVWF RA
BSF STATUS,RP0
BSF OPTION-R,7;關閉RB口弱上拉
CLRF TRISA;設置RA口為輸出
CLRF TRISB;設置RB口為輸出
BCF STATUS,RP0
RETURN
;
DISPLAY MOVF RA,W;送接收數到W
CLRF RA;禁止所有數據接收
ANDLW0FH;屏蔽高4位
MOVWF TEMPC;存接收值到TEMPC
BSF TEMPC,4;預置最低顯示數
RRF TEMPC;右移取下一位
BTFSS STATUS,C;進位位C=1?
BCF TEMPC,3;否,重置低顯示位
BTF SCTEMPC,0;是否最高位?
GOTO UPDATAMSD;是,取最高位值
BTFSC TEMPC,1;是否第3位
GOTO UPDATA3LED;是,取第3位值
BTFSC TEMPC,2;是否第2位
GOTO UPDATA2LED;是,取第2位值UPDATALSD
MOVF LSDTIME,W;最低數送W
ANDLW0FH;屏蔽高4位
GOTO DISPLAYOUT;數據顯示UPDATA2LED
SWAPF LSDTIME,W;第2位數送W
ANDLW0FH
GOTO DISPLAYOUT
UPDATA3LED
MOVF MSDTIME;第3位數送W
ANDLW0FH
GOTO DISPLAYOUT
UPDATAMSD
SWAPF MSDTIME,W;最高位數送W
ANDLW0FH
DISPLAYOUT
CALL LSDTABLE;取段碼值
MOVFWF RB;由RB口輸出顯示
MOVF TEMPC,W;取接收值送W
MOVFWF RA
RETURN
;
LEDTABLE
ADDWF PCL;加偏移量到PC低位
RETLW B'00111111';顯示0的段碼
RETLW B'00000110';顯示1的段碼
RETLW B'01011011';顯示2的段碼
RETLW B'01001111';顯示3的段碼
RETLW B'01100110';顯示4的段碼
RETLW B'01101101';顯示5的段碼
RETLW B'01111101';顯示6的段碼
RETLW B'00000111';顯示7的段碼
RETLW B'01111111';顯示8的段碼
RETLW B'01100111';顯示9的段碼
RETLW B'01110111';顯示A的段碼
RETLW B'00111100';顯示B的段碼
RETLW B'00111001';顯示C的段碼
RETLW B'01011110';顯示D的段碼
RETLW B'01111001';顯示E的段碼
RETLW B'01110001';顯示F的段碼
;
INAD MOVLW B'11000000';選內部RC振蕩
MOVWF ADCON0
RETURN
;
SAMPLEAD
CALL SAVEPORTS
CALL DOAD;進行A/D轉換ADDONE BTFSC ADCON0,2;A/D轉換完否
GOTO ADDONE;沒完則循環等待
BSF FLAG,ADOVER;設置A/D溢出標志
CALL RESPORTS;恢復I/O口狀態
RETURN
;
DOAD CLRF RB;滅LED顯示
BSF STATUS,RP0
MOVLW0FH
MOVWF TRISA;設置RA口低4位輸入
BCF STATUS,RP0
BSF ADCON0,0;啟動A/D
MOVLW0.125
CALL WAIT;等待
BSF ADCON0,2;置A/D結束標志
RETURN
;
WAIT MOVWF
NEXT DECFSZ
GOTO
RETURN
;
B2-BCD BCF STATUS,0;清進位位
MOVLW0.16
MOVWF COUNT;設計數器初值
CLRF R0
CLRF R1
CLRF R2
LOOP16RLF L-BYTE
RLF H-BYTE
RLF R2
RLF R1
RLF R0
DECFSZ COUNT
GOTO ADJDEC;十進制轉BCD碼
RETLW0
;
ADJDEC MOVLW R2
MOVWF FSR
CALL ADJBCD;調轉BCD碼子程序
;
MOVLW R1
MOVWF FSR
CALL ADJBCD;調轉BCD碼子程序
;
MOVLW R0
MOVWF FSR
CALL ADJBCD;調轉BCD碼子程序
;
GOTO LOOP16
;
ADJBCD MOVLW3
ADDWF INDF,W
MOVWF TEMP
BTFSC TEMP,3;測試低4位結果>7否?
MOVWF INDF
MOVLW30
ADDWF INDF,W
MOVWF TEMP
BTFSC TEMP,7;測試高4位結果>7否?
MOVWF INDF
RETLW0
;
END