Strona 1 z 1

[PIC16F][ASM] Przykład multipleksowania wyśw. 7seg

: niedziela 27 lis 2016, 17:45
autor: Antystatyczny
Witam. Kiedyś popełniłem mały programik multipleksujący wyświetlacz w assemblerze. Program jest na PIC16F870 i może komuś się przyda podczas nauki ;). Program jest do bólu obłożony komentarzami, więc zapraszam wszystkich na dowolnym poziomie wiedzy.

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
   
   


pic16_7seg_mux_asm.X.zip


Pozdrawiam

Re: [PIC16F][ASM] Przykład multipleksowania wyśw. 7seg

: poniedziałek 28 lis 2016, 01:15
autor: j23
Antystatyczny pisze:(...)może komuś się przyda(...)
Na pewno się przyda! :)
Świetna sprawa Anty!
Jeżeli Matematyka (jak mówią) jest królową nauk, to ja uważam, że Assembler jest królem wśród języków programowania mikrokontrolerów -oczywiście nic nie ujmując C czy C++... -innych języków nie uznaję ;)

Pozdrawiam! j23 Jarek