Hallo zusammen. Meine Variable i soll um eins inkrementieren, wenn der Timer Compare (10KHz) die ISR losjagt. ISR wird erfolgreich durchgeführt, im 10KHz Frequenz. Das Problem ist, dass i = 0 bleibt. Dadurch bleibt auch das Lämpchen aus. Es sollte ja angehen und nicht mehr aus. Ich habe versucht i global und auch mit volatile zu definieren, ohne Erfolg. Jemand eine Idee? Danke im Voraus. ISR (TIMER0_COMPA_vect) //10 KHz { static uint8_t i; //wurde auch mal global definiert/ volatile i++; UDR0=(i); //Sende den aktuellen Wert für i switch (i) { case 5: PORTB=(1<<PB0); //Lampe an break; case 10: i=0; //zurücksetzen break; } }
Wenn man PB0 bloss einschaltet, bleibt er ein. Was macht dein wahllos verstreutes Wort volatile dort ? Die Frage wäre auch, von welchem Wert an er loszählt. Und ist dein USART überhaupt richtig initialisiert, um ein Zeichen in 1/10000 Sekunde wegzusenden ?
MaWin schrieb: > Wenn man PB0 bloss einschaltet, bleibt er ein. richtig, damit wollte ich prüfen ob meine switch-abfrage richtig abläuft. MaWin schrieb: > Was macht dein wahllos verstreutes Wort volatile dort ? statt static. MaWin schrieb: > Die Frage wäre auch, von welchem Wert an er loszählt. null. MaWin schrieb: > Und ist dein USART überhaupt richtig initialisiert, um ein Zeichen in > 1/10000 Sekunde wegzusenden ? Baud: 230400. Zeichen werden korrekt dargestellt. Für i bekomme ich nur nuller.
WeißerRiese schrieb: > (10KHz) die ISR losjagt. ISR wird erfolgreich durchgeführt, im 10KHz > Frequenz. Das Problem ist, dass i = 0 bleibt. Das Problem ist, dass du nur denkst, dass i Null bleibt. Wenn die Senderoutine richtig funktioniert: a) PB.0 nicht als Ausgang gesetzt. b) LED falsch angeschlossen.
:
Bearbeitet durch User
Marc V. schrieb: > Das Problem ist, dass du nur denkst, dass i Null bleibt. > Wenn die Senderoutine richtig funktioniert: tut sie. Marc V. schrieb: > a) PB.0 nicht als Ausgang gesetzt. > b) LED falsch angeschlossen (Anode an PB.0). Ist alles richtig gesetzt. Wenn ich die LED einfach so anschalte im ISR unabhängig vom i-Wert leuchtet sie. Es liegt wirklich daran, dass i nicht inkrementiert.
WeißerRiese schrieb: > Wenn ich die LED einfach so anschalte im ISR unabhängig vom i-Wert > leuchtet sie. Es liegt wirklich daran, dass i nicht inkrementiert. Dann probiere es mal so:
1 | switch (i) { |
2 | case 5 ... 20: |
3 | PORTB=(1<<PB0); //Lampe an |
4 | break; |
5 | case 50: |
6 | i=0; //zurücksetzen |
7 | break; |
:
Bearbeitet durch User
Ändert nichts. i wird mit 0 initalisiert. Empfangen tue ich 1er. D.h. einmal wurde es inkrementiert. Danach nicht mehr.
static uint8_t i = 0; ISR (TIMER0_COMPA_vect) { i++; UDR0=(i); } ... nur einser. Die Variable wird nirgendswo sonst verwendet und weitere ISR sind nicht vorhanden.
Sorry obig genannter Code liefert mir zurück eine 129, DEC es wird nichts inkrementiert und gibt auch kein Überlauf.
WeißerRiese schrieb: > Sorry obig genannter Code liefert mir zurück eine > 129, DEC > es wird nichts inkrementiert und gibt auch kein Überlauf. Dann ist das jetzt der Punkt an dem du entweder - den gesammten Code auf ein Minimum reduzierst oder - den gesammten Code hier anhängst. Für mich sieht das nämlich so aus als ob irgendwas i überschreibt....
Volatile ist schon die richtige Idee. Probiere mal static volatile uint8_t i; Sonst kann es passieren, dass sich Interrupt oder Hauptprogramm i gegenseitig überschreiben o. ä..
Und noch eine Frage: Hast Du überhaupt irgendwo sei() gemacht? Wird der Interrupt überhaupt ausgeführt? Stecker in der Steckdose? ;)
i ist so ziemlich der schlechteste Bezeichner für eine globale Variable. Auch, wenn es nur ein Beispiel ist.
Dirk B. schrieb: > i ist so ziemlich der schlechteste Bezeichner für eine globale > Variable. > Auch, wenn es nur ein Beispiel ist. Das ist es! Jetzt haben wir den Grund gefunden, warum die Variable nicht inkrementiert wird. Wir werden dir auf ewige Zeiten dankbar sein und dir die Füße küssen!
Statische Variablen sollten bei der Deklaration initialisiert werden.
1 | static uint8_t i = 0; |
Ansonsten sicherstellen, dass das Programm auch wirklich in die ISR springt. Dazu evtl. die LED auf eine andere Art toggeln (Frequenz muss deutlich kleiner sein, damit du ein Blinken erkennst):
1 | ISR{ |
2 | static int flag = 0; |
3 | if(flag==0){ |
4 | PORTB |=(1<<PB0); |
5 | flag = 1; |
6 | }
|
7 | else{ |
8 | PORTB &=~(1<<PB0); |
9 | flag = 0; |
10 | }
|
11 | }
|
Dominik B. schrieb: > Statische Variablen sollten bei der Deklaration initialisiert werden. Bei 0 unnötig.
Ich würde mal als aller erstes in der ISR mit cli() verhindern dass weitere Interrupts die ISR unterbrechen. Achtung am Ende der ISR das sei() nicht vergessen.
Dominik B. schrieb: > ISR{ > static int flag = 0; > if(flag==0){ > PORTB |=(1<<PB0); > flag = 1; > } > else{ > PORTB &=~(1<<PB0); > flag = 0; > } > }
1 | ISR{ |
2 | PORTB ^= (1<<PB0); |
3 | }
|
Die LED blinkt dann mit halber ISR-Frequenz
Juergen R. schrieb: > Ich würde mal als aller erstes in der ISR mit cli() verhindern dass > weitere Interrupts die ISR unterbrechen. > Achtung am Ende der ISR das sei() nicht vergessen. Bloß nicht, das macht der GCC von selber... ISRs auf nem AVR sind von Natur aus unterbrechungsfrei
Juergen R. schrieb: > Ich würde mal als aller erstes in der ISR mit cli() verhindern dass > weitere Interrupts die ISR unterbrechen. Unnötig, macht die Maschine selbst. > Achtung am Ende der ISR das sei() nicht vergessen. Nicht nur unnötig, sondern direkt schädlich, weil dann in der Zeit zwischen SEI und RETI andere ISRs durchkommen können, die damit ungeplanten Stack belegen.
:
Bearbeitet durch User
Juergen R. schrieb: > Ich würde mal als aller erstes in der ISR mit cli() verhindern dass > weitere Interrupts die ISR unterbrechen. > Achtung am Ende der ISR das sei() nicht vergessen. Wenn es sich beim µC um einen AVR handelt, dann macht der das schon selbst.
A. K. schrieb: >> Statische Variablen sollten bei der Deklaration initialisiert werden. > > Bei 0 unnötig. Ist das sicher immer der Fall? Falls nicht, hätten wir nämlich ein Problem. Ich gehe da lieber auf Nummer sicher. Ingo L. schrieb: > ISR{ > PORTB ^= (1<<PB0); > } > Die LED blinkt dann mit halber ISR-Frequenz Genau, das ist die elegantere Variante. Habe das Beispiel extra so gewählt, damit wir eine statische Variable in der ISR deklarieren ;)
Dominik B. schrieb: > Ist das sicher immer der Fall? Ja, ist im Standard so definiert. Ob du die Variablen trotzdem explizit initialisierst, ist Geschmackssache.
WeißerRiese schrieb: > ISR (TIMER0_COMPA_vect) > { > i++; > UDR0=(i); > } > > Sorry obig genannter Code liefert mir zurück eine > 129, DEC > Die Variable wird nirgendswo sonst verwendet und weitere > ISR sind nicht vorhanden. Sicher. Code fast gleich, trotzdem wird im ersten Beispiel 1 und im zweiten dann 129 zurückgeliefert (dasselbe, aber mit Bit7 gesetzt). Aber nein, i wird nirgends überschrieben...
Dominik B. schrieb: > Ist das sicher immer der Fall? Globale und static Variablen werden, wenn nichts Anderes angegeben ist, mit 0 initialisiert.
Hallo zusammen und danke für eure Beiträge. Die ISR wird aufgerufen und funktioniert wie sie soll, Zeiten stimmen. Ich sende den i-Wert doch nur in der ISR(sonst würde ich gar nichts empfangen). Die LED geht an wenn ich den Befehl in default habe, statt Case xy: aber wie schon erwähnt tut sich auch ohne switch-abfrage bezüglich dem Inkrementierern nichts. Es wird in der ISR inkrementiert und der Wert ausgegeben. Immer 129. Ich hab schon die ISR auf 1 Khz begrenzt, ich weiß nicht wieviele takte eingeplant werden müssen, um den Wert einer Variable um 1 zu erhöhen. Vorweg : Es handelt sich um atmega328p, FCPU: 9.216 MHz static volatile habe ich auch schon probiert: Ausgeben wird eine 1, statt 129. Jedoch auch nichts inkrementiert. Ich werde den Code dann mal soweit wie möglich kürzen und hochladen.
WeißerRiese schrieb: > static uint8_t i; //wurde auch mal global was denn nun, i in der ISR und extern deklariert? Wenn es immer dieselbe i sein soll dann doch nur EINMAL deklarieren und initialisieren sonst hat man zwei i. Ein Verweis mit extern ist natürlich erlaubt und evtl. auch nötig.
:
Bearbeitet durch User
Joachim B. schrieb: > was denn nun, i in der ISR und extern deklariert? Beides mal probiert. Kein Unterschied. Aber als static deklariert ist es in der ISR ja erlaubt. Joachim B. schrieb: > Wenn es immer dieselbe i sein soll dann doch nur EINMAL deklarieren und > initialisieren sonst hat man zwei i. Logisch. Joachim B. schrieb: > Ein Verweis mit extern ist natürlich erlaubt und evtl. auch nötig. Das habe ich noch nicht probiert.
Was macht denn die Simulation? Die dürfte helfen, Programmfehler zu finden, insbesondere, wenn man den Wert von i verfolgt.
WeißerRiese schrieb: > Joachim B. schrieb: >> Ein Verweis mit extern ist natürlich erlaubt und evtl. auch nötig. > > Das habe ich noch nicht probiert. extern volatile unsigned char count; // wäre dein i in der ISR volatile unsigned char count=0;// an anderer Stelle umgedreht gehts aber auch
Dussel schrieb: > Was macht denn die Simulation? Die dürfte helfen, Programmfehler zu > finden, insbesondere, wenn man den Wert von i verfolgt. Ich habe bisher immer die Finger davon gelassen. Hab mir sagen lassen, ist furchtbar langsam. Aber dann will ich das auch nicht unprobiert lassen.
WeißerRiese schrieb: > Ich werde den Code dann mal soweit wie möglich kürzen und hochladen. Nicht nötig, dein gekürzter Code wird bestimmt funktionieren. Oder so etwas probieren:
1 | ISR(TIMER2_COMP_vect) |
2 | {
|
3 | static uint8_t ff, gg = 0, hh; |
4 | ff++; |
5 | gg++; |
6 | UDR=(gg); //Sende den aktuellen Wert für i |
7 | hh = ff + gg; |
8 | switch (gg) { |
9 | case 5 ... 10: |
10 | PORTB=(1<<PB0); //Lampe an |
11 | break; |
12 | case 10 ... 12: |
13 | i=0; //zurücksetzen |
14 | break; |
15 | }
|
16 | }
|
:
Bearbeitet durch User
WeißerRiese schrieb: > Ich habe bisher immer die Finger davon gelassen. Hab mir sagen lassen, > ist furchtbar langsam. Es wäre auch etwas unpraktisch, Variablenwerte in Originalgeschwindigkeit zu verfolgen.
Danke werde ich gleich mal alles ausprobieren. Dussel schrieb: > Es wäre auch etwas unpraktisch, Variablenwerte in > Originalgeschwindigkeit zu verfolgen. Das stimmt, aber es würde reichen wenn man eine Änderung sehen könnte, statt immer den gleichen Wert.
WeißerRiese schrieb: > Das stimmt, aber es würde reichen wenn man eine Änderung sehen könnte, > statt immer den gleichen Wert. wenn es nur eine einzige i gibt und diese auch volatile ist klappt das. Wenn du diese i auch noch umbenennst zu immer_wieder_sonntags kannst du dir sicher sein nicht irgendwo ein i übersehen zu haben von mir aus auch isr_i_die_nur_hier_interessiert
:
Bearbeitet durch User
WeißerRiese schrieb: > Danke werde ich gleich mal alles ausprobieren. Oder die Variable als erste in deinem Programm deklarieren, also vor allen anderen Variablen:
1 | volatile uin8_t IsrVar=0; // anstatt i |
und dann:
1 | ISR(TIMER2_COMP_vect) |
2 | {
|
3 | IsrVar++; |
4 | UDR=(IsrVar); //Sende den aktuellen Wert |
5 | switch (IsrVar) { |
6 | case 5 ... 9: |
7 | PORTB=(1<<PB0); //Lampe an |
8 | break; |
9 | case 10 ... 12: |
10 | IsrVar=0; //zurücksetzen |
11 | break; |
12 | }
|
13 | }
|
Marc V. schrieb: > Oder die Variable als erste in deinem Programm deklarieren, also > vor allen anderen Variablen: > volatile uin8_t IsrVar=0; // anstatt i und überall in anderen Modulen: extern volatile uin8_t IsrVar; // anstatt i
WeißerRiese schrieb: > static volatile habe ich auch schon probiert: Probieren ist einfach nur sch...lecht. Wissen ist besser. 1. Wenn Du eine Variable in einer ISR und in einer anderen Funktion benutzt: volatile 2. Wenn Du eine Variable ausschließlich in einer ISR benutzt: Definiere sie innerhalb der ISR, aber NICHT volatile. 3. Wenn der Wert einer Variablen, welche innerhalb der ISR definiert wurde, nach Beenden der ISR erhalten bleiben soll: static Nach Anwendung dieser 3 Regeln ergibt sich:
1 | ISR (TIMER0_COMPA_vect) |
2 | {
|
3 | static uint8_t i; |
4 | i++; |
5 | ...
|
6 | }
|
Das muss funktionieren. Wenn nicht, überschreibt Dein Programm irgendwo anders Deine globalen Variablen (Merke: Auch eine innerhalb einer Funktion definierte static-Variable liegt ähnlich wie Deine sonstigen globalen Variablen nicht auf dem Stack). Alles bisherigen Beiträge, die da rumrätseln "vielleicht static, vielleicht volatile, probiere mal aus" sind Dünnpfiff, weil sie nämlich von Leuten kommen, die keine Ahnung haben.
:
Bearbeitet durch Moderator
Der OP muss hier mal das komplette Programm posten. Das Verhalten klingt nämlich nach "Reset nach nicht behandeltem Interrupt", bzw. "Error is in Code not shown". Und ja, das hätte man schon 10 Beiträge früher machen müssen.
Frank M. schrieb: > Nach Anwendung dieser 3 Regeln ergibt sich:ISR (TIMER0_COMPA_vect) > { > static uint8_t i; > i++; > ... > } > > Das muss funktionieren. Funktionert aber nicht bei TO. Frank M. schrieb: > Wenn nicht, überschreibt Dein Programm > irgendwo anders Deine globalen Variablen Habe ich ihm schon geschrieben, was hast du neues beizutragen ? Frank M. schrieb: > Alles bisherigen Beiträge, die da rumrätseln "vielleicht static, > vielleicht volatile, probiere mal aus" sind Dünnpfiff, weil sie nämlich > von Leuten kommen, die keine Ahnung haben. Und du bist staatlich anerkannter Ahnungsschätzer, oder was ?
Marc V. schrieb: >> Wenn nicht, überschreibt Dein Programm >> irgendwo anders Deine globalen Variablen > > Habe ich ihm schon geschrieben, was hast du neues beizutragen ? Du hast es lediglich angedeutet. Damit kann der TO nichts anfangen. Ich schreibe, dass es so sein muss. Damit kann man was anfangen. > Und du bist staatlich anerkannter Ahnungsschätzer, oder was ? Da braucht man nicht schätzen, sondern einfach nur die Symptome zu beurteilen. Was passt Dir nicht an meinem Beitrag? Fühlst Du Dich angepisst, obwohl ich Dich überhaupt nicht meinte? Nicht mein Schuh, sondern Deiner :-) P.S. Stelle bitte das plenken ab. Danke.
WeißerRiese schrieb: > ISR (TIMER0_COMPA_vect) //10 KHz > { > > static uint8_t i; //wurde auch mal global definiert/ volatile > i++; > UDR0=(i); //Sende den aktuellen Wert für i > switch (i) { > case 5: > > PORTB=(1<<PB0); //Lampe an > > break; > > case 10: > > i=0; //zurücksetzen > break; > } > } Also meine beschränkte Auffassung sagt mir: ISR Wird aufgerufen -> i wird deklariert -> i wird um eins inkrementiert (daher die 1) -> Switch/Case -> ISR wird beendet und i wird fallen gelassen -> ISR wird aufgerufen -> i wird deklariert -> i wird um eins inkrementiert.... usw... usw. i kann immer nur auf eins (1) kommen, da die Variable zum Ende der ISR ja wieder freigegeben wird. i gehört außerhalb volatile deklariert und nicht in der ISR!
Draco schrieb: > i kann immer nur auf eins (1) kommen, da die Variable zum Ende der ISR > ja wieder freigegeben wird Nö. Da steht eindeutig ein static davor. Lies mal ein gutes Buch über die Programmiersprache "C". Der OP hat mit einem Programmierfehler im nicht geposteten Teil für einen Reset gesorgt. Daher hab ich oben nachgefragt.
:
Bearbeitet durch User
Draco schrieb: > WeißerRiese schrieb: >> static uint8_t i; //wurde auch mal global definiert/ volatile > i kann immer nur auf eins (1) kommen, da die Variable zum Ende der ISR > ja wieder freigegeben wird. Schwachsinn Nr. 1: i ist static und wird deshalb nicht freigegeben. > i gehört außerhalb volatile deklariert und nicht in der ISR! Schwachsinn Nr. 2: Wenn i ausschließlich in der ISR benutzt wird, dann sollte man die Variable auch innerhalb der ISR definieren. volatile ist dabei tunlichst zu vermeiden, weil man damit dem Optimierer des C-Compilers ein Bein stellt. Genau diese Art von Beiträgen meinte ich oben: Keine Ahnung, aber Unsinn erzählen. Lies mal in Deinem C-Buch nach, was static bedeutet.
:
Bearbeitet durch Moderator
Frank M. schrieb: > Was passt Dir nicht an meinem Beitrag? Fühlst Du Dich angepisst, obwohl > ich Dich überhaupt nicht meinte? Nicht mein Schuh, sondern Deiner :-) Dein Pauschalurteil. Man kann schreiben, dass die "bisherigen Beiträge, die da rumrätseln vielleicht static, vielleicht volatile, probiere mal aus" Dünnpfiff sind, aber nicht, dass die alle von Leuten kommen, die keine Ahnung haben. > P.S. > Stelle bitte das plenken ab. Danke. plenken ? Wo ? Falls du plänkeln meinst: Diesmal wollte ich wirklich nicht plänkeln, war vielleicht etwas zu voreilig, entschuldige mich hiermit.
Mit static ist i noch immer nicht global, aber auch nicht local... Ich gehe noch immer nach meinem Sinn, auch wenn mir ein C Buch was anderes sagt. Und wenn ich sehe das i nach der deklaration auf 1 inkrementiert wird und bei jedem Aufruf der ISR immer wieder ne 1 rausgehauen wird, dann ist das erste was icj probiere: Die Variable global volatile außerhalb der ISR deklarieren und probieren ob sie funktionert. (Wobei der Name i, entschuldigung, wirklich dämlich gewählt ist!)
Draco schrieb: > Mit static ist i noch immer nicht global Sie hat keinen globalen Scope, aber sonst wird sie wie eine globale Variable gehandhabt: Sie liegt nicht auf dem Stack wie lokale auto-Variablen. > Ich > gehe noch immer nach meinem Sinn, auch wenn mir ein C Buch was anderes > sagt. Das solltest Du bleiben lassen, denn das führt Dich auf Abwege. > Und wenn ich sehe das i nach der deklaration auf 1 inkrementiert > wird und bei jedem Aufruf der ISR immer wieder ne 1 rausgehauen wird, > dann ist das erste was icj probiere "Probiere"? Das ist genau das falsche! Man sollte wissen, was man tut und nicht probieren! Der TO haut sich seine globalen und static-Variablen mit einem Überschreiber im RAM weg, NICHTS ANDERES bleibt als Konsequenz übrig! Hör auf, mit Deinem Halbwissen so einen Mist zu verbreiten.
Draco schrieb: > dann ist das erste was icj probiere: Die Variable global volatile > außerhalb der ISR deklarieren und probieren ob sie funktionert. Was auf dasselbe hinauskommt solange es um Speicher geht, aber die Möglichkeit, irgendwo in main() oder in einer anderen Routine die Variable zu überschreiben, um ein vielfaches erhöht.
:
Bearbeitet durch User
Draco schrieb: > Mit static ist i […] nicht local Was ist es denn sonst? Von wo kann man auf i sonst noch zugreifen, außerhalb der Funktion?
Marc V. schrieb: > plenken ? > Wo ? Zum Beispiel hier zweimal :-) Plenken wird hier erklärt: https://de.wikipedia.org/wiki/Plenk Dein abgesetztes Fragezeichen führt dabei zu ungewollten Umbrüchen. Beispiel: Ist das eine Unart, ein Fragezeichen mit einem Leerzeichen abzusetzen ? Das passiert nicht, wenn man das Leerzeichen vor dem Fragezeichen unterlässt - wie es auch jede Zeitung - aus gutem Grunde - tut. Schließlich machst Du ja auch kein Leerzeichen vor einem Satzpunkt.
:
Bearbeitet durch Moderator
Dussel schrieb: > Was ist es denn sonst? Von wo kann man auf i sonst noch zugreifen, > außerhalb der Funktion? wenn er mehr als eine i benutzt, passiert gerne bei typischen c & p dann weiss hier keiner welche i welchen Inhalt hat! Deswegen statt i mal eindeutige Variablennamen zu benutzen die zweifelsfrei immer identifiziert werden können wo sie hingehören.
Joachim B. schrieb: > Dussel schrieb: >> Was ist es denn sonst? Von wo kann man auf i sonst noch zugreifen, >> außerhalb der Funktion? > > wenn er mehr als eine i benutzt, passiert gerne bei typischen c & p dann > weiss hier keiner welche i welchen Inhalt hat! > > Deswegen statt i mal eindeutige Variablennamen zu benutzen die > zweifelsfrei immer identifiziert werden können wo sie hingehören. Wenn aber eine andere Variable "i" (außerhalb der ISR) wegen des Namens-Irrtums auf Null gesetzt würde, dann hätte das keinen Einfluß auf "i" innerhalb der ISR. Du hast zwar recht mit der Variablen-Benennung, aber das ist nicht die Ursache des Fehlers beim TO.
Joachim B. schrieb: > Deswegen statt i mal eindeutige Variablennamen zu benutzen die > zweifelsfrei immer identifiziert werden können wo sie hingehören. Wenn der TO die Variable i sauber innerhalb der ISR mit static definiert, ist es vollkommen egal, ob "draussen" noch eine weitere Variable i mit gleichem Namen herumschwirrt. Da gibt es keine Konflikte. Von daher muss es gar nicht "eindeutig" sein. Der RAM-Überschreiber kommt woanders her. Mit dem Namen der Variablen hat es nichts zu tun. Huh schrieb: > Wenn aber eine andere Variable "i" (außerhalb der ISR) wegen des > Namens-Irrtums auf Null gesetzt würde, dann hätte das keinen Einfluß auf > "i" innerhalb der ISR. Du hast zwar recht mit der Variablen-Benennung, > aber das ist nicht die Ursache des Fehlers beim TO. Korrekt.
:
Bearbeitet durch Moderator
Frank M. schrieb: > Schließlich machst Du ja auch kein Leerzeichen vor einem Satzpunkt. Nein, aber wenn Leerzeichen vor ? nicht zu Umbrüchen führen, mache ich das so. Wenn doch, dann ohne. Mit ist irgendwie übersichtlicher, zumindest für mich und ich mache es (aber nur im Forum) immer so. Und das ist plänkeln deinerseits.
Sende doch einfach mal vor dem Betreten Deiner Endlosschleife in Deiner Main ein 0xFF auf die UART. Wenn dann 0xFF 0x01 0xFF 0x01 ... raus kommt ist der ständige Reset bestätigt. Kannst aber auch n Debugger nehmen und einfach n Breakpoint an Beginn der Main setzen. Hans
Frank M. schrieb: > Der RAM-Überschreiber kommt woanders her. Mit dem Namen der Variablen > hat es nichts zu tun. Ja. Deswegen soll er die Variable als erste deklarieren. Eine andere Möglichkeit (zum Testen) ist es, ein Array vor dieser Variable zu deklarieren.
Marc V. schrieb: > Nein, aber wenn Leerzeichen vor ? nicht zu Umbrüchen führen, > mache ich das so. Wenn doch, dann ohne. an dieser Stelle bin ich bei dir, nur übersieht man leicht das der Zeilenumbruch automatisch generiert wird, was wir nicht sehen sehen andere! Ich kann die Kritik verstehen, mag aber trotzdem lieber vor dem ? ein <SPACE>
Marc V. schrieb: > Ja. Nein. Dann ist der Fehler nur wo anders. Und morgen kommt dann: "Gestern ging's noch. Ich hab' gar nichts gemacht!"
Joachim B. schrieb: > an dieser Stelle bin ich bei dir, nur übersieht man leicht das der Und deinetwegen ging EDIT nicht mehr;) Hmmm. Mit Leerzeichen sieht das nicht so beschissen aus ;-) Marc V. schrieb: > Eine andere Möglichkeit (zum Testen) ist es, ein Array vor dieser > Variable zu deklarieren. und danach die Werte im Array kontrollieren/ausgeben.
Marc V. schrieb: > Mit Leerzeichen sieht das nicht so beschissen aus ;-) sag ich auch, obwohl wie selten einer Meinung sind :)
Marc V. schrieb: > Ralf G. schrieb: >> Marc V. schrieb: >>> Ja. >> Nein. > > Doch. bei soviel i-Verwirrung weiss doch keiner wieviele i und wo der TO alle i deklariert hat, es ist auch müssig über i zu streiten, der Variablenname i ist einfach nur Mist wenn er mehrfach auftaucht.
:
Bearbeitet durch User
Joachim B. schrieb: > bei soviel i-Verwirrung weiss doch keiner wieviele i und wo der TO alle > i deklariert hat, es ist auch müssig über i zu streiten, der > Variablenname i ist einfach nur Mist wenn er mehrfach auftaucht. Ich deklariere in Funktionen alle Variablen mit l am Anfang, also lVar1, lVar2, Parameter kriegen ein p davor, also pPar1, pPar2 usw. Konstanten werden mit c_Konst1, c_Konst2 deklariert, Eeprom Variablen dementsprechend mit e_Var etc. Variablen die in jedem Programmteil beliebig geändert werden können, kriegen ein x davor. Auch nach ein paar Monaten weiss ich, ob der wert einer Variable noch irgendwo anders sicher geändert werden kann und wo sich was befindet. Ansonnsten kriegen die Variablen sinnvolle Namen, i ist wirklich ein schlechter Name, aber in diesem Fall absolut irrelevant.
:
Bearbeitet durch User
Marc V. schrieb: > i ist wirklich ein > schlechter Name, aber in diesem Fall absolut irrelevant. hast du den gesamten Code gesehen? ich nicht.
Marc V. schrieb: > Nicht nötig, dein gekürzter Code wird bestimmt funktionieren. Recht sollst du behalten. http://pastebin.com/w9Fx16Ye so funktioniert es. Die Variable i = cnt, habe sie nur hier als Beispiel "i" getauft, habe nicht gedacht, dass ein Buchstabe für so viel Verwirrung sorgt. Muss ich wohl nochmal den Code durchschauen. Bin/war mir eigentlich sicher dass auf die Variable bezogen nichts geändert wurde. Danke euch allen.
Joachim B. schrieb: > hast du den gesamten Code gesehen? Nenne bitte eine Möglichkeit, eine Variable i, die innerhalb einer Funktion static definiert ist, durch eine gleichnamige Variable - außer durch RAM-Überschreibungen - zu manipulieren. Glaube mir: am Namen liegts nicht.
Joachim B. schrieb: > hast du den gesamten Code gesehen? ich nicht. Die Variable "i", um die es hier geht, ist in der ISR definiert und hat damit keinen Sichtbarkeitsbereich außerhalb der ISR. Da können im restlichen Programm noch hunderte "i" auftauchen, das kratzt die "i" in der ISR nicht.
Frank M. schrieb: > Glaube mir: am Namen liegts nicht. Huh schrieb: > Da können im > restlichen Programm noch hunderte "i" auftauchen, das kratzt die "i" in > der ISR nicht. glaube ich euch unbesehen, nur ist das Problem vom TO damit offensichtlich nicht vom Tisch, abgesehen davon das ich bei seinen Aussagen was wann wo nicht mehr durchblicke und ich aus eigener Erfahrung beim Schindluder treiben mit dem Variablennamen i selber schon reingefallen bin. Auch wenn i richtig angewendet kein Problem ist ist der Variablenname doof gewählt weil uneindeutig.
Oder gibts da evtl. doch den Klassiker unter den Fehlern und die Warnung wird ignoriert?:
1 | if ( i = 1 )... |
;)
Ingo L. schrieb: > Oder gibts da evtl. doch den Klassiker unter den Fehlern und die > Warnung > wird ignoriert?:if ( i = 1 )... > ;) Das wäre auch nur ein Problem, wenn es innerhalb der ISR stehen würde. Außerhalb wird es zwar unerwünschte Effekte haben, aber nicht den hier beschriebenen Fehler.
Joachim B. schrieb: > Auch wenn i richtig angewendet kein Problem ist ist der Variablenname > doof gewählt weil uneindeutig. Stell Dir vor, Du schreibst eine C-Library. Oder Du nutzt eine ... und Du müsstest immer darauf achten, dass alle Variablennamen eindeutig sind! Glücklicherweise ist es nicht so, dass die Variablen eindeutig sein müssen. Sonst müsste ich als Bibliotheks-Programmierer ja schon im vorhinein wissen, was die Anwender für Variablennamen wählen, damit ich diese selbst vermeide, um Konflikte zu vermeiden. Die Programmiersprache C wäre in diesem Fall unbrauchbar, weil man überhaupt nicht modular programmieren könnte. Also: Benutzte ruhig nicht-eindeutige Variablen. Aber wende die Regeln für die Scopes eindeutig an. Dann gibt es auch keine Schwierigkeiten.
Joachim B. schrieb: > nur ist das Problem vom TO damit > offensichtlich nicht vom Tisch, abgesehen davon das ich bei seinen > Aussagen was wann wo nicht mehr durchblicke und ich aus eigener > Erfahrung beim Schindluder treiben mit dem Variablennamen i selber schon > reingefallen bin. Hey doch ist es. Es muss so funktionieren, wie beschrieben wurde. Das Problem liegt offensichtlich doch irgendwo in meinem Code, aber den Fehler muss ich dann selbst finden. :) Fakt ist : es funktioniert mit dem Schlüsselwort static in der ISR Routine. An dem Variablennamen i lag es nicht. Der Fehler ist in meinem Code. Wo muss ich herausfinden. Aber dass es so gehen muss, hilft mir schon weiter :) Danke euch.
Da grad noch weiter diskutiert wurde. Falls mein Beitrag übersehen wurde nochmal: http://pastebin.com/w9Fx16Ye SO FUNKTIONIERT ES. Hiermit ist mein Problem zwar nicht gelöst, aber ich weiß bescheid dass es so gehen muss. Natürlich dürft ich weiter diskutieren, aber meinetwegen ist hiermit die Sache erledigt. Vielen Danke an alle.
Es ist übrigens keine gute Idee, UDR einfach zu beschreiben, vor allem, wenn das mit 10kHz Wiederholrate geschieht. Um sicherzustellen, das das Zeichen schon weg ist, das da vorher drin war, muss man bei 8-Bit ohne Parity eine Baudrate von über 100kBaud servieren. (Jedes Zeichen besteht aus 10 Bit) Selbst bei 1kHz sollte man mit mindestens 10kBaud wegsenden. Gut, es gibt ein wenig Luft, weil die Verarbeitung der ISR etwas dauert, das sind aber eben nur µs.
Matthias S. schrieb: > Es ist übrigens keine gute Idee, UDR einfach zu beschreiben, vor allem, > wenn das mit 10kHz Wiederholrate geschieht. Um sicherzustellen, das das > Zeichen schon weg ist, das da vorher drin war, muss man bei 8-Bit ohne > Parity eine Baudrate von über 100kBaud servieren. (Jedes Zeichen besteht > aus 10 Bit) Habe eine Baud von 230.4k Ja ist noch nicht alles ausgereift. Vielleicht probiere ich mich dann an den FIFO's. Danke.
Matthias S. schrieb: > Es ist übrigens keine gute Idee, UDR einfach zu beschreiben, vor allem, > wenn das mit 10kHz Wiederholrate geschieht. Um sicherzustellen, das das > Zeichen schon weg ist, das da vorher drin war, muss man bei 8-Bit ohne > Parity eine Baudrate von über 100kBaud servieren. (Jedes Zeichen besteht > aus 10 Bit) Daran hatte ich auch gedacht, aber es hieß ja es käme nicht zu einem Überlauf. Anstatt die Baudrate hochzubohren, würde ich das ganze aber eher mit Polling machen (hoffe, das ist das richtige Flag):
1 | while(!UDRE); // Warten bis vorheriges Senden abgeschlossen |
2 | UDR0 = i; |
Dann ist sichergestellt, dass auch das Zeichen vorher rausgegangen ist, bevor die ISR das Daten-Register wieder vollstopft
:
Bearbeitet durch User
Dominik B. schrieb: > while(!UDRE); // Warten bis vorheriges Senden abgeschlossen > UDR0 = i; Warten in einer ISR könnte unerwünschte Nebeneffekte haben - kommt auf das Programm im Ganzen an. Aber das kennen wir überhaupt nicht.
Frank M. schrieb: > Dominik B. schrieb: >> while(!UDRE); // Warten bis vorheriges Senden abgeschlossen >> UDR0 = i; > > Warten in einer ISR könnte unerwünschte Nebeneffekte haben - kommt auf > das Programm im Ganzen an. Aber das kennen wir überhaupt nicht. Das ist richtig, sauber ist das definitiv auch nicht. Könnte dadurch zumindest ausschließen, dass der UART nicht abgehängt wird beim Senden.
Dominik B. schrieb: > Anstatt die Baudrate hochzubohren, würde ich das ganze aber eher mit > Polling machen (hoffe, das ist das richtige Flag): > while(!UDRE); // Warten bis vorheriges Senden abgeschlossen > UDR0 = i; Selbst wenn der Code stimmen würde (richtig wäre etwa
1 | while (!( UCSR0A & (1<<UDRE0))){}; |
2 | UDR0 = i; |
) ,hebelt man damit den grossen Vorteil eines Timer Interrupt aus - nämlich das beinharte Abarbeiten in genau definierten Zeitabständen. Wenn UDR nicht leer ist, wird das nicht klappen. Seriellen Kram also besser ausserhalb der ISR machen. Dafür müsste i allerdings global sein, was auf den kleinen MC aber auch kein Nachteil ist.
Matthias S. schrieb: > Seriellen Kram also besser ausserhalb der ISR machen. Ist deshalb innerhalb der ISR, weil der CTC Timer 0 durch Autotrigger an den ADC-Start gebunden ist. Dadurch soll das Timing beim Samplen eingehalten werden.
WeißerRiese schrieb: > Dadurch soll das Timing beim Samplen eingehalten werden. Man kann durchaus ausrechnen, welche Baudraten bei welcher Samplerate möglich sind. Bei geeigneten Geschwindigkeiten kann dann das Testen auf UCSR0A & (1<<UDRE0) tatsächlich entfallen. Hast Du Dir das vorher ausgerechnet, damit die serielle Schnittstelle nicht überläuft? Wenn ja, ist das durchaus okay so.
:
Bearbeitet durch Moderator
Ich hab mühselig jetzt alles durchprobiert. Es ist alles gleich. Einzige Änderung, ich habe ADC vom Timer entkoppelt. Dann inkrementiert die Variable. Nun gut. Ich wollte mir das Aufrufen von ADC-Start sparen, in dem ich den Autotrigger nutze für ADC-Start, der mit CTC Timer0 ausgelöst wird. Dann wird das eben manuell gestartet. Frank M. schrieb: > Hast Du Dir das vorher ausgerechnet, damit die serielle Schnittstelle > nicht überläuft? Wenn ja, ist das durchaus okay so. ja, haut alles hin. Danke.
WeißerRiese schrieb: > Einzige Änderung, ich habe ADC vom Timer entkoppelt. Dann inkrementiert > die Variable. Dann hast du irgendwo in der ADC Routine munter die Variable i überschrieben, wahrscheinlich mit einem Array oder mit einem ADC-integer der als uint8_t deklariert war. Warum deklarierst du die ISR Variable nicht als volatile und als erste Variable überhaupt und probierst es dann nochmal ?
:
Bearbeitet durch User
Marc V. schrieb: > Dann hast du irgendwo in der ADC Routine munter die Variable i > überschrieben, wahrscheinlich mit einem Array oder mit einem > ADC-integer der als uint8_t deklariert war. nein. Es war der ADC-Interrupt. Es ist immer noch Autogetriggert, aber der ADC-Interrupt ausgeschalten. Alles läuft wunderbar. Heiner schrieb im Beitrag #4644798: > typisch Anfänger: Problem nicht mehr sichtbar -> weiter geht's ohne > die wirkliche Ursache nachvollzogen und verstanden zu haben. Wenn du > noch Das Problem ist mir zur Hälfte klar. Durch Fehler lernt man. Und ja ich bin Anfänger. Heiner schrieb im Beitrag #4644798: > mit FIFO´s anfängst, endet das in einer Katastrophe. Nicht unbedingt, hab es aber so aufgeteilt bekommen, dass ich das nicht mehr brauche.
WeißerRiese schrieb: > nein. Es war der ADC-Interrupt. Es ist immer noch Autogetriggert, aber > der ADC-Interrupt ausgeschalten. Alles läuft wunderbar. Nein, sicher nicht. Aber du kannst es ruhig weiter glauben.
Marc V. schrieb: > WeißerRiese schrieb: >> nein. Es war der ADC-Interrupt. Es ist immer noch Autogetriggert, aber >> der ADC-Interrupt ausgeschalten. Alles läuft wunderbar. > > Nein, sicher nicht. > Aber du kannst es ruhig weiter glauben. // ADCSRA |= (1<<ADIE); geht ADCSRA |= (1<<ADIE); geht nicht. ADC-Autotrigger an CTC Timer 0.
WeißerRiese schrieb: > // ADCSRA |= (1<<ADIE); geht > > ADCSRA |= (1<<ADIE); geht nicht. > > ADC-Autotrigger an CTC Timer 0. Hmmm.
1 | i++; |
2 | UDR0=(i); //Sende den aktuellen Wert für i |
Das wird nicht ausgeführt:
1 | i++; |
aber folgendes
1 | UDR0=(i); //Sende den aktuellen Wert für i |
geht. Dein Compiler muss aber ganz schön Mist gebaut haben... EDIT: Oder du. Was ist wahrscheinlicher ?
:
Bearbeitet durch User
WeißerRiese schrieb: Oh mann. Mach es uns doch nicht so schwer. Ohne deinen Vollständigen Code zu kennen kann dir hier keiner effektiv helfen. Das ist alles nur stochern im Nebel. Dem Hinweis das ein anderer Codeteil dir i überschreibt(*) und es deshalb nötig ist den ganzen Code zu betrachten gehst du nicht ein. Den Beweis das der uns unbekannte Code schuld ist hast du mit dem funktionierenden minimal Beispiel ja selbst geliefert. Und wenn ich versuche die 2 Aussagen: > // ADCSRA |= (1<<ADIE); geht > ADCSRA |= (1<<ADIE); geht nicht. mit deinem Code in einklang zu bringen passt das hinten und vorne nicht. Du hast keine ISR für den ADC drin, ergo das ding macht einen reset, was nicht sein kann da du den ADC noch nicht mal startest geschweige denn konfigurierst.... Willkommen im Nebel. Also Poste alles an Code oder begib dich in der *.sym / *.size auf die suche nach verdächtigen. *) Zum Thema überschreiben: Es hat nichts mit dem i in der ISR zu tun. Diese i steht an einer bestimmten Stelle im RAM und irgendwer schreibt da illegalerweise auch rein. Die üblichen Verdächtigen sind: - Arrays - das meiste aus string.h - Pointer Oder der µC macht einen Reset. Das geht so schnell, das merkst du nicht -> ausbremsen mit einem LED-Test am anfang.
Julian .. schrieb: > Oh mann. Mach es uns doch nicht so schwer. > Ohne deinen Vollständigen Code zu kennen kann > dir hier keiner effektiv helfen. Es hat sich doch schon lange erledigt. Ich denke kaum, dass jemand Lust hat sich durch den ganzen Code zu wurschteln. Julian .. schrieb: >> // ADCSRA |= (1<<ADIE); geht >> ADCSRA |= (1<<ADIE); geht nicht. > > mit deinem Code in einklang zu bringen passt das hinten > und vorne nicht. Doch tut es.. >Du hast keine ISR für den ADC drin, Braucht man nicht. > ergo das ding macht einen reset, was nicht sein kann > da du den ADC noch nicht mal startest geschweige denn ..Autostart. Alle Werte und Frequenzen sind korrekt. Counter läuft wie er soll. Julian .. schrieb: > Also Poste alles an Code oder begib dich in der *.sym / *.size > auf die suche nach verdächtigen. Hab ich doch schon lange.
Julian .. schrieb: > Oder der µC macht einen Reset. Das geht so schnell, das > merkst du nicht -> ausbremsen mit einem LED-Test am anfang. ausgeschlossen. Die "Messung" startet erst wenn ein bestimmtes Zeichen empfangen wird.
WeißerRiese schrieb: > Das Problem ist mir zur Hälfte klar. > Durch Fehler lernt man. Und ja ich bin Anfänger. Um auf diese Aussage einzugehen. Der Timer0 startet im Hintergrund eine single ADC-Conversion ohne Weiteres Dazutun -> Autostart. Zusätzlich nutze ich die ISR von Timer0 (mit dem Wissen, dass gerade eine ADC-Start erfolgt ist). In der inkrementiert meine Variable, die aber nie aufaddiert wurde. Zwischen dem Beginn der ISR(Timer0) und den ADC-Interrupt (den ich eigentlich nirgends aufgerufen habe) vergeht 1/45KHz [s]. Nachdem ich den Interrupt für den ADC ausgeschalten habe (Der restliche Code ist völlig identisch), habe ich das Problem nicht mehr. Und ich habe nur eine einzige Variable in einer Schleife. Es wird nichts überschrieben.
WeißerRiese schrieb: > Nachdem ich den Interrupt für den ADC ausgeschalten habe (Der restliche > Code ist völlig identisch), habe ich das Problem nicht mehr. Das klingt aber wirklich nach folgendem: Zuerst hattest du den Interrupt für den ADC eingeschaltet, hattest aber keine ISR dafür (hast du weiter oben selbst gesagt). Der µC wollte die ISR aufrufen beim ADC-Interrupt, fand aber keine, springt ins Leere, deshalb RESET... Als du den ADC-Interrupt ausgeschaltet hattest, ging es. Jetzt versucht er auch nicht mehr ins Leere zu springen...
Räusper schrieb: > Das klingt aber wirklich nach folgendem: > Zuerst hattest du den Interrupt für den ADC eingeschaltet, hattest aber > keine ISR dafür (hast du weiter oben selbst gesagt). Der µC wollte die > ISR aufrufen beim ADC-Interrupt, fand aber keine, springt ins Leere, > deshalb RESET... > Als du den ADC-Interrupt ausgeschaltet hattest, ging es. Jetzt versucht > er auch nicht mehr ins Leere zu springen... Das ist möglich. Wenn du noch zwischen ins Leere und RESET unterscheidest. Auf jeden Fall lag der Fehler darin. Der Rest wurde ja auch nicht ausgeführt von der ISR. Ich hab nicht dran gedacht, die Interrupts auszuschalten. War noch vom vorherigen Code, wo die ISR(ADC) genutzt wurde. Nur würde er beim RESET mir keinen weiteren Wert liefern ohne dass ich ihm ein Zeichen sende. WeißerRiese schrieb: > WeißerRiese schrieb: >> Das Problem ist mir zur Hälfte klar. >> Durch Fehler lernt man. Und ja ich bin Anfänger. Ich erkläre es mir so: es ist als würde da stehen: void (ADC-ISR) { //leer } Wie dem auch sei. Vielen Dank für eure Beiträge. Ich habe wieder was lernen können.
WeißerRiese schrieb: > Ich hab nicht dran gedacht, die Interrupts auszuschalten. War noch vom > vorherigen Code, wo die ISR(ADC) genutzt wurde. Eben. Das musst du dir merken. Zu jedem freigegebenen Interrupt gehört zwingend eine ISR. Sonst kracht's. Hast du ja gesehen :-)
Räusper schrieb: > Eben. Das musst du dir merken. Zu jedem freigegebenen Interrupt gehört > zwingend eine ISR. Sonst kracht's. Hast du ja gesehen :-) ist verinnerlicht. in meinem Kopf war das so: wo keine Aufruf (Interrupt), da kein Interrupt :) Danke euch allen.
Das hier: > // ADCSRA |= (1<<ADIE); geht > ADCSRA |= (1<<ADIE); geht nicht. gibt einen Hinweis auf die Lösung. Da der TIMER0-Interrupt und der ADC-Interrupt gleichzeitig auftreten, wenn das ADIE-Bit im ADCSRA gesetzt ist, werden zwei Interrupts gleichzeitig getriggert. Diese Interrupts werden vom AVR nacheinander bearbeitet in der Reihenfolge, wie sie im Datenblatt in Tabelle 12-1 aufgeführt sind. Timer0_compA wohnt im Vector Nr.15, der ADC-Interrupt hat den Vector Nr.22 In den Vektoren werden vom Compiler Sprungbefehle zum Anfang der jeweiligen ISR eingefügt - aber nur, wenn auch eine im Programm definiert ist. Es wird also der Timer-Interrupt aufgeführt. Der AVR ist so konstruiert, dass nach dem reti des Timer-Interrupts zunächst ein Befehl des Hauptprogramms ausgeführt wird, dann wird in den Vector des ADC verzweigt. Da ist aber nun kein Sprungbefehl eingetragen (ich habe den Thread nochmal überflogen und nicht gesehen dass eine ISR für den ADC definiert wurde.) Also steht in Vector Nummer 22 vermutlich 0xFFFF , genau wie in Vector Nummer 23-26 vermutlich auch. Der AVR versucht die 0xFFFF als Befehl zu interpretieren. Entweder ist dass Bitmuster unbekannt, dann wird es als "nop" interpretiert, oder es wird irgendetwas sinnfreies gemacht. Da 0xFFFF jedoch kein Sprung ist, läuft der AVR nach dem Ende der Vectortabelle ganz banal in den C-startup-Code, und alles wird neu initialisiert. Das ist nicht direkt ein Reset, aber ich denke auf die Variablen wirkt es so. (bei einem Reset im AVR würden auch die Register auf die Reset-Werte gestellt, das ist hier aber nicht so) Jedenfalls sollte das beobachtete Verhalten so zu erklären sein. Cheers Wolfgang
WeißerRiese schrieb: > Julian .. schrieb: >> Ohne deinen Vollständigen Code zu kennen kann >> dir hier keiner effektiv helfen. > > Es hat sich doch schon lange erledigt. Ich denke kaum, dass jemand Lust > hat sich durch den ganzen Code zu wurschteln. Test? Was meinst du macht mehr spass: - Raten was im vorenthaltenden Code steht - Nachschauen zu können was Sache ist. > Julian .. schrieb: >>> // ADCSRA |= (1<<ADIE); geht >>> ADCSRA |= (1<<ADIE); geht nicht. >> >> mit deinem Code in einklang zu bringen passt das hinten >> und vorne nicht. > > Doch tut es.. Mit dem Code vor deiner Nase vielleicht. Ich habe hier nur den: http://pastebin.com/w9Fx16Ye Ergo bleibe ich bei meiner Aussage das das nicht zusammen passt. >>Du hast keine ISR für den ADC drin, > > Braucht man nicht. Wenn du die Interrupts beim ADC einschaltest (1<<ADIE) schon. >> ergo das ding macht einen reset, was nicht sein kann >> da du den ADC noch nicht mal startest geschweige denn > > ..Autostart. Alle Werte und Frequenzen sind korrekt. Counter läuft wie > er soll. In http://pastebin.com/w9Fx16Ye ist kein ADC autostart drin....
Julian .. schrieb: > Wenn du die Interrupts beim ADC einschaltest (1<<ADIE) schon. (Hatte dich missverstanden). Entschuldige. Damit hast du auch vollkommen recht und das war auch der Auslöser. (Richtig konnte keiner von euch riechen) Ich habe den Interrupt ignoriert, weil ich es nicht besser wusste. Ist ja auch meine heutige Erkenntnis. Also dir auch vielen Dank noch. @Wolfgang, Danke für die ausführliche Information.
@WeißerRiese: gerne, leider war ich zum Ende hin nicht ganz korrekt. Bin gerade mal durchgegangen, was der GCC hier produziert. In einem nicht verwendeten Vector läßt GCC keineswegs 0xFFFF stehen, sondern fügt in unbenutzten Vektoren Sprünge in einen Teil des Startup-codes ein, an dem ein Sprung auf den Resetvektor steht, in dem wiederum ein Sprung auf den Beginn des Startupcodes steht. Das Ergebnis ist allerdings dann das selbe. Cheers! Wolfgang
wneudert schrieb: Okay, zu spät. Jetzt habe ich das aber schon getippt.... > Also steht in Vector Nummer 22 vermutlich 0xFFFF , genau wie in Vector > Nummer 23-26 vermutlich auch. Der AVR versucht die 0xFFFF als Befehl zu > interpretieren. Entweder ist dass Bitmuster unbekannt, dann wird es als > "nop" interpretiert, oder es wird irgendetwas sinnfreies gemacht. Im .lss File steht bei nicht definierten IRQs: Springe zu __bad_interrupt. __bad_interrupt hat nur einen Befehl: jmp auf 0x0000 Also ein Pseudo Reset (ein Hardware Reset wird nicht ausgelöst). Genau wie in der Dokumentation beschrieben: http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html WeißerRiese schrieb: > (Richtig konnte keiner von euch riechen) Deswegen wird hier immer darauf bestanden den Vollständigen Code zu zeigen. > Ich habe den Interrupt ignoriert, weil ich es nicht besser wusste. Ist > ja auch meine heutige Erkenntnis. Das wird dir nicht mehr passieren ;-) > Also dir auch vielen Dank noch. Aber Gerne doch.
Ingo L. schrieb: > Juergen R. schrieb: >> Ich würde mal als aller erstes in der ISR mit cli() verhindern dass >> weitere Interrupts die ISR unterbrechen. >> Achtung am Ende der ISR das sei() nicht vergessen. > Bloß nicht, das macht der GCC von selber... ISRs auf nem AVR sind von > Natur aus unterbrechungsfrei Damit hätte doch Jürgen Recht? Die Routine läuft ja "nicht-atomar" ab? (Entschuldigt meine wahrscheinlich erfundene Fachbegriffe.) Interrupts werden zu keinem Zeitpunkt ausgeschalten.
Julian .. schrieb: > Also ein Pseudo Reset (ein Hardware Reset wird nicht ausgelöst). Das deckt sich auch damit, dass kein Zeichen mehr empfangen werden muss. Julian .. schrieb: > Deswegen wird hier immer darauf bestanden den Vollständigen Code zu > zeigen. Wenn ich mir nicht zu 100% sicher gewesen wäre, dass es nicht an dem ADC-Interrupt liegt.. (aber ich habe vergessen, dass ihr nicht wissen könnt, dass ich kein ADC_ISR habe... ;) )
Der AVR hat keine echten Interruptprioritäten. Wenn eine ISR dran ist, ist sie dran und kann nicht unterbrochen werden. Es sei denn, du setzt von Hand das I-Flag im Statusregister wieder. Cheers! Wolfgang
wneudert schrieb: > Der AVR hat keine echten Interruptprioritäten. > Wenn eine ISR dran ist, ist sie dran und kann nicht unterbrochen werden. > Es sei denn, du setzt von Hand das I-Flag im Statusregister wieder. Ich dachte, genau das Gegenteil ist dann der Fall. Da keine Priorität = alle gleichwertig. D.h. wenn die nächste dran ist, ist sie halt jetzt dran.
Na gut. Der "Pseude-Reset" erklärt dann auch, warum ich 1er (einmal inkrementiert) ständig bekommen habe. Danke fürs Aufklären.
Wenn man eine
1 | ISR(BADISR_vect) { |
2 | // some usefull debug code
|
3 | }
|
anlegt, dann kann man dieses Problem abfangen.
Carl D. schrieb: > Wenn man eineISR(BADISR_vect) { > // some usefull debug code > }anlegt, dann kann man dieses Problem abfangen. Wieder was gelernt. Merci!
Priorität bei Interrupts bedeutet, dass eine ISR mit niedrigerer Priorität durch eine ISR höherer Priorität unterbrochen werden kann. Das aber gibt es bei ATTINY- und ATMEGA-AVRs nicht. Da sind alle gleichwertig (mit gleicher Priorität), und gleiche Prioritäten unterbrechen sich nicht gegenseitig. Im Datenblatt wird trotzdem das Wort Priorität erwähnt. Das bedeutet nur, daß, wenn mehrer Interrupt mehr oder weniger gleichzeitig auftreten und die entsprechenden Flags gesetzt sind, die zugehörigen ISRs in der Reihenfolge abgearbeitet werden, wie sie in der Position in der Tabelle liegen. Deswegen kommt zum Beispiel die Timer-ISR vor der ADC-ISR dran, wenn beide Interrupts gleichzeitig auftreten. Cheers! Wolfgang
wneudert schrieb: > Problem ist nur, dass es keine BADISR_vect gibt > > :) Soso! Wird aber vom Compiler in alle Int-Vektoren ohne ISR eingetragen und wird normalerweise aus der Lib gezogen. Dieser Defaul macht im wesentlichen Jump 0, quasi RESET. Hat man selbst eine eigene BADISR implementiert, so wird diese vom Linker "bevorzugt". http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html#ga1f6459a85cda682b2163a20af03ac744
na gut! Nur wird der nicht in der Vektoren eingetragen, sondern im C-Startup gibts einen Sprung, entweder auf den 0x0000 oder auf diese BADISR. In den Vectoren stehen wiederum Sprünge auf diesen Sprung. :) Nur so um spitzfindig zu bleiben :)
Eigentlich wollt ich dem TO erklären, wie das geht. Denn der hat gezeigt, daß er was dazulernen will. Manche Feinheiten wird er später selbst rausbekommen. (Und ja Klugscheisser deiner Art sind zum K.....)
WeißerRiese schrieb: > Der "Pseude-Reset" erklärt dann auch, warum ich 1er (einmal > inkrementiert) ständig bekommen habe. Danke fürs Aufklären. > Wieder was gelernt. Merci! Das glaube ich nicht. Ich glaube, du wirst die Leute nur verarschen und die meisten sind darauf reingefallen. Erstens: WeißerRiese schrieb: > Sorry obig genannter Code liefert mir zurück eine > 129, DEC > es wird nichts inkrementiert und gibt auch kein Überlauf. Wie soll da die 129 reinkommen wenn der uC ständig resettet ? Zweitens: WeißerRiese schrieb: > Julian .. schrieb: >> Oder der µC macht einen Reset. Das geht so schnell, das >> merkst du nicht -> ausbremsen mit einem LED-Test am anfang. > > ausgeschlossen. Die "Messung" startet erst wenn ein bestimmtes Zeichen > empfangen wird. An deiner Stelle würde ich aufhören rumzutrollen. Carl D. schrieb: > Eigentlich wollt ich dem TO erklären, wie das geht. Denn der hat > gezeigt, daß er was dazulernen will. Manche Feinheiten wird er später Er hat nur gezeigt, dass er ein Troll ist, dass sein Programm und das was er hier erzählt, nichts gemeinsam haben und dass er alle für zu dumm hält, um sein (nicht gepostetes) Programm zu verstehen. Deswegen hält er es auch nicht für nötig, dieses Glanzwerk der Programmierkunst hier zu zeigen.
:
Bearbeitet durch User
Marc V. schrieb: > Ich glaube, du wirst die Leute nur verarschen und die meisten sind > darauf reingefallen. Mist. Wie hast du mich nur erwischt? Marc V. schrieb: > Wie soll da die 129 reinkommen wenn der uC ständig resettet ? Wenn du es wissen, willst nur für dich kann ich nochmal probieren. Glaube es war bei der Initialisierung mit static volatile eine 1 und nur mit static eine 129. Marc V. schrieb: >> ausgeschlossen. Die "Messung" startet erst wenn ein bestimmtes Zeichen >> empfangen wird. > > An deiner Stelle würde ich aufhören rumzutrollen. Das nennt sich dann Bluetooth-Kommunikation mit einem Mobilfunkgerät. Dieses genannte Gerät schickt so komische Zeichen wenn man bei der App so komische virtuelle Knöpfe betätigt. Abhängig davon erledigt der µC sein Zeugs.. Wenn keine Knöpfe gedrückt -> µC warten. Wenn µC reset-> µC nichts machen. Marc V. schrieb: > Er hat nur gezeigt, dass er ein Troll ist, dass sein Programm und das > was er hier erzählt, nichts gemeinsam haben und dass er alle für zu > dumm hält, um sein (nicht gepostetes) Programm zu verstehen. > Deswegen hält er es auch nicht für nötig, dieses Glanzwerk der > Programmierkunst hier zu zeigen. genau aus solchen Gründen habe ich das "Programm" a) gekürzt bis aufs Minimum b) vorenthalten. Bei allem Respekt vor deinem Können Marc, hast du es nachts wirklich nötig auf einem Anfänger rumzuhacken mit einem Beitrag, der nichts sinnvolles beiträgt? Das Thema ist hier doch schon lange durch. Angenehmes Nächtle.
Wenn jemand den Code haben möchte (was auch immer er damit machen möchte) oder mich noch jemand für einen Troll hält (@Marc, ich musste herzhaft lachen.), teile ich Ihn natürlich. Zwecks Fragestellung ist das nicht mehr notwendig, denn diese hat sich lediglich darauf bezogen, ob das Vorgehen bzgl. der Inkrementierung innerhalb einer ISR richtig war. Denn dadurch konnte ich vermeindliche Fehler ausschließen und bin euch dankbar dafür, unglaublich wie manchen einfach die Diskussions-Lust nicht vergeht. Klasse Forum, weiter so! :D :D
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.