Liebes Forum!
Bei unserem Projekt gibt es ein Problem mit dem externen Interrupt Int0.
Wir verwenden einen ATmega16.
Der Interrupt ist ziemlich sicher richtig initialisiert worden und
funktioniert teilweise auch.
Das Problem: Der Code, welcher nach dem sei() Makro steht wird nicht
richtig oder garnicht ausgeführt.
Das Programm schaut wie folgt aus:
1
voidinit(void)
2
{
3
DDRA=0x00;//set PORTA as input
4
PORTA=0xFF;//pull-widerstände
5
DDRD=_BV(PD5)|_BV(PD4);// set OC1A/B pin as output, required for output
6
DDRB=_BV(PB3);// set OC0 pin as output
7
8
TCCR1A=_BV(WGM10)|_BV(COM1A1)|_BV(COM1B1);// clear timer/counter on compareAB match, phase correct pwm
9
TCCR1B=_BV(CS10);// no prescaler
10
11
TCCR0=_BV(WGM00)|_BV(COM01)|_BV(CS00);//no prescaler, set/clear on compare match (OCR0)
12
13
TIMSK=_BV(OCIE0)|_BV(OCIE1A)|_BV(OCIE1B);//enable interrupt on compare match timer0,1ab
14
15
MCUCR=_BV(ISC01)|_BV(ISC00);//generates interrupt on INT0 on falling edge
>> wie kann ein uint8_t jemals den Endwert 1000 erreichen? Der geht doch> nur bis 255!
Was soll der Quatsch eigentlich?
Selbst wen du das dann richtig stellst, optimiert es der Compiler wieder
raus.
Wenn du Wartezeiten willst, dann nimm fürs erste _delay_ms bis du
gelernt hast, wie man mit einem Timer längere Wartezeiten realisiert.
> Das Problem: Der Code, welcher nach dem sei() Makro steht wird nicht> richtig oder garnicht ausgeführt.
Interrupts einschalten ohne die passenden ISRs ist.. ähm.. 'ungünstigt'.
Oder enthältst Du uns reichlich relevanten Code vor? Und was heisst
'nicht richtig'?
doca schrieb:> Das Problem: Der Code, welcher nach dem sei() Makro steht wird nicht> richtig oder garnicht ausgeführt.
Und du willst uns testen, ob wir rausfinden, was der Code machen soll
und was falsch läuft und dir auch noch des Problem nennen?
doca schrieb:> Der Interrupt ist ziemlich sicher richtig initialisiert worden und> funktioniert teilweise auch.
kann man schlecht sagen. Du zeigst ja die ISR nicht.
doca schrieb:> Danke für die schnelle Antwort.> Leider immer noch der gleiche Fehler.
Zeig alles. Und zwar so, wie es jetzt aussieht.
Und auch nicht uninteressant: was ist eigentlich der Fehler?
"Code wird nicht richtig ausgeführt" ist keine Fehlerbeschreibung. Was
passiert? Was sollte deiner Meinung nach passieren?
Es ist ja nicht so, dass wir hinter dir sitzen würden und dir über die
Schulter schauen können. Oder gehst du zum Arzt und sagst "Es tut weh.
Mach mal."
Die ISR schaut wie folgt aus:
ISR (INT0_vect)
{
_delay_ms(2000);
}
(Kann also eigentlich nicht viel falsch an der ISR sein, oder?)
Der Code soll mit einer PWM eine LED heller und wieder dunkler machen.
(Das funktioniert auch einwandfrei solang man das sei() Makro nicht
verwendet.)
Karl Heinz schrieb:> Was soll der Quatsch eigentlich?> Selbst wen du das dann richtig stellst, optimiert es der Compiler wieder> raus.
Nein, das darf er nicht, weil das eine Endlosschleife ist. Gcc macht das
auch richtig offensichtlich wenn die Optimierungen an sind:
1
$ cat main.c
2
#include <inttypes.h>
3
4
int main(void)
5
{
6
for (uint8_t x = 0; x < 1000; x++)
7
{}
8
9
return 0;
10
}
11
12
$ gcc -Wall -Wextra -O3 -std=c99 -g -o main main.c
13
main.c: In function ‘main’:
14
main.c:5:24: warning: comparison is always true due to limited range of data type [-Wtype-limits]
doca schrieb:> Danke für die schnelle Antwort.> Leider immer noch der gleiche Fehler.
Poste den gesamten Code oder troll dich woanders.
WAS hast du denn jetzt geandert?
Wir koennen nicht in deinen PC, deinen Code, deine Toolchain, geschweige
denn in deinen Kopf gucken um zu sehen, was wo falsch laeuft...
Also: Wie bitte sollen wir dir helfen? Erklaer mal...
Sorry, aber sowas kotzt mich echt an... >:[
g457 schrieb:> Karl Heinz schrieb:>> Was soll der Quatsch eigentlich?>> Selbst wen du das dann richtig stellst, optimiert es der Compiler wieder>> raus.>> Nein, das darf er nicht, weil das eine Endlosschleife ist. Gcc macht das> auch richtig offensichtlich wenn die Optimierungen an sind:
Was für einen Unsinn erzählst du uns hier jetzt?
Aber immerhin lieferst du den Nachweis, dass es wegoptimiert wird,
gleich mit.
Irgendwie sinnfrei, oder?
mfg.
doca schrieb:> Die ISR schaut wie folgt aus:>> ISR (INT0_vect)> {> _delay_ms(2000);> }>> (Kann also eigentlich nicht viel falsch an der ISR sein, oder?)
Naja, da ist genau eine Zeile drin, und die ist verheerend. Sie führt
dazu, daß immer beim Auftreten des INT0 der µC erstmal für zwei Sekunden
komplett blockiert wird. Wozu sollte dieses Delay denn gut sein?
g457 schrieb:> Karl Heinz schrieb:>> Was soll der Quatsch eigentlich?>> Selbst wen du das dann richtig stellst, optimiert es der Compiler wieder>> raus.>> Nein, das darf er nicht, weil das eine Endlosschleife ist.
Ich sagte doch: Selbst wenn du das dann richtig stellst.
Annahme: Er hat den Code im Datentyp korrigiert.
Folgerung: Der Compiler wirft die Schleife dann (nach Korrektur) raus.
doca schrieb:> Der gesamte Code schaut wie folgt aus(entschuldigt die lückenhafte> Auskunft):
Und wo sind die restlichen ISR?
> TIMSK = _BV(OCIE0) | _BV(OCIE1A) | _BV(OCIE1B); //enable interrupt on> compare match timer0,1ab
du musst für JEDEN Interrupt, den du frei gibst, eine ISR schreiben!
Ergo: gib keinen Interrupt frei, den du nicht brauchst,
Karl Heinz schrieb:> doca schrieb:>> Der gesamte Code schaut wie folgt aus(entschuldigt die lückenhafte>> Auskunft):>> Und wo sind die restlichen ISR?>>> TIMSK = _BV(OCIE0) | _BV(OCIE1A) | _BV(OCIE1B); //enable interrupt on>> compare match timer0,1ab>> du musst für JEDEN Interrupt, den du frei gibst, eine ISR schreiben!>> Ergo: gib keinen Interrupt frei, den du nicht brauchst,
Toter Code ist schlechter Code! Danke für den Hinweis, das hab ich
komplett übersehen. Der Timer Interrupt wird garnicht verwendet. Vielen
Dank!
doca schrieb:> Toter Code ist schlechter Code! Danke für den Hinweis, das hab ich> komplett übersehen. Der Timer Interrupt wird garnicht verwendet. Vielen> Dank!
Es wird auch scheinbar der Timer 1 gar nicht (richtig) verwendet. Und
was du mit dem externen Interrupt bezweckst, will ich glaub ich gar
nicht wissen.
Irgendwie nicht nachvollziehbar, ein Programm, das in der Hauptschleife
laeuft, mit einem (vermutlich) Taster fuer 2 Sekunden zu blockieren und
sonst nichts damit zu machen. Versteh ich nicht.
wendelsberg
doca schrieb:>> Ergo: gib keinen Interrupt frei, den du nicht brauchst,>> Toter Code ist schlechter Code!
Es geht nicht nur darum, toten Code zu vermeiden. Wenn ein Interrupt
ausgelöst wird, für den du keine ISR definiert hast, wird das Programm
beim Auftreten des Interrupts jedesmal neu gestartet.
wendelsberg schrieb:> Versteh ich nicht.
PB3 ist ein PWM-Ausgang. Der Duty-Cycle wird in der Hauptschleife erst
rauf- und dann runtergezählt. Beides mit voller CPU-Geschwindigkeit.
Drückt man den Taster, wird der momentane PWM-Zustand für 2 oder 4s, je
nach Prellen, eingefroren.
Ich find das gut.
mfg.
Thomas Eckmann schrieb:> Aber immerhin lieferst du den Nachweis, dass es wegoptimiert wird,> gleich mit.
Nein, es wird hier eben nicht ∗weg∗optimiert, sondern zu einem 'jump to
self' (aka Endlosschleife) optimiert:
> for (uint8_t x = 0; x < 1000; x++)> {}> 4003c0: eb fe jmp 4003c0 <main>
^^^^^^ ^^^^^^^^^^^^^
Karl Heinz schrieb:> Annahme: Er hat den Code im Datentyp korrigiert.
Das ist allerdings richtig, ein jeder andständige Compiler bügelt das
dann ersatzlos weg.
g457 schrieb:> Nein, es wird hier eben nicht ∗weg∗optimiert, sondern zu einem 'jump to> self' (aka Endlosschleife) optimiert:
Irgendwie raffst du das hier nicht, oder?
mfg.
Thomas Eckmann schrieb:> PB3 ist ein PWM-Ausgang. Der Duty-Cycle wird in der Hauptschleife erst> rauf- und dann runtergezählt. Beides mit voller CPU-Geschwindigkeit.> Drückt man den Taster, wird der momentane PWM-Zustand für 2 oder 4s, je> nach Prellen, eingefroren.
Hmm, so genau hatte ich das nicht untersucht.
Aber ehrlich, glaube nur ich, dass das nicht das ist, was das Programm
eigentlich tun soll?
wendelsberg
wendelsberg schrieb:> Aber ehrlich, glaube nur ich, dass das nicht das ist, was das Programm> eigentlich tun soll?
Bestimmt nicht. Aber er erzählt uns ja nicht, was er erwartet.
Ich kann es mir zwar vorstellen, aber ich bin ja nicht seine Oma.
mfg.
wendelsberg schrieb:> Hmm, so genau hatte ich das nicht untersucht.> Aber ehrlich, glaube nur ich, dass das nicht das ist, was das Programm> eigentlich tun soll?
Ooch. Ich glaub ihm das sogar, wenn er (=der TO) sagt das das Programm
genau das tun soll. Interessant wird es erst, wenn es darum geht, was
das Programm sonst noch tun soll. Denn immerhin steckt da im Programm ja
noch ein 2.te Timer drinn, der momentan ja eigentlich nur so vor sich
hinzählt bzw. eine halbseidene PWM erzeugt. Da kommt also noch was. Und
dann lautet die spannende Frage: Hat er sich mit diesem Ansatz die
Projektfortsetzung verbaut oder nicht.
Das man das Ganze anders rum aufziehen würde, den PWM-Durchlauf in einem
Timer-Interrupt zusammen mit einem globalen Freigabe-Flag bzw. einer
Timer-Interrupt getriebenen Zeitsteuerung, wodurch die Pause nur
angestossen werden braucht und sich selbst terminiert, brauchen wir
nicht diskutieren.
Ist in der Programmierung öfter so, dass man erst dann drauf kommt,
warum andere einen scheinbar komplexeren Ansatz wählen, wenn man sich
selbst mit dem banalen Ansatz in eine Sackgasse manövriert hat. Dann
allerdings versteht man den Problemkreis und auch warum der scheinbar
viel einfachere Ansatz im Endeffekt doch nicht so gut war.