;***************************************************************
; Program: INTR.asm
;***************************************************************
; Author : Kelemen
; Date   : 2006.12.21
;***************************************************************
; A program bemutatja a szubrutin hívást, és az interrupt kezelését.
; A program a PORTB.0 LED-et villogtatja másodpercenként,
; a TIMER1 interrupt segítségével.
; Rendszer Quartz=8Mzh , Rendszerütem: Fosc/4 = 0,5usec
; INT: 20000*0,5usec = 10msec (századmásodpercenként)
; Megértéséhez ajánlatos tanulmányozni, a PIC16F87x adatlap 12.10 fejezetét! 
;***************************************************************

        LIST P=16F876, R=dec     ; Lista file beállítása, Alap számrendszer=decimális
        #include "P16f876.inc"   ; PIC16F876 alap konstansok
        errorlevel 1, -302       ; Bank ellenőrzési üzenetek kikapcsolása 


#define LED     PORTB,0          ; Led a Bporta 0. bitjén

; Konstansok

DivNum  equ     65536-20000      ; TMR1 osztás száma (ha 20000 akkor t=10msec)
NumH    equ     DivNum/256       ; TMR1H byte
NumL    equ     DivNum-NumH*256  ; TMR1L byte
Cnum    equ     100              ; Ciklusszámláló kezdeti értéke (osztásszám)

; Változók

Cvar    equ     0x20             ; ciklusszámláló helye a File-regiszterekben(Bank0)

;--------------------------------------------------------------------

; Program  kezdete  =================================================

        org 0x00                ; RESET vektor
        nop                     ; csak az ICD miatt
        goto    START           ; Ugrás a program elejére

; Interrupt kiszolgálása  ===========================================

        org 0x04                ; Interrupt vektor kötelező helye a 04
Int_serv			; Interrupt kiszolgálás, 10msec-onként.
        bcf     PIR1,TMR1IF     ; INT jelzés törlése (jöhet az új megszakítás)
        call    Set_TMR1        ; Timer1 újratöltése (a következő ciklus 65536lenne!)
        decfsz  Cvar            ; Cvar=Cvar-1  (100,99,98..1,0)
        goto    EndInt          ; Nincs teendőnk, ha ciklus még nagyobb mint nulla.
One_sec                         ; elfogyott a 100 ciklus (1sec)
        movlw   Cnum            ; Ciklusszám=100
        movwf   Cvar            ; ciklusváltozó újratöltése
        movlw   0x01            ; Invertáljuk majd a 0. bitet
        xorwf   PORTB,f         ; Led átváltása on/off vagy off/on
        ; Ide kellene beszúrni az idő tovább számlálását másodperc, perc, óra, stb.
EndInt
        retfie                  ; vége az INT kiszolgálásnak

; Főprogram kezdete  *********************************************

START                           ; Főprogram kezdete
        Banksel PORTB           ; Bank0                    
        clrf    PORTB           ; PortB törlése
        Banksel TRISB           ; bank1
        clrf    TRISB           ; Porta minden bitje kimenet
        Banksel PORTB           ; Bank0
        bsf     LED             ; Led bekapcsolása
        movlw   Cnum            ; ciklusszám: 10msec x 100 = 1sec
        movwf   Cvar            ; a ciklusváltozó első feltöltése

        call    Set_TMR1        ; Timer1 beállítása


; Interrupt beálítása
        Banksel PIE1            ; Bank1
        bsf     PIE1,TMR1IE     ; Timer1 INT engedélyezve
        Banksel INTCON          ; Bank0
        bsf     INTCON,PEIE     ; Periféria INT engedélyezve
        bsf     INTCON,GIE      ; Globál INT engedélyezése

; Főprogram végtelen hurokban
Loop    nop			
        goto Loop 		; Itt most semmit nem tesz, csak körbejár. 

; Ha a főprogram mást is tesz, akkor ajánlatos az interrupt elején menteni a W és STATUS
; regisztereket, majd a INT végén visszatölteni, mert az INT a programfutás bármrly részén
; bejöhet és elronthatja a két fontos regiszter tartalmát! PIC16F87x 12.10/ Example12-1

; Főprogram vége ***************************************************

; Szubrutinok  ====================================================
        
; Timer1 inicializálása
Set_TMR1                        ; Szubrutin kezdet
        banksel T1CON           ; Bank0
        clrf    T1CON           ; Timer1 leállítása
        movlw   NumH            ; Timer1 felső byte
        movwf   TMR1H           ; osztás szám betöltése H_byte
        movlw   NumL            ; Timer1 alsó byte
        movwf   TMR1L           ; osztás szám betöltése L_byte
        movlw   b'00000001'     ; Timer1: clk=osc/4 , sync=syncron , prescaler=1:1
        movwf   T1CON           ; Timer1 beállítása és indítása 
        return                  ; Szubrutin vége

; Program vége
        end


