Kod: Zaznacz cały
; 22.08.2015
; Zegar z wy¶wietlaczem 7 segmentowym
; PIC16F870 @ 4MHz
; Antystatyczny
list p=16f870
#include <p16f870.inc>
#include <mux/mux.inc>
;global ss, mm, hh
extern mux_init, mux_isr, timer
extern digit1, digit2, digit3, digit4
;*********************** CONFIG PROCKA *****************************************
__config _XT_OSC & _WDT_OFF & _PWRTE_OFF & _LVP_OFF & _DEBUG_OFF
;*********************** "ZMIENNE" *********************************************
UDATA_SHR ;przestrzeń 16 bajtów niebankowanych
w_temp RES 1 ;akumulator - context saving
status_temp RES 1 ;status procka - context saving
ss RES 1 ;sekundy
mm RES 1 ;minuty
hh RES 1 ;godziny
dividend RES 1 ;dzielna
divider RES 1 ;dzielnik
result RES 1 ;czę¶ć całkowita wyniku dzielenia
remainder RES 1 ;czę¶ć ułamkowa z dzielenia
;*********************** START PROGRAMU ****************************************
RESET_VECTOR CODE 0x0000
goto start
INT_VECTOR CODE 0x0004 ;wektor i obsługa przerwania
movwf w_temp ;akumulator do w_temp
movf STATUS,w ;ładuj STATUS do akumulatora
movwf status_temp ;akumulator do STATUS_temp
call mux_isr
movf status_temp,w ;status_temp do akumulatora
movwf STATUS ;ładuj akumulator do STATUS
swapf w_temp,f ;zamień półbajty, wynik w w_temp
swapf w_temp,w ;zamień półbajty, wynik w akumulatorze
retfie ;powrót z przerwania
;************************** MAIN ***********************************************
MAIN_PROG CODE
start
;************************** inicjalizacja zmiennych ****************************
;To trzeba zautomatyzować i wykorzystać adresowanie po¶rednie
movlw 0 ;ładuj akumulator warto¶ci± 0
movwf timer ;akumulator zapisany w zmiennej timer
movwf ss
movwf mm
movwf hh
call mux_init
;************************** PĘTLA GŁÓWNA ***************************************
loop
movlw 10
movwf divider ;ustawiam dzielnik na 10
movf hh, W ;ładuję godziny do akumulatora
movwf dividend ;ustawiam dzieln±(dzielenie godzin przez 10)
call div8by8 ;wywołujemy podprogram dzielenia i modulo
movf result, W
movwf digit1 ;czę¶ć całkowita dzielenia do cyfry 3
movf remainder, W
movwf digit2 ;czę¶ć ułamkowa dzielenia do cyfry 4
movlw 10
movwf divider ;ustawiam dzielnik na 10
movf mm, W ;ładuję minuty do akumulatora
movwf dividend ;ustawiam dzieln±(dzielenie minut przez 10)
call div8by8 ;wywołujemy podprogram dzielenia i modulo
movf result, W
movwf digit3 ;czę¶ć całkowita dzielenia do cyfry 3
movf remainder, W
movwf digit4 ;czę¶ć ułamkowa dzielenia do cyfry 4
movf timer, F ;programowy timer == 0?
btfsc STATUS, Z ;je¶li nie, nie wywołuj podprogramu (skip)
call clock ;w przeciwnym razie wywołaj podprogram
goto loop
;************************** podprogram wykonuj±cy dzielenie i modulo ***********
div8by8
movlw 0
movwf result ;zerowanie wyniku
go_div
movf dividend, W ;załaduj dzieln±
movwf remainder ;dzielna jako "reszta" (na wszelki wypadek)
movf divider, W ;załaduj dzielnik do akumulatora
subwf dividend, F ;odejmij od dzielnej, wynik w dzielnej
btfss STATUS, C ;wynik odejmowania spowodował przepełnienie?
goto skip_sub ;je¶li przepełnienie, kończ operację
btfsc STATUS, Z ;została jaka¶ reszta?
goto skip_sub_zero ;je¶li zero, kończ operację
incf result ;zwiększam wynik o 1
goto go_div ;ponawiamy operację odejmowania
skip_sub_zero
incf result ;ostatni raz zwiększam, bo dzielnik się zmie¶cił
movlw 0
movwf remainder ;zeruję licznik reszty
skip_sub
return
;************************** podprogram clock ***********************************
clock
check_ss
incf ss ;inkrementuj sekundy
movf ss, W ;sprawdzamy, czy ss > 59
sublw 59
btfsc STATUS, C ;je¶li nie, od razu skocz do update_clock
goto update_clock
movlw 0 ;je¶li tak, to ss = 0, mm++
movwf ss ;resetuj sekundy
incf mm ;inkrementuj minuty
check_mm
movf mm, W ;sprawdzamy, czy mm > 59
sublw 59
btfsc STATUS, C
goto update_clock
movlw 0
movwf mm ;resetuj minuty
incf hh ;inkrementuj godziny
check_hh
movf hh, W ;sprawdzamy, czy hh > 23
sublw 23
btfsc STATUS, C
goto update_clock
movlw 0 ;resetuj godziny
movwf hh
update_clock
movlw 199
movwf timer
return
end
Pozdrawiam