salve a tutti,
vi faccio una domanda particolare perché non mi era mai capiutata una cosa simile.
Sto lavorando su un AtTiny 817, configuro l'ADC come freerun mode e con le inteurrupt ad ogni conversione:funziona.
Apro un nuovo programma per provare la configurazione del timer che genera un interrupt quando va in overflow: funziona.
Metto tutto in un programma solo... l'ADC non genera più l'interrupt! mi basta commentare l'inizializzazione del timer per far funzionare l'adc.
Secondo voi dove può stare il problema?
Davide
ADC e TIMER che fanno a cazzotti
Moderatore:
Paolino
10 messaggi
• Pagina 1 di 1
1
voti
Impossibile dire nulla senza codice, non specifichi neanche quali timer usi e quale porta ADC e come viene programmato se direttamente in C o usi API particolari come quelle di Arduino o programmi direttamente in assembler o altro.
1
voti
Forse il timer si impadronisce dei registri di interrupt usati dall'ADC. Leggi bene il datasheet, alla sezioni interrupt, timer e ADC - a volte per risovere problemi simili sugli interrupt serve pure leggere qualcos'altro*. Sii puntiglioso!
*qualcos'altro potrebbero essere i registri che vanno a configurare come sono abilitati gli interrupt. Talvolta non sono descritti nella sezione degli interrupt.
*qualcos'altro potrebbero essere i registri che vanno a configurare come sono abilitati gli interrupt. Talvolta non sono descritti nella sezione degli interrupt.
I don't fight weather - Woodrow W. Smith
1
voti
Oppure, più semplicemente i timer sono programmati per avere un intervallo troppo ristretto e generano un proliferare di interrupt tale, che quelli dell'ADC, anche se presenti, vengono completamente ignorati.
-

harpefalcata
326 1 3 6 - Stabilizzato

- Messaggi: 422
- Iscritto il: 28 lug 2015, 21:03
0
voti
- Codice: Seleziona tutto
int8_t TIMER_0_init()
{
//TCA0.SINGLE.CMP0 = 0xffff; /* Compare Register 0: 0x0 */
// TCA0.SINGLE.CMP1 = 0x0; /* Compare Register 1: 0x0 */
// TCA0.SINGLE.CMP2 = 0x0; /* Compare Register 2: 0x0 */
TCA0.SINGLE.CNT = 0x0000; /* Count: 0xff */
TCA0.SINGLE.CTRLB = 0 << TCA_SINGLE_ALUPD_bp /* Auto Lock Update: disabled */
| 0 << TCA_SINGLE_CMP0EN_bp /* Compare 0 Enable: enabled */
| 0 << TCA_SINGLE_CMP1EN_bp /* Compare 1 Enable: disabled */
| 0 << TCA_SINGLE_CMP2EN_bp /* Compare 2 Enable: disabled */
| TCA_SINGLE_WGMODE_NORMAL_gc; /* */
// TCA0.SINGLE.CTRLC = 0 << TCA_SINGLE_CMP0OV_bp /* Compare 0 Waveform Output Value: disabled */
// | 0 << TCA_SINGLE_CMP1OV_bp /* Compare 1 Waveform Output Value: disabled */
// | 0 << TCA_SINGLE_CMP2OV_bp; /* Compare 2 Waveform Output Value: disabled */
TCA0.SINGLE.DBGCTRL = 1 << TCA_SINGLE_DBGRUN_bp; /* Debug Run: enabled */
// TCA0.SINGLE.EVCTRL = 0 << TCA_SINGLE_CNTEI_bp /* Count on Event Input: disabled */
// | TCA_SINGLE_EVACT_POSEDGE_gc; /* Count on positive edge event */
TCA0.SINGLE.INTCTRL = 0 << TCA_SINGLE_CMP0_bp /* Compare 0 Interrupt: enabled */
| 0 << TCA_SINGLE_CMP1_bp /* Compare 1 Interrupt: disabled */
| 0 << TCA_SINGLE_CMP2_bp /* Compare 2 Interrupt: disabled */
| 1 << TCA_SINGLE_OVF_bp; /* Overflow Interrupt: disabled */
//TCA0.SINGLE.INTFLAGS |= 1<<0;
TCA0.SINGLE.PER = 0x0f00; /* Period: 0xffff */
TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1024_gc /* System Clock / 1024 */
| 1 << TCA_SINGLE_ENABLE_bp; /* Module Enable: enabled */
return 0;
}
ho impostato così il timer A. Setto un valore in PER (period) che dovrebbe essere il massimo a cui arriva e poi si resetta generando un overflow interrupt.
Il codice di inizializzazione è generato da Atmel START che è una interfaccia grafica per impostare i parametri nei registri, sono comunque stati controllati e a me sembrano giusti.
Voi ci vedete qualcosa che non torna?
1
voti
mistero risolto!
ogni volta che viene generata un'interrupt, deve essere resettata a mano la flag. Pensavo che per l'overlow azzerandosi il timer si resettasse da solo ma a quanto pare no, nel capitolo dei timer non c'era scritto ma stava nel capitolo delle interrupt
se tutto va come deve settimana prossima potrebbe uscire un articoletto
ogni volta che viene generata un'interrupt, deve essere resettata a mano la flag. Pensavo che per l'overlow azzerandosi il timer si resettasse da solo ma a quanto pare no, nel capitolo dei timer non c'era scritto ma stava nel capitolo delle interrupt
se tutto va come deve settimana prossima potrebbe uscire un articoletto
0
voti
dadduni ha scritto:[..] nel capitolo dei timer non c'era scritto ma stava nel capitolo delle interrupt
Tipico!
I don't fight weather - Woodrow W. Smith
0
voti
ho aggiornamenti e mi servirebbero chiarimenti se potete!
questa è la funzione handler dell'interrupt dell'ADC
Scrivo in un buffer circolare, resetto la interrupt flag e faccio ripartire la nuova conversione. A voi sembra una routine troppo lunga? perché mi sono accorto che se la lascio così la interrupt del timer non viene proprio eseguita invece se tolgo i comandi che scrivono nel buffer il timer funziona perfettamente. Voi che ne pensate? pensavo di poter scrivere in un paio di registri in una interrupt!
PS non ha senso però che nella routine faccio alzare un bit che segnala la fine della conversione perché poi dovrei fare polling nel main a questo punto tanto vale la pena fare direttamente polling e questa interrupt non generarla nemmeno!
questa è la funzione handler dell'interrupt dell'ADC
- Codice: Seleziona tutto
ISR(ADC0_RESRDY_vect)
{ rms_buffer[rms_buffer_pointer]= ADC0.RES;
rms_buffer_pointer++;
/* The interrupt flag has to be cleared manually */
ADC0.INTFLAGS = ADC_RESRDY_bm;
ADC0.COMMAND=1;
}
Scrivo in un buffer circolare, resetto la interrupt flag e faccio ripartire la nuova conversione. A voi sembra una routine troppo lunga? perché mi sono accorto che se la lascio così la interrupt del timer non viene proprio eseguita invece se tolgo i comandi che scrivono nel buffer il timer funziona perfettamente. Voi che ne pensate? pensavo di poter scrivere in un paio di registri in una interrupt!
PS non ha senso però che nella routine faccio alzare un bit che segnala la fine della conversione perché poi dovrei fare polling nel main a questo punto tanto vale la pena fare direttamente polling e questa interrupt non generarla nemmeno!
1
voti
Quello non è un buffer circolare. Manca il controllo del limite massimo nell'indice e molto probabilmente hai un buffer overflow con conseguenze deleterie nel codice. Devi mettere un test sull'indice, se raggiunge il massimo azzerarlo.
Un trucco per evitare il test è creare il buffer con un numero di elementi uguale a una potenza di 2, quando incrementi l'indice fai un "and" binario (&) col numero numero di elementi meno 1. Ad esempio se il buffer ha 16 (
) elementi, quando incrementi l'indice fai:
Un trucco per evitare il test è creare il buffer con un numero di elementi uguale a una potenza di 2, quando incrementi l'indice fai un "and" binario (&) col numero numero di elementi meno 1. Ad esempio se il buffer ha 16 (
) elementi, quando incrementi l'indice fai:- Codice: Seleziona tutto
rms_buffer_pointer = (rms_buffer_pointer + 1) & 0x0F
10 messaggi
• Pagina 1 di 1
Torna a Firmware e programmazione
Chi c’è in linea
Visitano il forum: Nessuno e 5 ospiti

Elettrotecnica e non solo (admin)
Un gatto tra gli elettroni (IsidoroKZ)
Esperienza e simulazioni (g.schgor)
Moleskine di un idraulico (RenzoDF)
Il Blog di ElectroYou (webmaster)
Idee microcontrollate (TardoFreak)
PICcoli grandi PICMicro (Paolino)
Il blog elettrico di carloc (carloc)
DirtEYblooog (dirtydeeds)
Di tutto... un po' (jordan20)
AK47 (lillo)
Esperienze elettroniche (marco438)
Telecomunicazioni musicali (clavicordo)
Automazione ed Elettronica (gustavo)
Direttive per la sicurezza (ErnestoCappelletti)
EYnfo dall'Alaska (mir)
Apriamo il quadro! (attilio)
H7-25 (asdf)
Passione Elettrica (massimob)
Elettroni a spasso (guidob)
Bloguerra (guerra)





