|
www.elektronik.si Forum o elektrotehniki in računalništvu
|
Poglej prejšnjo temo :: Poglej naslednjo temo |
Avtor |
Sporočilo |
Hector1 Član
Pridružen-a: Čet 23 Feb 2012 11:54 Prispevkov: 98 Aktiv.: 0.67 Kraj: Primorska
|
Objavljeno: Tor Jul 24, 2012 5:42 pm Naslov sporočila: Timer1, primerjalni način delovanja |
|
|
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 |
|
|
igo Član
Pridružen-a: Sre 11 Okt 2006 19:11 Prispevkov: 3638 Aktiv.: 17.11
|
Objavljeno: Sre Jul 25, 2012 5:07 pm Naslov sporočila: |
|
|
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 |
|
|
Hector1 Član
Pridružen-a: Čet 23 Feb 2012 11:54 Prispevkov: 98 Aktiv.: 0.67 Kraj: Primorska
|
Objavljeno: Čet Avg 16, 2012 1:34 pm Naslov sporočila: |
|
|
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 |
|
|
igo Član
Pridružen-a: Sre 11 Okt 2006 19:11 Prispevkov: 3638 Aktiv.: 17.11
|
Objavljeno: Čet Avg 16, 2012 3:26 pm Naslov sporočila: |
|
|
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 |
|
|
Hector1 Član
Pridružen-a: Čet 23 Feb 2012 11:54 Prispevkov: 98 Aktiv.: 0.67 Kraj: Primorska
|
Objavljeno: Čet Avg 16, 2012 4:26 pm Naslov sporočila: |
|
|
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 |
|
|
Alex17 Član
Pridružen-a: Ned 28 Feb 2010 21:46 Prispevkov: 476 Aktiv.: 2.78 Kraj: Ljutomer
|
Objavljeno: Čet Avg 16, 2012 7:14 pm Naslov sporočila: |
|
|
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 |
|
|
|
|
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
|