十年專注單片機方案開發的方案公司英銳恩,分享和初學者一起學習。英銳恩現提供服務產品涉及主控芯片:8位單片機、16位單片機、32位單片機及各類運算放大器等。
以下程序:
;************************
;60秒記數,RB0控制時間模式切換;RB1控制秒高/低位切換;
;RB2控制加1功能;RB4控制停止/啟動;TMR2產生秒信號;TMR0
;控制數碼管掃描
;************************
list p=16f877a
#include
;************************
__CONFIG _CP_OFF&_WDT_OFF&_PWRTE_ON&_XT_OSC&_WRT_OFF&_LVP_OFF&_CPD_OFF
;************************
cblock 0x30
second_l ;秒低位
second_h ;秒高位
_t2count ;T2記數
time_mode ;時間模式
flag ;停止標志
porta ;移位標志
porta_w ;位選通標志
fsr
_ptr ;指針
_count ;閃爍次數記數
_flag0 ;兩次閃爍間隔標志
endc
cblock 0x70
w_temp
status_temp
fsr_temp
pclath_temp ;中斷臨時寄存器
endc
#define key0 PORTB,0
#define key1 PORTB,1
#define key2 PORTB,2
#define key4 PORTB,4 ;定義按鍵
#define _cycletime .249 ;循環時間
;*************************
org 0x000
nop
goto main
;************************
org 0x004
movwf w_temp
movf STATUS,w
clrf STATUS
movwf status_temp
movf PCLATH,w
movwf pclath_temp
movf FSR,w
movwf fsr_temp ;現場保護
;*************************
banksel INTCON ;中斷判斷
btfss INTCON,PEIE
goto _chkt0int
banksel PIE1
btfss PIE1,TMR2IE
goto _chkt0int
banksel PIR1
btfss PIR1,TMR2IF
goto _chkt0int
;****************************
;確定T2中斷
;****************************
banksel PORTA
pagesel $
clrf PIR1 ;清標志
btfss time_mode,0 ;模式判斷,是否普通顯示模式
goto _flickerdis ;否,轉閃爍顯示模式
;****************************
decf _t2count,f
movf _t2count,w
skpz
goto _generaldis ;沒到1秒,轉普通顯示
movlw .25
movwf _t2count
call _addsec ;1秒處理
goto _generaldis ;1秒處理后轉普通顯示
;******************
_chkt0int ;t0中斷判斷
banksel INTCON
btfss INTCON,T0IE
goto endofint
btfss INTCON,T0IF
goto endofint ;不是則直接中斷退出
;****************************
bcf INTCON,T0IF;確定為T0中斷,先清標志
btfss time_mode,0 ;判斷顯示模式
goto _flickerdis ; 轉閃爍顯示
goto _generaldis ;轉普通顯示
;****************************
_generaldis
clrf STATUS ;轉體0,普通顯示,C=0,IRP=0
comf porta_w,w
movwf PORTA ;低位選通
movlw second_l&0xff ;取秒低位首地址
movwf FSR
movf _ptr,w
addwf FSR,f ;確定時間單元地址
movf INDF,w
movwf fsr
call _tablepro;查表處理
movwf PORTC ;數碼顯示
btfsc porta_w,1 ;判斷2位是否移位完畢
goto bb
clrc
rlf porta_w,f ;沒有,準備點亮下一位
cc incf _ptr,f ;指針指向下1時間單元
movlw 0x01
andwf _ptr,f ;保證指針在2個時間單元移動
goto endofint
bb movlw 0x01 ;兩位移位完畢,重新賦值開始新一輪顯示
movwf porta_w
goto cc
;*******************************
_flickerdis
movlw .25 ;閃爍顯示,重新賦值時間記數器
movwf _t2count
clrf STATUS ;轉體0,C=0,IRP=0
btfss _flag0,0 ;兩次閃爍的間隔次數控制標志,1=調整位亮,0=調整位滅
goto mm ;0則調整位滅
comf porta_w,w
movwf PORTA
movlw second_l&0xff ;取秒低位首地址
movwf FSR
movf _ptr,w
addwf FSR,f
movf INDF,w
movwf fsr
call _tablepro
movwf PORTC
btfsc porta_w,1
goto bb1
clrc
rlf porta_w,f ;準備點亮下一位
cc1 incf _ptr,f
movlw 0x01
andwf _ptr,f
decf _count,f ;閃爍次數
movf _count,w
skpnz
goto _judge_porta
goto endofint
bb1 movlw 0x01
movwf porta_w
goto cc1
;***********************************
_judge_porta
clrf _flag0 ;標志位清0
movlw .100
movwf _count
mm btfss porta,0 ;判斷正在調整哪一位
goto sec_lpro ;秒低位調整
goto sec_hpro ;秒高位調整
sec_lpro
movlw b'11111101' ;低位調整,高位一直選通
movwf PORTA
movf second_h,w
LL movwf fsr
call _tablepro
movwf PORTC
decf _count,f
movf _count,w
skpz
goto endofint
movlw 0x01
xorwf _flag0,f ;標志取反
movlw .60
movwf _count
goto endofint
sec_hpro
movlw b'11111110';高位調整
movwf PORTA
movf second_l,w
goto LL
;******************
endofint ;中斷退出
clrf STATUS
MOVF fsr_temp,w ;現場恢復
MOVWF FSR
movf pclath_temp,w
movwf PCLATH
movf status_temp,w
movwf STATUS
swapf w_temp,f
swapf w_temp,w
retfie
;************************
main
banksel TRISA
movlw 0x07
movwf ADCON1 ;轉體1,設置A口全數字通道,輸出,數碼管位控
clrf TRISA
movlw b'00010111'
movwf TRISB
clrf TRISC ;數碼管段碼輸出
movlw 0x02
movwf OPTION_REG ;TMRO分品比1:8,內部時鐘,2MS中斷一次,B口內部上拉
clrf STATUS ;轉體0
clrf INTCON ;清標志
bsf INTCON,T0IE
bsf INTCON,PEIE ;T0&PEIE使能
banksel TRISA
movlw _cycletime
movwf PR2 ;設置T2循環周期
clrf PIE1
bsf PIE1,TMR2IE ;使能T2
banksel PORTA
clrf PORTB
RETLW 99H ;4
RETLW 92H ;5
RETLW 82H ;6
RETLW 0F8H ;7
RETLW 80H ;8
RETLW 98H ;9
;***************************************
end
(文源網絡,侵刪)