- Messaggi: 40
- Ringraziamenti ricevuti 0
Timer ma con tempi lunghi
Ho provato tante combinazioni ma non riesco ad avere una base-time senza decimali. Il minimo errore che riesco ad avere dalle combinazioni è del 2,8%. Un pò troppo per tempi lunghi.
La soluzione che Max ha prospettato per Toni di fare partire il conteggio del registro non da zero, è molto interessante, ma funziona anche per altri registri, anche a 8 bit ?
Ad esempio, se facessi partire da 0b00000110 (6 decimale) il registro timer0 se a 8 bit (nel 16F1847 timer0 è a 8 bit), dividendo una frequenza per 250 anzichè per 256 è più facile ottenere base-time senza decimali.
Però, se ho capito bene, è lo stesso registro che si incrementa e provoca l'overflow. Lo stesso registro non si ferma all'overflow ma continua ripartendo da ..... zero ? Oppure, come riparte da 6 ?
Un'altra cosa interessante è il BAUDCONbits.WUE=1 con SLEEP(). In tal caso, la prima serie del codice asincrono serve solo per "svegliare" EUSART ? La lettura vera e propria del codice avviene dopo la sveglia, con la ripetizione dell'invio ?
Si prega Accedi o Crea un account a partecipare alla conversazione.
- MauroFx
- Autore della discussione
- Senior Member
sima funziona anche per altri registri, anche a 8 bit ?
ma come non hai capito? lo ho spiegato bene nei due post precedenti comunque ripeto:Però, se ho capito bene, è lo stesso registro che si incrementa e provoca l'overflow. Lo stesso registro non si ferma all'overflow ma continua ripartendo da ..... zero ? Oppure, come riparte da 6 ?
all'overflow cioè al passaggio da 255 a 0, per il timer0 a 8bit, viene generato un interrupt quindi basta inserire nella funzione che gestisce l'interrupt una linea di codice che ricarica il registro contatore del timer0 con il valore 6 così il conteggio riparte da 6 tutte le volte
personalmente non ho mai provato la funzione sleep con wake up da eusart, comunque nel data sheet si consiglia di inviare una sequenza di zeri, penso che usando sleep si complichi il tutto e dovrai inventarti un protocollo di comunicazione tra il device esterno e la centralina in questo modo:Un'altra cosa interessante è il BAUDCONbits.WUE=1 con SLEEP(). In tal caso, la prima serie del codice asincrono serve solo per "svegliare" EUSART ? La lettura vera e propria del codice avviene dopo la sveglia, con la ripetizione dell'invio ?
il device esterno invia una sequenza di zeri poi invia un carattere speciale per indicare che inizia a trasmettere i dati validi poi trasmette i dati e infine invia un altro carattere speciale per indicare che i dati sono terminati a meno che i dati abbiano una lunghezza costante, la centralina invece riceve i caratteri e li butta via finchè non riceve il carattere speciale di inizio dati, a quel punto inizia a memorizzare i dati ricevuti in un array per un numero costante o finchè non riceve il carattere speciale di fine dati, chiaramente i caratteri speciali non devono far parte del set di caratteri dei dati, nel caso si debbano ripetere i dati, per ragioni di sicurezza, la cosa si complica ulteriormente
Si prega Accedi o Crea un account a partecipare alla conversazione.
- permax1958
- Premium Member
- Messaggi: 91
- Ringraziamenti ricevuti 16
Visto che conosci molto bene il 16F1847 (mi rivolgo principalmente a Max), vorrei chiederti come si "spenge" il timer0. Dal datasheet e dallo schema elettrico, sembra che sia sempre attivo, o in una modalità o in un'altra.
Agli effetti del codice non cambia molto, in quanto si può agisce sulla attivazione/disattivazione delle interrupt.
Timer1, al contrario, ha i registri necessari per essere attivato e disattivato (T1CONbits.TMR1ON).
Mi puoi spiegare ?
Grazie in anticipo.
Si prega Accedi o Crea un account a partecipare alla conversazione.
- MauroFx
- Autore della discussione
- Senior Member
- Messaggi: 40
- Ringraziamenti ricevuti 0
Si prega Accedi o Crea un account a partecipare alla conversazione.
- permax1958
- Premium Member
- Messaggi: 91
- Ringraziamenti ricevuti 16
Una parola sullo SLEEP: riduce i consumi ma solo della CPU. Quando ci sono ingressi e uscite a bassa impedenza, che normalmente devono essere "caricati", ci sono più consumi lì che nella CPU, tanto da rendere poco efficace il risparmio di SLEEP. In alternativa, ho preferito abbassare la frequenza di clock, ma stando attento a non "impiccarmi" con l'oscillatore per EUSART; 1MHz è al limite per ottenere 9600Baud.
Per la gestione di tutte le temporizzazioni ho usato il timer0, che è sempre attivo di suo.
Per comprenderne l'utilità, pensiamo a uscite-attuatore, che devono essere mantenute attive solo per un determinato tempo, con attivazione e reset diversi tra le varie uscite. Ma serve anche per gestire alcuni ingressi, specialmente se interessati da collegamenti esterni lunghi, per i quali non basta il "normale" anti-rimbalzo.
Per ottenere i lunghi ritardi, simultanei e diversi per più uscite, ho creato una variabile statica che assume la funzione di registro-timer, a livello logico attivo, quando è richiesta almeno una delle temporizzazioni necessarie. L'assenza di temporizzazioni in atto, resetta il registro.
A sua volta il registro agisce nella elaborazione del codice e, principalmente, attiva/disattiva le interrupt da timer0.
Per ogni temporizzazione ho creato 3 variabili:
- R_Uno che attiva il conteggio;
- T_Uno che si incrementa ad ogni interrupt da overflow di timer0;
- M_Uno è impostata al tempo massimo da raggiungere.
E questo, sia per Uno, Due, Tre, ecc.
se (T_Uno>=M_Uno){ T_Uno=R_Uno=0; LATXbits.LAX =0}
se (R_Uno || R_Due || R_n) {registro_timer=1}
oppure {registro_timer=0;}
Il valore delle 3 variabili NON indica i secondi, bensì, il periodo della base dei tempi, cioè, l'inverso della frequenza alla quale si verificano le interrupt da overflow di timer0. Ho scelto 1 millisecondo.
La base-tempi deve essere irrilevante rispetto a quella di elaborazione delle istruzioni (FOSC), ma con periodo senza decimali, per non costringerci a calcoli complicati.
Siccome, difficilmente si ottengono periodi senza decimali, ho usato lo stratagemma suggerito ma PerMax, di fare ripartire il registro di timer0 da una posizione diversa da zero. Ad esempio, se ottengo un periodo senza decimali dividendo per 250, mentre il prescaler consente solo il valore di 256, ad ogni interrupt da overflow, si fa ripartire il conteggio da 6, anziché da 0 (vedere mess precedenti). Anche se noto qualche imprecisione e dopo chiederò conferma a Max.
Così, se base-tempi=1mSec, il valore delle variabili T_xxx e M_xxx esprimono anch'esse i millisecondi.
Se qualcuno pensa che possa servire, come qualcuno ha aiutato me, io aiuto altri.
Ma veniamo ai problemi:
- non ho potuto scegliere FOSC ideale per EUSART ed ho un errore del 0,16% sul Baud-Rate Asincrono (9615 anziché 9600). Non mi rendo conto se questo possa portare problemi. Va comunque bene ?
- Quando ad ogni overflow di timer0 rimetto la partenza a 6, in realtà non mi "salta" un pò di più. Ho impostato tempi molto lunghi e sembra che ne salti quasi il doppio, ma SEMPRE UGUALI.
Non è un grande errore e posso tranquillamente accettarlo, ma mi riesce difficile pensare di aver colto in errore il PIC, ed è più facile che sia io in errore.
Ho letto sul testo "Step-by-step" di Mauro che c'è quel salto di 2 istruzioni dopo la scrittura del registro, ma non ho capito bene che ruolo possano avere nel mio caso. Inoltre, le istruzioni che dall'interrupt precedono la sincronizzazione del registro di timer0, sono almeno su 4-5 righe di programma, e alcune di queste obbligano a salti di allocazione, che immagino portino via ciascuna più di una istruzione. Simultaneamente, il clock di timer0 è già arrivato a 0 con l'overflow e continua ad avanzare alla velocità di FOSC/4. E' davvero impossibile sincronizzare meglio l'overflow e la ripartenza del registro da da posizione diversa da zero ?
Si prega Accedi o Crea un account a partecipare alla conversazione.
- MauroFx
- Autore della discussione
- Senior Member
- Messaggi: 40
- Ringraziamenti ricevuti 0
Registrati al sito
Accedi a tutte le risorse e articoli non visibili pubblicamente, puoi registrarti con pochi passi.