Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Interrupt con AtMega16

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] Interrupt con AtMega16

Messaggioda Foto UtenteEliseoMy » 17 mag 2012, 13:50

Ciao ragazzi.

Sono disperato...ho fatto

un piccolo e semplice firmware per la gestione di alcune sonde pt100 e alcuni consensi dei relè e roba simile, il tutto visualizzato su display LCD.

La gestione del tutto è affidata al microcontrollore atMega16.

Ora il problema è che volevo gestire un semplice orologio che mi serve per alcuni parametri, ma nonostante utilizzi sempre il solito sistema di interrupt sul timer1, stavolta non riesco a farlo funzionare.

Ogni volta che interviene l'interrupt, mi si resetta il micro.

Allora ho rifatto il programma solo per gestire l'interrupt, ma nulla da fare, si resetta ad ogni interrogazione.

Dove sbaglio?? qualcuno sa aiutarmi??

Posto il programma timer1.

Codice: Seleziona tutto
// Target : M16
// Crystal: 8.0000Mhz
#include <iom16v.h>
#include <macros.h>

char secondi=0;

void port_init(void)
{ PORTA = 0xF0;
DDRA  = 0xF0;
PORTB = 0xFF;
DDRB  = 0xFF;
PORTC = 0xF0;
DDRC  = 0xF0;
PORTD = 0x0B;
DDRD  = 0x0B;
}
//Watchdog initialisation
// prescale: 1024K cycles
void watchdog_init(void)
{ WDR();
WDTCR = 0x0E;
}
//TIMER1 initialisation - prescale:1024
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 1Sec
// actual value:  1,000Sec (0,0%)
void timer1_init(void)
{ TCCR1B = 0x00;
TCNT1H = 0xE1;
TCNT1L = 0x7C;
OCR1AH = 0x1E;
OCR1AL = 0x84;
OCR1BH = 0x1E;
OCR1BL = 0x84;
ICR1H  = 0x1E;
ICR1L  = 0x84;
TCCR1A = 0xC0;
TCCR1B = 0x05; //start Timer
}
void init_devices(void)
{ CLI();
port_init();
watchdog_init();
timer1_init();
MCUCR = 0x00;
GICR  = 0x00;
TIMSK = 0x10;
SEI();
}

//void main(void)
{ init_devices();
while (1)
    WDR();
//if (TCNT1==OCR1A)
//secondi++;       
//TCNT1H = 0xE1;
//TCNT1L = 0x7C;}
//if ((secondi%2)==0)   
//PORTC=PORTC|0x80;//spegni disp
//else 
//PORTC=PORTC&0x7f;//accendi disp
//}
}

#pragma interrupt_handler timer1_compa_isr:7
void timer1_compa_isr(void)
{
secondi++;
if (secondi%2)
PORTC=PORTC|0x80;//spegni disp
else
PORTC=PORTC&0x7f;//accendi disp
}


Come si vede, nel main ho commentato delle righe di codice, che sono quelle gestite dall'interrupt, infatti se lo disabilito e utilizzo quelle righe di codice, la frequenza sul pin7 della porta C è perfetto ad 1 secondo.

GRAZIE
Avatar utente
Foto UtenteEliseoMy
0 2
 
Messaggi: 13
Iscritto il: 16 mag 2012, 19:09

0
voti

[2] Re: Interrupt con AtMega16

Messaggioda Foto Utentesimo85 » 18 mag 2012, 8:25

Per caso hai abilitato il WTD? Se si disabilitalo.
Avatar utente
Foto Utentesimo85
30,8k 7 12 13
Disattivato su sua richiesta
 
Messaggi: 9930
Iscritto il: 30 ago 2010, 4:59

0
voti

[3] Re: Interrupt con AtMega16

Messaggioda Foto UtenteEliseoMy » 18 mag 2012, 8:37

WTD??....cosa intendi il watch dog??...anche disabilitandolo non cambia nulla.
E' proprio alla interrogazione dell'interrupt, anche cambiando il tempo del timer, si allunga o accorcia il reset, esattamente con la frequenza del timer impostata. (misurata con oscilloscopio)
Avatar utente
Foto UtenteEliseoMy
0 2
 
Messaggi: 13
Iscritto il: 16 mag 2012, 19:09

0
voti

[4] Re: Interrupt con AtMega16

Messaggioda Foto Utentesimo85 » 18 mag 2012, 8:47

Riesci ad interpretare il tuo stesso codice?
Avatar utente
Foto Utentesimo85
30,8k 7 12 13
Disattivato su sua richiesta
 
Messaggi: 9930
Iscritto il: 30 ago 2010, 4:59

0
voti

[5] Re: Interrupt con AtMega16

Messaggioda Foto UtenteEliseoMy » 18 mag 2012, 8:53

Certo che lo interpreto....ma il problema non è il watch dog, già provato a disabilitarlo
Avatar utente
Foto UtenteEliseoMy
0 2
 
Messaggi: 13
Iscritto il: 16 mag 2012, 19:09

0
voti

[6] Re: Interrupt con AtMega16

Messaggioda Foto Utentesimo85 » 18 mag 2012, 9:06

Stando al tuo codice, questo richiama la funzione WDR() all'infinito.. Perché? Quello che hai commentato non veniva ugualmente mai eseguito, o così sembra..
Detto questo la logica del firmware, a prima impressione, non mi sembra corretta.

Non sono un indovino ma secondo me WDR sta per Watch Dog Reset, giusto? Se lo disabiliti che senso ha resettarlo?
Avatar utente
Foto Utentesimo85
30,8k 7 12 13
Disattivato su sua richiesta
 
Messaggi: 9930
Iscritto il: 30 ago 2010, 4:59

0
voti

[7] Re: Interrupt con AtMega16

Messaggioda Foto UtenteEliseoMy » 18 mag 2012, 9:19

Allora:
1)Il ciclo infinito while(1) continua a resettare il Watch dog, altrimenti al termine del suo conteggio si resetta il micro, poiché, come si vede dal codice, il wacth dog è abilitato.
Dalla tua prima risposta, mi indicavi il problema del continuo reset sul watch dog, ma quello non è, perché anche disabilitandolo, e quindi cambiando il codice con
while(1);
il mio problema non si risolve.
2)le frasi commentate nel main, non vengono MAI eseguite, ma le ho postate comunque, perché sono gli stessi comandi che dovrebbe fare l'interrupt, solo che se inseriti nel main (togliendo il commento) il sistema funziona con la frequenza desiderata, senza alcun reset, il che significa che il reset che si autogenera non è provocato dalle righe stesse di codice.
3)Il vero principio del firmware è: non fare nulla.....attiva e disattiva l'uscita solo se si presenta l'intrerrupt di comparazione timer1. Il problema però è che ogni qual volta entra in interrupt, mi resetta il micro.
Sembra quasi che l'indirizzo dello stack si cancelli e non riprenda il programma da dove era stato lasciato
Avatar utente
Foto UtenteEliseoMy
0 2
 
Messaggi: 13
Iscritto il: 16 mag 2012, 19:09

0
voti

[8] Re: Interrupt con AtMega16

Messaggioda Foto Utentesimo85 » 18 mag 2012, 12:09

EliseoMy ha scritto:1)Il ciclo infinito while(1) continua a resettare il Watch dog, [...] ma quello non è, perché anche disabilitandolo [...] il mio problema non si risolve.

Allora non usare il WTD..

2)le frasi commentate nel main [...] sono gli stessi comandi che dovrebbe fare l'interrupt, solo che se inseriti nel main [...] il sistema funziona con la frequenza desiderata.
[...]
Sembra quasi che l'indirizzo dello stack si cancelli e non riprenda il programma da dove era stato lasciato


A quale documento o microcontrollore si fa riferimento? A questo? Quale compilatore o IDE usi? Si sa poco o niente di come stai lavorando. :(

Il tuo main deve essere qualcosa del genere:
Codice: Seleziona tutto
void main(void)
{
   while(1)
   {
      if((secondi % 2) == 0)
         PORTC |= 0x80;
      else
         PORTC &= 0x7f;
   }
}

E nell'interrupt incrementi solo i secondi.
Avatar utente
Foto Utentesimo85
30,8k 7 12 13
Disattivato su sua richiesta
 
Messaggi: 9930
Iscritto il: 30 ago 2010, 4:59

0
voti

[9] Re: Interrupt con AtMega16

Messaggioda Foto UtenteEliseoMy » 18 mag 2012, 12:34

Utilizzo ICC AVR della ImageCraft, il microcontrollore è un ATmega16 della Atmel, quello che hai postato col datasheet.
Il firmware è molto più complesso, ma visto che si trattava di un problema sull'interrupt, ho fatto un programmino di 3 righe per vedere e capire dov'è il problema.
Come si fa a gestire l'interruput??
Comunque ho rifatto il codice, ma non funziona.

Codice: Seleziona tutto
#include <iom16v.h>
#include <macros.h>
char secondi=0;
void port_init(void)
{
PORTA = 0xF0;
DDRA  = 0xF0;
PORTB = 0xFF;
DDRB  = 0xFF;
PORTC = 0xF0; //m103 output only
DDRC  = 0xF0;
PORTD = 0x0B;
DDRD  = 0x0B;
}
//TIMER1 initialisation - prescale:1024
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 1Sec
// actual value:  1,000Sec (0,0%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0xE1; //setup
TCNT1L = 0x7C;
OCR1AH = 0x1E;
OCR1AL = 0x84;
ICR1H  = 0x1E;
ICR1L  = 0x84;
TCCR1A = 0xC0;
TCCR1B = 0x05;
}
void init_devices(void)
{CLI();
port_init();
timer1_init();
MCUCR = 0x00;
GICR  = 0x00;
TIMSK = 0x10;
SEI();
}
void main(void)
{
init_devices();
while (1)
{if (secondi%2)
    PORTC=PORTC|0x80;//spegni disp
  else
    PORTC=PORTC&0x7f;//accendi disp
}
}//main
#pragma interrupt_handler timer1_compa_isr:7
void timer1_compa_isr(void)
{ secondi++;
}
Avatar utente
Foto UtenteEliseoMy
0 2
 
Messaggi: 13
Iscritto il: 16 mag 2012, 19:09

0
voti

[10] Re: Interrupt con AtMega16

Messaggioda Foto Utentedursino » 6 giu 2012, 12:56

Sai, potresti provare il programma che resetta sempre e aggiungere all'inizio una routine che si salva il registro di reset dell'atmega.
E' un registro dove si setta un bit opportuno a seconda della causa di reset.

Se questo sarà tutto nullo, allora il problema è solo software (stack Overflow?).

Ciao
Avatar utente
Foto Utentedursino
255 1 5 5
Expert
Expert
 
Messaggi: 522
Iscritto il: 8 mar 2009, 13:24


Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 3 ospiti