Forum: Mikrocontroller und Digitale Elektronik Variable i inkrementiert nicht


von WeißerRiese (Gast)


Lesenswert?

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;
 }
      }

von WeißerRiese (Gast)


Lesenswert?

Habe den Timer runtergesetzt auf 1 Khz, hat nichts geändert.

von MaWin (Gast)


Lesenswert?

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 ?

von WeißerRiese (Gast)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von WeißerRiese (Gast)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von WeißerRiese (Gast)


Angehängte Dateien:

Lesenswert?

Ändert nichts.

i wird mit 0 initalisiert.

Empfangen tue ich 1er. D.h. einmal wurde es inkrementiert. Danach nicht 
mehr.

von WeißerRiese (Gast)


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

Sorry obig genannter Code liefert mir zurück eine

129, DEC

es wird nichts inkrementiert und gibt auch kein Überlauf.

von WeißerRiese (Gast)


Angehängte Dateien:

Lesenswert?

Bild

von Julian .. (juliank)


Lesenswert?

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....

von franz schlüter (Gast)


Lesenswert?

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. ä..

von franz schlüter (Gast)


Lesenswert?

Und noch eine Frage: Hast Du überhaupt irgendwo sei() gemacht? Wird der 
Interrupt überhaupt ausgeführt? Stecker in der Steckdose? ;)

von Dirk B. (dirkb2)


Lesenswert?

i ist so ziemlich der schlechteste Bezeichner für eine globale Variable.
Auch, wenn es nur ein Beispiel ist.

von Huh (Gast)


Lesenswert?

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!

von Dominik B. (odysseus1710)


Lesenswert?

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
}

von (prx) A. K. (prx)


Lesenswert?

Dominik B. schrieb:
> Statische Variablen sollten bei der Deklaration initialisiert werden.

Bei 0 unnötig.

von Juergen R. (stumpjumper)


Lesenswert?

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.

von Ingo L. (corrtexx)


Lesenswert?

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

von Ingo L. (corrtexx)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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
von Huh (Gast)


Lesenswert?

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.

von Dominik B. (odysseus1710)


Lesenswert?

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 ;)

von B. S. (bestucki)


Lesenswert?

Dominik B. schrieb:
> Ist das sicher immer der Fall?

Ja, ist im Standard so definiert. Ob du die Variablen trotzdem explizit 
initialisierst, ist Geschmackssache.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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...

von Dirk B. (dirkb2)


Lesenswert?

Dominik B. schrieb:
> Ist das sicher immer der Fall?

Globale und static Variablen werden, wenn nichts Anderes angegeben ist, 
mit 0 initialisiert.

von WeißerRiese (Gast)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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
von WeißerRiese (Gast)


Lesenswert?

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.

von Dussel (Gast)


Lesenswert?

Was macht denn die Simulation? Die dürfte helfen, Programmfehler zu 
finden, insbesondere, wenn man den Wert von i verfolgt.

von Joachim B. (jar)


Lesenswert?

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

von WeißerRiese (Gast)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von Dussel (Gast)


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
}

von Joachim B. (jar)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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
von Jim M. (turboj)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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 ?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Draco (Gast)


Lesenswert?

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!

von Dussel (Gast)


Lesenswert?

Was macht deiner Meinung nach das Schlüsselwort static?

von Jim M. (turboj)


Lesenswert?

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
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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än­keln meinst:
 Diesmal wollte ich wirklich nicht plän­keln, war vielleicht etwas zu
 voreilig, entschuldige mich hiermit.

von Draco (Gast)


Lesenswert?

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!)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von Dussel (Gast)


Lesenswert?

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?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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
von Joachim B. (jar)


Lesenswert?

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.

von Huh (Gast)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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än­keln deinerseits.

von Hans M. (Gast)


Lesenswert?

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

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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>

von Ralf G. (ralg)


Lesenswert?

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!"

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

Marc V. schrieb:
> Mit Leerzeichen sieht das nicht so beschissen aus ;-)

sag ich auch, obwohl wie selten einer Meinung sind :)

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Ralf G. schrieb:
> Marc V. schrieb:
>> Ja.
> Nein.

 Doch.

von Ralf G. (ralg)


Lesenswert?

Marc V. schrieb:
> Ralf G. schrieb:
>> Marc V. schrieb:
>>> Ja.
>> Nein.
>
>  Doch.

:-)

von Joachim B. (jar)


Lesenswert?

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
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von Joachim B. (jar)


Lesenswert?

Marc V. schrieb:
> i ist wirklich ein
>  schlechter Name, aber in diesem Fall absolut irrelevant.

hast du den gesamten Code gesehen? ich nicht.

von WeißerRiese (Gast)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Huh (Gast)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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.

von Ingo L. (corrtexx)


Lesenswert?

Oder gibts da evtl. doch den Klassiker unter den Fehlern und die Warnung 
wird ignoriert?:
1
if ( i = 1 )...
;)

von Huh (Gast)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

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.

von Dominik B. (odysseus1710)


Lesenswert?

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
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Dominik B. (odysseus1710)


Lesenswert?

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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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
von WeißerRiese (Gast)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von WeißerRiese (Gast)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von Julian .. (juliank)


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

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.

von Räusper (Gast)


Lesenswert?

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...

von WeißerRiese (Gast)


Lesenswert?

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.

von Räusper (Gast)


Lesenswert?

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 :-)

von WeißerRiese (Gast)


Lesenswert?

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.

von wneudert (Gast)


Lesenswert?

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

von Julian .. (juliank)


Lesenswert?

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....

von WeißerRiese (Gast)


Lesenswert?

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.

von wneudert (Gast)


Lesenswert?

@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

von Julian .. (juliank)


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

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... ;) )

von wneudert (Gast)


Lesenswert?

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

von WeißerRiese (Gast)


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

Na gut.


Der "Pseude-Reset" erklärt dann auch, warum ich 1er (einmal 
inkrementiert) ständig bekommen habe. Danke fürs Aufklären.

von Carl D. (jcw2)


Lesenswert?

Wenn man eine
1
ISR(BADISR_vect) {
2
  // some usefull debug code
3
}
anlegt, dann kann man dieses Problem abfangen.

von WeißerRiese (Gast)


Lesenswert?

Carl D. schrieb:
> Wenn man eineISR(BADISR_vect) {
>   // some usefull debug code
> }anlegt, dann kann man dieses Problem abfangen.

Wieder was gelernt. Merci!

von wneudert (Gast)


Lesenswert?

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

von WeißerRiese (Gast)


Lesenswert?

Danke!

von wneudert (Gast)


Lesenswert?

Problem ist nur, dass es keine BADISR_vect gibt

:)

von Carl D. (jcw2)


Lesenswert?

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

von wneudert (Gast)


Lesenswert?

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 :)

von Carl D. (jcw2)


Lesenswert?

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.....)

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von WeißerRiese (Gast)


Lesenswert?

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.

von WeißerRiese (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.