Hallo liebe Forengemeinde,
ich schreibe gerade ein Programm, welches eine LCD Menüanzeige ausgibt
auf der Sensordaten (die Sensorinfos werden regelmäßig über Interrupts
ausgelesen) ausgegeben werden. Der jeweilige LCD Anzeigetext wurde per
Image2GLCD Konverter umgewandelt und in das Programm integriert. Die
einzelnen Menüpunkte werden per Taster umgeschalten und auch bestätigt.
Aufgrund der Menge an Anschlüssen die ich für dies und das benötige,
muss ich die Taster auf die PINS PD2-PD4 am ATMEGA32 hängen. Dummerweise
sind am PIN PD2 und PD3 die INT0 und INT1 Eingänge, so dass der µC mir
bei Betätigung des Tasters einen Reset macht. (INT0 und INT1 besitzen
keine ISRs). Das ganze Programm anzuhängen würde den Rahmen sprengen,
aus diesem Grund lediglich den Main.c Teil sowie die ISR des
Temperaturauslesens. Ich hoffe das genügt und mir kann jemand einen
sinnvollen Hinweis geben, wie ich es schaffe das er bei Betätigung des
PD2 und PD3 nicht resettet, sondern die entsprechende Entprellfunktion
ausführt. Einen CLI() Befehl kann ich schlecht einsetzen, bzw. wüsste
ich nicht wo dies sinnvoll ist, da er mir die Tasterabfrage per for(;;)
durchführt.
Achja und eine Bitte noch. Nachdem es vielleicht sein kann, das andere
irgendwann einmal das gleiche dumme Schicksal ereignet sollte sich die
Diskussion hier aufs Fachliche beschränken. Unnütze Kommentare können
wenn als nötig erachtet gerne per PN gesendet werden.
Nachdem mir hier bisher immer geholfen wurde, bin ich guter Dinge das
dies auch diesesmal so ist. Vielen Dank schonmal.
Gruß
Der Alex
1
//Main.c
2
intmain(void)
3
{
4
5
//Definieren der Taster Eingangsports
6
PORTD=0b00011100;// Pullup Widerstand für Taster einschalten
7
DDRD=0b00100000;//Pin D5 als PWM Ausgang, Pin D2,D3,D4 als Eingänge für Taster
8
9
10
//lokale Variablen
11
uint16_ttemp_1,temp_2,temp_3;
12
uint16_tPWM_Prozent_neu;
13
14
uint8_ti=0;
15
uchars[30];//Variable Temperaturwert
16
ucharZahl;//Variable RomCode Wert 1-Wire
17
uchars_1[31];//Variable Temperaturwert 1
18
uchars_2[31];//Variable Temperaturwert 2
19
uchars_3[31];//Variable Temperaturwert 3
20
ucharstring[31];
21
22
//LCD initialisieren
23
lcd_init();
24
uart_init();
25
lcd_clear();
26
//Interrupt für Tasterentprellung wird eingeschalten
27
TCCR0=(1<<CS02)|(1<<CS00);// divide by 1024 from prescaler
28
TIMSK|=(1<<TOIE0);// enable timer interrupt
29
TIMSK|=(1<<TICIE1);
30
31
32
33
//Interrupt für Ausführung Temperaturmessung und GPS-Datenaufnahme
34
TCCR2=(1<<WGM21)|(1<<CS22)|(1<<CS21);// divide by 1024 from prescaler
Editiere Dein Post und benutze die Formatierung!
Warum liest Du nicht die Postingregeln?
Alexander Pl schrieb:> INT0 und INT1 besitzen> keine ISRs
Dann gibt man sie auch nicht frei.
Alexander Pl schrieb:> Das ganze Programm anzuhängen würde den Rahmen sprengen
Dann reduziere es soweit, daß der Fehler noch auftritt und prüfe es vor
dem Posten!
In dem Programmgeschnipsel erkennt man nix.
Warum sind INT0 / 1, aktiviert, wenn sie nicht gebraucht werden?
Wenn sie denn aktiviert sind, kann man eine ISR schreiben,
die nix tut und sofort zurückkommt.
Kein einziger Interrupt eines AVR aktiviert sich automatisch. Solange du
keinen aktivierst, sind die inaktiv. Ergo brauchst du nichts zu
deaktivieren.
Der Fehler liegt woanders...
Oliver
Guten Morgen,
okay ich muss zugeben, dass dies doch sehr unübersichtlich war, was ich
geschickt habe. Sah aufn ersten Blick garnicht so schlimm aus. Schande
auf mein Haupt.Ich gelobe Besserung.
Ich hab den Code nun gekürzt, die ganzen LCD Routinen rausgeschmissen
und das Ganze nun per LED Kombination getestet. Die Invertierung beim
PORTD ist STK 500 bedingt.
Das für mich eigenartige ist, dass wenn ich den Interrupt Timer 0
beschriebenen Teil auskommentiere alles sehr sauber läuft wie es soll,
sobald ich diesen mit aufnehme startet das Programm ständig von vorne.
Die gleiche Situation erlebe ich im eigentlichen Programm bei
Tasterdruck der Taste PD2,PD3(INT0,INT1).
Auch wenn der Fehler nicht identisch ist, so hoffe ich über die Lösung
dieses Problems meinen eigentlichen Fehler zu finden. Würde mich freuen,
wenn mir jemand auf die Sprünge helfen könnte. Vielen Dank.
Ich seheh schon mal, das du Timer 0 auch mit Interrupt initialisierst,
aber nicht behandelst. Das reicht schon aus, um den AVR regelmässig
zurückzusetzen.
Denke dran, für jeden freigegebenen Interrupt musst du auch eine ISR
vorhalten, sonst rennt der MC immer wieder in den Default Handler - und
das ist nun mal der Resetvektor.
Guten morgen,
Du hast bei Dir im Code ein delay mit 35 und 50 gesetzt.
In diesem Moment macht die CPU GARNICHTS auser warten, warten und
nochmals warten. Für den Fall eines Interrupts wird keiner ausgelöst.
Da du aber mit Interrrupts arbeitest, wie mit den Timer_2 interrupt, so
würde ich an deiner Stelle eher eine For- Schleife machen, und über i=1
bis i=50 ein delay von 1ms ausführen lassen.
Ist zwar auch immerhin 1*10^-3s aber wenigstens kann danach noch ein
Interrupt kommen, der Prozessor wird nur nach einer ms blockiert.
mit einen delay ist es wie gesagt, komplett für 50 Ms gesperrt, und es
geht mal dann garnichts außer warten.
Ansonsten, wie bereits die Forumskollegen erwähnt haben, arbeitest Du
NICHT mit einen Interrupt, aktivier ihn nicht, und er bleibt aus.
Nur wenn du einen Interrupt brauchst, aktiviere ihn.
Mfg,
tommyProg
Hinzufügen möchte ich gerne die Frage, warum du einen festen Wert ins
TCNT2, also in das Zählregister des Timers schreibst?
Laut meines Lesens von einen ATmega8 Datenblattes hat das schlechte
Konsequenzen auf das Interruptverhalten des Timers.
Mfg,
tommyProg
Tho Wes schrieb:> In diesem Moment macht die CPU GARNICHTS auser warten, warten und> nochmals warten. Für den Fall eines Interrupts wird keiner ausgelöst.
Das ist ein Irrtum. Die _delay_ms() und _delay_us() Routinen sperren
keine Interrupts und sind unterbrechbar.
Matthias Sch. schrieb:> Tho Wes schrieb:>> In diesem Moment macht die CPU GARNICHTS auser warten, warten und>> nochmals warten. Für den Fall eines Interrupts wird keiner ausgelöst.>> Das ist ein Irrtum. Die _delay_ms() und _delay_us() Routinen sperren> keine Interrupts und sind unterbrechbar.
Ach du meine Güte. Bist Du dir da zu 100% sicher? Wenn ja, bedanke ich
mich für die Wissenskorrektur
Tho Wes schrieb:> Du hast bei Dir im Code ein delay mit 35 und 50 gesetzt.> In diesem Moment macht die CPU GARNICHTS auser warten, warten und> nochmals warten. Für den Fall eines Interrupts wird keiner ausgelöst.
Das ist Unsinn. Natürlich ist ein delay von einem Interrupt
unterbrechbar.
Tho Wes schrieb:> Ja, Franky, ist ja schon gut, ich wurde bereits freundlich darauf> hingewiesen, dann musst du es nichtmehr tun.
Sorry, war mit dem Durchlesen des Threads noch nicht ganz durch, sonst
hätte ich es mir verkniffen. Aber solche Aussagen kann man einfach nicht
stehenlassen, sonst glaubt da noch einer dran.
Ehrlich gesagt, ich wundere mich ein wenig... für jemanden mit angeblich
20 Jahren Berufserfahrung hast Du erschreckend wenig Ahnung.
> Sorry, war mit dem Durchlesen des Threads noch nicht ganz durch, sonst> hätte ich es mir verkniffen. Aber solche Aussagen kann man einfach nicht> stehenlassen, sonst glaubt da noch einer dran.>> Ehrlich gesagt, ich wundere mich ein wenig... für jemanden mit angeblich> 20 Jahren Berufserfahrung hast Du erschreckend wenig Ahnung.
Entschuldigung angenommen, Franky. Nein, das stimmt, da hast du recht.
Kannst mir bitte den Link schicken, wo das mit 20 Jahren Berufserfahrung
steht (und ernst gemeint ist)?
Mfg,
tommyProg
Tho Wes schrieb:> Kannst mir bitte den Link schicken, wo das mit 20 Jahren Berufserfahrung> steht (und ernst gemeint ist)?Beitrag "Re: Mikrocontroller Aufgabe"
Aber lass uns hier keine alten Kamellen auspacken ;-)
Frank M. schrieb:> Tho Wes schrieb:>> Kannst mir bitte den Link schicken, wo das mit 20 Jahren Berufserfahrung>> steht (und ernst gemeint ist)?>> Beitrag "Re: Mikrocontroller Aufgabe">> Aber lass uns hier keine alten Kamellen auspacken ;-)
Achso^^. Dachte schon, ich hätte geschrieben, dass ich selber 20 Jahre
Berufserfahrung hätte xD
Es freut mich das mir so viele Leute versuchen zu helfen und auch das
mein Beitrag zum illusteren Small-Talk einlädt.
Danke Matthias für den Tipp. Nach Einarbeitung der anderen ISR
funktioniert die ganze Schoße wie sie soll, nur leider nicht im Original
Programm. Ich sehe das so (bitte korrigiert mich falls ich falsch
liege): Nachdem die Timer0 und 2 Interrupts entsprechende ISRs besitzen
und Timer1 keinen Interrupt hat und somit keine ISR braucht passt das
eigentlich. Komischerweise wird im eigentlichen Programm bei aufruf der
Entprellfunktion der Reset ausgelöst. Vielleicht sollte ich die
Entprellfunktion komplett entfernen und das Ganze mit delay Zeiten
lösen, wobei mir diese Funktion wirklich sehr gut gefällt.
Hat zufällig noch jemand einen Ansatz woran es liegen kann?
Grüße
Alex
> uint16_t z;
Wenn du diese Variable global halten willst, sollte auch sie 'volatile'
erklärt werden. Das liegt u.a. daran, das der Kompiler ISR als nicht
angesprungene Programmteile erkennt und somit erstmal alle Dinge, die
sich darauf beziehen, wegoptimieren will. Genauer kann dir das z.B.
Karl-Heinz erklären.
Der m.E. elegantere Weg ist es, z einfach als static zu erklären, und
sie in die ISR mit reinzunehmen:
1
ISR(TIMER2_COMP_vect)
2
{
3
staticuint16_tz;
4
z++;
5
if(z==1024)//30 entspricht ca 1 Sekunde
6
{
7
PORTD^=(1<<PD5);//PIN D1 wird getoggelt um Interruptausführung zu sehen
8
z=0;
9
10
}
11
OCR1A=z;
12
}
Das ist aber Geschmackssache. Manche Leute meckern über viele globale
Variablen, ist aber bei einem MC eigentlich wurscht.
Aber hauptsächlich hast du bei PeDas ISR die Hälfte vergessen, die geht
noch weiter:
1
ISR(TIMER0_OVF_vect)// every 10ms
2
{
3
staticuint8_tct0,ct1,rpt;
4
uint8_ti;
5
6
TCNT0=(uint8_t)(int16_t)-(F_CPU/1024*10e-3+0.5);// preload for 10ms
7
8
i=key_state^~KEY_PIN;// key changed ?
9
ct0=~(ct0&i);// reset or count ct0
10
ct1=ct0^(ct1&i);// reset or count ct1
11
i&=ct0&ct1;// count until roll over ?
12
key_state^=i;// then toggle debounced state
13
key_press|=key_state&i;// 0->1: key press detect
14
15
if((key_state&REPEAT_MASK)==0)// check repeat function
16
rpt=REPEAT_START;// start delay
17
if(--rpt==0){
18
rpt=REPEAT_NEXT;// repeat delay
19
key_rpt|=key_state&REPEAT_MASK;
20
}
21
}
Du musst allerdings vorher mindestens noch KEY_MASK deklarieren, KEY_PIN
hast da ja hardkodiert.
Alexander Pl schrieb:> Nach Einarbeitung der anderen ISR> funktioniert die ganze Schoße wie sie soll, nur leider nicht im Original> Programm.
Wer oder was ist jetzt das Originalprogramm?
Das aus dem Eröffnungposting, oder das zuletzt gepostete?
> Ich sehe das so (bitte korrigiert mich falls ich falsch> liege): Nachdem die Timer0 und 2 Interrupts entsprechende ISRs besitzen> und Timer1 keinen Interrupt hat und somit keine ISR braucht passt das> eigentlich.
Exakt.
> Komischerweise wird im eigentlichen Programm bei aufruf der> Entprellfunktion der Reset ausgelöst.
Ich geh mal davon aus, dass das 'eigentlichen Programm' im wesentlichen
das aus dem Eröffnungsposting ist, in das du noch die Tastenbehandlung
eingebaut hast.
Da ist noch ein Fehler drinn
1
TIMSK|=(1<<OCIE2);
2
3
4
...
5
6
ISR(TIMER2_OVF_vect)
7
8
...
Output Compare INterrupt ist nicht dasselbe wie Overflow Interrupt.
-> Reset
> Vielleicht sollte ich die> Entprellfunktion komplett entfernen
Die PeDa Funktionalität funktioniert super. Wenn in deinem Programm was
abschmiert, dann ist das so ziemlich die einzige Stelle (wenn du den
Code korrekt Copy&Paste übernommen hast), an der du nicht suchen
brauchst.
Karl Heinz schrieb:> Die PeDa Funktionalität funktioniert super. Wenn in deinem Programm was> abschmiert, dann ist das so ziemlich die einzige Stelle (wenn du den> Code korrekt Copy&Paste übernommen hast), an der du nicht suchen> brauchst.
PS: Wenn du keinen Autorepeat brauchst, dann kannst du natürlich den
ganzen Teil bzgl. key_rpt aus der ISR raus lassen. Aber dann solltest du
auch die Variable key_rpt komplett entfernen und auch die 'short'
Funktion nicht mehr benutzen. Die einzige Funktion, die du noch brauchst
ist get_key_press.
Hammer!
Es geht. Endlich keinen Reset mehr. Die ausschlaggebende Änderung war
den ISR Timer 2 in Compare umzuschreiben. Was mich nur wirklich
verwundert ist die Tatsache das ich, obwohl ich wirklich mehrmals Zeile
für Zeile durchgegangen bin, dies nicht gesehen habe.
Vielen Dank kbuchegg und allen die sich die Mühe gemacht haben mir
helfen zu wollen.
Dieses Forum hier ist wirklich Oberklasse und so macht es auch Spaß sich
mit der manchmal nicht ganz leichten Materie zu beschäftigen und
dazuzulernen.