che componente è questo, un quarzo ? Problema con atmega16

E' un quarzo SMD questo ?

formatting link

Chiedo perche' ho un problema "inspiegabile" con un atmega16 che oscilla con quel componente li' : ambiente c, ottimizzazione disattivata, semplice programma che genera una base tempi ( 5mS alto, 5 mS basso) in interrupt routine TMR0 testato con AVR studio 4.

Eccolo di seguito :

__interrupt void int_timer (void){

//per tempi precisi

asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");

SFIOR=SFIOR | 1; //azzero prescaler per ri-sincronizzare

TCNT0=178; //ricarico timer per 1 interruzione ogni 5 mS con quarzo 4 MHz !

if(PIND&4){PORTD_Bit2=0;}else{PORTD_Bit2=1;}

} //end interrupt TMR0 routine

Con AVR studio 4 in simulazione ottengo un toggle del PORTD Bit2 ogni 5 mS spaccati, nella realtà per ottenere un fronte ascendente ogni 10 mS ho dovuto aggiungere degli wait states per rallentare il programma dello 0.6%. In pratica, usandolo come cronometro, "guadagnava" circa 2.9 secondi ogni 8 minuti. Un'esagerazione...

Ciao, Pier.

formatting link

Reply to
Pier GSi
Loading thread data ...

Pier GSi:

quel componente li' : ambiente c,

alto, 5 mS basso) in interrupt routine

Non ho guardato il programma, ma tu sei sicuro di non aver riprogrammato i fusibili a caso?

Reply to
F. Bertolazzi

oscilla con quel componente li' : ambiente c,

tempi ( 5mS alto, 5 mS basso) in interrupt routine

riprogrammato i

non ho il pc sottomano ma ricordo con certezza i 4 fuses relativi all'oscillatore non spuntati (uso ponyprog), per cui 1111 > external crystal resonator e non oscillatore interno (se e' a questo che volevi arrivare )...

Ciao, Pier.

formatting link

Reply to
Pier GSi

Pier GSi ha scritto:

sembra di si' , i due grigi sotto sono i due cap NP0 verso gnd.

quel componente li' : ambiente c,

alto, 5 mS basso) in interrupt routine

durante questi 17 nop + sfior + int_timer sono passati circa 5uS , che su 5mS corrisponde allo 0.1% : non e' certo con questi che rallenti dello 0.6% . con questo sistema inquini la precisione dell' hardware con la indeterminazione del software (quando e' scattato interrupt stava eseguendo una istruzione da 1_2_3 cicli ?). meglio eliminare questa parte e lavorare altrove.

se proprio devi usare il timer0, il numero esatto sarebbe

256ovf-(5000uS*4MHz/256psc) = 177.875 , che puoi ottenere (preciso nel lungo periodo) facendo 7 volte 178 e 1 volta 177. l' errore residuo e' il quarzo.

saluti

--
  lowcost
Reply to
lowcost

"lowcost" ha scritto nel messaggio news:gm57t1$s2p$ snipped-for-privacy@nnrp-beta.newsland.it...

? Quelle istruzioni ci sono perche' senno' l'interrupt arriverebbe prima dei 5 mS.

Che indeterminazione, scusa ? Lui esegue *sempre* le stesse istruzioni a vuoto per arrivare al tempo richiesto, piu preciso di cosi'... Non vedo inoltre nessun collegamento tra il discorso-istruzioni che stava eseguendo prima e la INT routine...

Mettere delle iterazioni per fare 7 volte 178 ed una 177, secondo te sarebbe piu preciso e semplice rispetto al mio codice ? :O

Sono perplesso...

Ciao, Pier.

formatting link

Reply to
Pier GSi

Pier GSi ha scritto:

mS.

tu hai detto che rallenti dello 0.6% , ma quelle istruzioni non possono rallentare piu' dello 0.1% .

per arrivare al tempo richiesto, piu

eseguendo prima e la INT routine...

mega16 ha istruzioni da 1_2_3_4 clock : "If an interrupt occurs during execution of a multi-cycle instruction, this instruction is completed before the interrupt is served. "

piu preciso e semplice rispetto al mio

se vuoi usare il timer0 e ottenere il periodo esatto (mediato a lungo termine) questo e' uno dei modi possibili; non e' il piu' semplice. non sono iterazioni, e' un contatore.

saluti

--
  lowcost
Reply to
lowcost

"lowcost" ha scritto nel messaggio news:gm7qut$hff$ snipped-for-privacy@nnrp-beta.newsland.it...

mS.

Il codice che ho riportato è quello per ottenere i 5 mS teorici ma che in realtà va lo 0.6% piu' veloce.

IN SEGUITO l'ho ritardato dello 0.6%.

vuoto per arrivare al tempo richiesto, piu

eseguendo prima e la INT routine...

Si ma cosa c'entra con il nostro discorso ? Il mio micro va troppo veloce, non troppo lento.

P.S. La prossima volta che smonto la scheda sostituisco provvisoriamente il quarzo con un altro sempre da 4 MHz e ri-misuro.

piu preciso e semplice rispetto al mio

Credo di non avere capito, scrivimi come faresti 7 volte 177 ed una 178...

Ciao, Pier.

formatting link

Reply to
Pier GSi

Pier GSi:

news:gm7qut$hff$ snipped-for-privacy@nnrp-beta.newsland.it...

Metti il Timer0 in modo CTC e gli carichi 177 in OCR0A. Ad ogni interrupt Timer0 CompA incementi una variabile. Quando arriva a 7 carichi 178 in OCR0A. Quando arriva a 8 carichi 177 in OCR0A e azzeri la variabile.

Reply to
F. Bertolazzi

E fu cosi` che invento` il fractional divider :)

(Non c'entra, mi indichi il data sheet delle celle?)

--

Franco

Wovon man nicht sprechen kann, darüber muß man schweigen.
(L. Wittgenstein)
Reply to
Franco

Franco:

E' solo un'implementazione su di un particolare hardware, nulla di più. ;-)

formatting link

Reply to
F. Bertolazzi

"F. Bertolazzi" ha scritto nel messaggio news:1fyfb1it6c34n$. snipped-for-privacy@40tude.net...

Ok, l'iterazione quindi c'e'. Visto che perdere qualche uS in int routine non mi cambia di certo la vita, vale la pena complicarsi la vita ? IMHO no...

Altra cosa : questo micro fornisce il timing ad un pic 16f877 @ 20 MHz che deve gestire due capture a qualche centinaio di Hz per prendere i giri motore e la velocità del veicolo, svariate decine di acquisizioni per secondo, inviare via seriale i dati ed, oltre a questo, UN CRONOMETRO.

Ci ho pensato un bel po ma non ho trovato il modo per fare tutto con i timer interni mantenendo delle temporizzazioni precise (non posso perdere piu di 1 decimo ogni 10 minuti) : quando il timer chiama l'interruzione, se il micro sta eseguendo un'istruzione che richiede piu cicli di un altra, o peggio se sta dentro un'altra routine di interruzione, accumulo man mano sempre piu' ritardo perche' non lo ricarico nel momento esatto. Penso che l'unica sarebbe non ricaricare mai il timer ed "accettare" di avere gli interrupt ad un tempo pari al clock * il prescaler, solo che in questo modo con un quarzo da 20 MHz non potro' mai avere un interrupt ogni 10 mS (o suoi sottomultipli interni) ma bensì ogni 13.1 mS. Ci vorrebbe un quarzo da 15.25878 MHz, esiste ?

Ciao, Pier.

formatting link

Reply to
Pier GSi

"Pier GSi" ha scritto nel messaggio news: snipped-for-privacy@mid.individual.net...

^^^^^^^^^^ INTERI ! ops

Reply to
Pier GSi

Pier GSi:

Fa' come preferisci. Sappi solo che, nel seguito, dimostri di non aver capito un tubo.

Ma, permettimi, cosa chiedi a fare aiuto qui, se credi di sapere già tutto?

Reply to
F. Bertolazzi

Franco:

Questo invece è il test sheet:

formatting link

Reply to
F. Bertolazzi

"F. Bertolazzi" ha scritto nel messaggio news:6ux57vy4yyck$.7ickkvqeayo5$. snipped-for-privacy@40tude.net...

Se capissi qualcosa forse non avrei neanche posto la domanda :P

Se ho dato questa impressione me ne scuso, mi piacerebbe semplicemente arrivare ad una soluzione del problema (non tanto per reale necessità ma solo per discuterne, ora come ora con il clock esterno funziona, e per me potrebbe benissimo restare cosi').

Ciao, Pier.

formatting link

Reply to
Pier GSi

Pier GSi ha scritto:

OK , allora i 17 NOP non sono gli "wait states" che rallentano il programma dello 0.6% : mi chiedo dove sei intervenuto per sistemarlo.

troppo lento.

per rallentarlo, ogni periodo timer di 4992 mS perdi 5uS coi nop + X (che dipende da cosa ha deciso il compilatore) + 1__4 clock di indeterminazione nella latenza interrupt.

7 volte 178 ed una 177. elimini nop e clear prescaler, metti un contatore 8_0 che decrementi ogni volta che entri in isr, poi lo testi: se diverso da 0 avvii il TCNT0=178 , se invece e' 0 lo ricarichi a 8 e avvii TCNT0=177. visto il prescaler a 256, interrupt ha ben 256 clock per fare il lavoro. non ci sono errori cumulativi: i periodi non sono tutti uguali ma a lungo termine hai tutta la precisione del quarzo. se vuoi periodi tutti uguali, devi usare timer16 oppure un altro quarzo oppure un prescaler piu' basso e interrupt piu' frequente; se vuoi i periodi perfettamente uguali, deve essere l' hardware (compare) a muovere il pin.

saluti

--
  lowcost
Reply to
lowcost

lowcost:

Già. Ormai per me 8=88 e 16=168.

Reply to
F. Bertolazzi

"lowcost" ha scritto nel messaggio news:gmadft$7s9$ snipped-for-privacy@nnrp-beta.newsland.it...

Nel caso atmega16 si', effettivamente cosi' il prescaler continua a contare e non ci sono errori dovuti al numero di cicli relativi all'istruzione che il micro stava eseguendo prima della chiamata, pero' di fatto il mio programma ha come main

while(1){ }

quindi cosa cambierebbe ?

Lui quando non è in interrupt tmr0 (l'unico abilitato) esegue all'infinito un salto a PC-0x0000, per cui prima di saltare in INT sta eseguendo un'istruzione lunga 2 (?) cicli...

Facendo come dici non risolverei neanche il problema principale che ho esposto a Bertolazzi e che mi ha portato a mettere la base tempi esterna, visto che sul 16F877 quando ricarico TMR0 il prescaler si resetta...

O sbaglio ?

Ciao, Pier.

formatting link

Reply to
Pier GSi

Pier GSi ha scritto:

ntare e non ci sono errori dovuti al numero di=20

chiamata, pero' di fatto il mio programma ha come=20

inito un salto a PC-0x0000, per cui prima di=20

esposto a Bertolazzi e che mi ha portato a=20

0 il prescaler si resetta...

faccio veramente fatica a seguirti, devo essere troppo stupido.

se il mega16 fa solamente quello (praticamente niente) & devi usare il=20 timer0 , allora puoi fare come gia' detto (178_177) + usare prescaler 64 e muovere il pin ogni 4 giri di interrupt (usi lo stesso contatore 8). int avviene ogni 1.25mS circa, deve essere eseguito entro 64 clock=20 (prima del prossimo incremento dal prescaler). tra i due periodi 5mS alto e 5mS basso avresti una piccola differenza=20 costante di 64 clock (16uS); il 10 mS e' sempre preciso, a parte il=20 quarzo e il ritardo del sw per eseguire isr e muovere pin. non ci sono=20 errori cumulativi.

io mi fermo qui, saluti.

--=20 lowcost

Reply to
lowcost

"lowcost" ha scritto nel messaggio news:gmccne$g8f$ snipped-for-privacy@nnrp-beta.newsland.it...

Ma figurati, probabilmente sono io a non capire.

allora puoi fare come gia' detto

prossimo incremento dal prescaler).

di 64 clock (16uS); il 10 mS e' sempre

non ci sono errori cumulativi.

Questo l'ho capito, grazie. E mi è anche chiaro : se non vado a resettare il prescaler lui continua a contare, per cui ho a disposizione un numero di cicli per fare il tutto pari al fattore di divisione dello stesso.

Il problema dell'877 è che, a differenza dell'atmel in cui posso resettarlo se voglio alzando il bit SFIOR, ogni volta che ricarico TMR0 non conosco un modo per far si' che il prescaler non si azzeri da solo. Come faccio a non avere errori cumulativi avendo a disposizione solo TMR0 ? Non ho altro a disposizione, i due capture e TMR2 sono occupati.

Ciao, Pier.

formatting link

Reply to
Pier GSi

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.