www.elektronik.si Seznam forumov www.elektronik.si
Forum o elektrotehniki in računalništvu
 
 PomočPomoč  IščiIšči  Seznam članovSeznam članov  SkupineSkupine  StatisticsStatistika  AlbumAlbum  DatotekeFilemanager DokumentacijaDocDB LinksPovezave   Registriraj seRegistriraj se 
  PravilaPravila  LinksBolha  PriponkePriponke  KoledarKoledar  ZapiskiZapiski Tvoj profilTvoj profil Prijava za pregled zasebnih sporočilPrijava za pregled zasebnih sporočil PrijavaPrijava 

Timer1, primerjalni način delovanja

 
Objavi novo temo   Odgovori na to temo   Printer-friendly version    www.elektronik.si Seznam forumov -> Osnove programiranja PIC-a v Assembler-ju
Poglej prejšnjo temo :: Poglej naslednjo temo  
Avtor Sporočilo
Hector1
Član
Član



Pridružen-a: Čet 23 Feb 2012 11:54
Prispevkov: 98
Aktiv.: 0.67
Kraj: Primorska

PrispevekObjavljeno: Tor Jul 24, 2012 5:42 pm    Naslov sporočila:  Timer1, primerjalni način delovanja Odgovori s citatom

Ta program naj bi generiral pravokotne impulze. Zadeva naj bi delovala, vendar ko program zaženem s simulatorjem, ter priključim osciloskop, mi vleče samo ravno črto.Gre za PIC16F887a. Ima morda kdo kakšno idejo? Hvala za pomoč.

Koda:

//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// Timer1 - generiranje pravokotnih impulzov           
// Razmerje signal/PAVZA 4s/2s .. frekvenca quartz kr=4MHz
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

unsigned short int  stevec_signal=80, CCPR1_high=0xC3,CCPR1_low=0x50;
unsigned short int  stevec_pavza=40;
unsigned short int stevec=40;
// osnovna nastavitev v CCPR1=50000=0xC350


void interrupt(){
  asm{
   bcf PIR1,CCP1IF
   incf PORTD,1
   clrf TMR1L
   clrf TMR1H
   btfss PORTB,3  ; ce je bil 1 ga ugasni
   goto prizgi
   decfsz stevec,1
   retfie
   movf stevec_pavza,0
   movwf stevec
   bcf PORTB,3
   retfie
prizgi:
   decfsz stevec,1
   retfie
   movf stevec_signal,0
   movwf stevec
   bsf PORTB,3
  }

}
void timer1_ini(){
 asm{

    clrf TMR1L
    clrf TMR1H
    bsf T1CON,TMR1ON
    ;;;;;;;;;nastavimo se primerjalno mejo
    movf CCPR1_high,0
    movwf CCPR1H
    movf CCPR1_low,0
    movwf CCPR1L
  }
}
void interr_ini(){
  asm{
    bsf INTCON,PEIE
    bsf STATUS,RP0
    bsf PIE1,CCP1IE    ; v banki 1 .. naslov 0x80
    bcf STATUS,RP0
    bsf INTCON,GIE
    bsf CCP1CON,CCP1M3
    bcf CCP1CON,CCP1M2
    bcf CCP1CON,CCP1M1
    bcf CCP1CON,CCP1M0

  }
}

void main(){
    asm{
     bsf STATUS,RP0
     clrf TRISD
     clrf TRISB
     bcf STATUS,RP0
    }
    timer1_ini();
    interr_ini();

}
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
igo
Član
Član



Pridružen-a: Sre 11 Okt 2006 19:11
Prispevkov: 3638
Aktiv.: 17.11

PrispevekObjavljeno: Sre Jul 25, 2012 5:07 pm    Naslov sporočila:   Odgovori s citatom

Na koncu prekinitve manjka en retfie.

Če ze uporabljaš .asm v C-ju, mora biti na koncu main neskončna zanka, ki kroži, prekinitve pa se lepo prožijo ob predvidenih trenutkih:
Zanka
nop
goto Zanka

V C-ju je to While zanka:
while(1){
Razni ukazi
}end While , ali nekaj podobnega (stvar sintakse).

incf PORTD,1 je dokaj tvegan ukaz, zaradi beri/spremeni/piši delovanja portov.
Uporabi dodelitev konstant
W equ 0x00
F equ 0x01

nato daj raje
movf PORTD.W
addlw 0x01
movwf PORTD

_________________
Teoretično je praksa posledica teorije, praktično je pa ravno obratno. (igo 2001)
LP, Igor
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo Pošlji E-sporočilo
Hector1
Član
Član



Pridružen-a: Čet 23 Feb 2012 11:54
Prispevkov: 98
Aktiv.: 0.67
Kraj: Primorska

PrispevekObjavljeno: Čet Avg 16, 2012 1:34 pm    Naslov sporočila:   Odgovori s citatom

Hvala za odgovor, Ukaz "incf" je res malce zgoljufan vendar pa je v tem primeru prav tako uporaben za spreminjanje signala na izhodu.

Imam pa še en problem in sicer z računanjem frekvenc oziroma časovnih intervalov izvajanja prekinitev. Na spletu sem odkril kar nekaj kalkulatorjev za preračunavanje vendar prav po nobeni formuli nisem dobil rezultata kakršnega dobim, ko program testiram v simulatorju. Primer:

Kvarz kristal je 4Mhz. v TMR0 pa vpisana vrednost C8

Koda:
void interrupt(){
  asm{
   movlw 0xC8
   movwf TMR0
   bcf INTCON,T0IF
   incf PORTD,1
  }

}


void timer0_ini0(){

 asm{
    bsf STATUS,RP0

    bcf OPTION_REG,T0CS
    bsf OPTION_REG,PSA   
  /*  bcf OPTION_REG,PS0   
    bcf OPTION_REG,PS1
    bcf OPTION_REG,PS2 */

    bcf STATUS,RP0

 }

}

// inicializira prekinitve na timer0
void timer0_int_ini(){
    asm{
    bsf INTCON,T0IE
    bsf INTCON,GIE
    movlw 0xC8
    movwf TMR0
    }
}

void main(){
     TRISD=0;
     PORTD=0;
     timer0_ini0();
     timer0_int_ini();
     while(1){

     }

V simulatorju mi generira prekinitve na pribljižno 70 mikro sekund.
TUKAJ Pravijo, da naj bi se prekinitve izvajale na 56 mikrosekund.

TUKAJ pa sem spet dobil nekaj tretjega.


Upam da ima kdo v rokavu kakšno pravo formulo za izračun.
Hvala za odgovore.
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
igo
Član
Član



Pridružen-a: Sre 11 Okt 2006 19:11
Prispevkov: 3638
Aktiv.: 17.11

PrispevekObjavljeno: Čet Avg 16, 2012 3:26 pm    Naslov sporočila:   Odgovori s citatom

Dejanski čas je odvisen od vrednosti preddelilnika, ki je določena z OPTION,PS_ biti. Če so vsi trije biti 000, je preddelilnik 1:1, torej en korak od TMR0 enak strojnemu koraku od MCU. V tvojem primeru se TMR0 poveča vsako 1us.

Ker se prekinitev sproži ob prehodu TMR0 iz 0xFF v 0x00, je čas do prekinitve enak:

100.hex - C8.hex = 38.hex = 56.dec ; .hex in .dec računaš kar v WinKalkulatorju.
Ker 1.dec pri 1:1 preddelilniku traja 1us, se bo tvoja prekinitev zgodila vsakih 56us.

Teoretično.

Praktično se zgodi 2 strojna takta kasneje (2us kasneje), kolikor MCU potrebuje, da povozi trenutno vrednost TMR0 z vsiljeno.

Razlika od 58us do 70us pa nastane zaradi tvojega prevajalnika.
Če bi pisal v čistem .asm, bi prekinitev izgledala takole:
Koda:

pPrekin            ;Interupt Vektor
   movwf   w_copy      ; w kopija
   swapf   STATUS, w    ; STATUS kopija
   clrf   STATUS   ; Banka 0
   movwf   s_copy      ; STATUS kopija
      movf   PCLATH, W
      movwf   p_copy   ; KOPIJA OD PCLATH v prekinitvi
   clrf   PCLATH


; Intrupt service routine
   movlw 0xC8
   movwf TMR0
   bcf INTCON,T0IF 
   incf PORTD,1   ; *************
; Intrupt service routine


pPrekV ; prekinitev VEN
   bcf   INTCON, T0IF   ; Interupt-Flag IZBRIŠE   
   movf   p_copy,w   ; KOPIJA OD PCLATH v prekinitvi
   movwf   PCLATH
   swapf   s_copy,w   ; povrne STATUS
   movwf   STATUS
   swapf   w_copy,f   ; Povrne W, skupaj s STATUS zastavicami
   swapf   w_copy,w

   retfie
Kot vidiš se od trenutka, ko se postavi prekinitvena zastavica, pa do trenutka, ko se spremeni PORTD ********** , zgodi kar nekaj korakov, ki jih ti ne vidiš, prevajalnik pa jih samodejno doda. Pa še nekaj jih doda, preden odleti iz prekinitve, a se ti koraki že štejejo v TMR0.

Enostavno testiraj in boš videl, kolikšen je konstanten pribitek mikrosekund.

_________________
Teoretično je praksa posledica teorije, praktično je pa ravno obratno. (igo 2001)
LP, Igor
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo Pošlji E-sporočilo
Hector1
Član
Član



Pridružen-a: Čet 23 Feb 2012 11:54
Prispevkov: 98
Aktiv.: 0.67
Kraj: Primorska

PrispevekObjavljeno: Čet Avg 16, 2012 4:26 pm    Naslov sporočila:   Odgovori s citatom

Citiram:
Kot vidiš se od trenutka, ko se postavi prekinitvena zastavica, pa do trenutka, ko se spremeni PORTD ********** , zgodi kar nekaj korakov, ki jih ti ne vidiš, prevajalnik pa jih samodejno doda. Pa še nekaj jih doda, preden odleti iz prekinitve, a se ti koraki že štejejo v TMR0.
To je odgovor na vprašanje katerega se mislil pravkar zastavit.

Hvala za izčrpno razlago, se pravi če želim točen interval se bom moral še malce pozabavat.
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
Alex17
Član
Član



Pridružen-a: Ned 28 Feb 2010 21:46
Prispevkov: 476
Aktiv.: 2.78
Kraj: Ljutomer

PrispevekObjavljeno: Čet Avg 16, 2012 7:14 pm    Naslov sporočila:   Odgovori s citatom

Večina simulatorjev/debuggerjev ima možnost izvajanja programa korak po korak tudi v asemblerju, ki ga prevajalnik naredi iz tvoje C kode. Najdeš ga pa ponavadi nekje pri View - Assembly/Listing... Tam točno vidiš koliko ukazov se v resnici izvaja.
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
Pokaži sporočila:   
Objavi novo temo   Odgovori na to temo   Printer-friendly version    www.elektronik.si Seznam forumov -> Osnove programiranja PIC-a v Assembler-ju Časovni pas GMT + 2 uri, srednjeevropski - poletni čas
Stran 1 od 1

 
Pojdi na:  
Ne, ne moreš dodajati novih tem v tem forumu
Ne, ne moreš odgovarjati na teme v tem forumu
Ne, ne moreš urejati svojih prispevkov v tem forumu
Ne, ne moreš brisati svojih prispevkov v tem forumu
Ne ne moreš glasovati v anketi v tem forumu
Ne, ne moreš pripeti datotek v tem forumu
Ne, ne moreš povleči datotek v tem forumu

Uptime: 48 dni


Powered by phpBB © 2001, 2005 phpBB Group