Forum: Compiler & IDEs Problem mit Interrupt


von Sebastian H. (s3b1)


Lesenswert?

Hallo liebe Community. Ich hoffe ihr könnt mir helfen.

Hier erstmal ein Ausschnitt des Codes in dem das Problem steckt:
1
ISR(INT1_vect)
2
{
3
  
4
   //Next Reads
5
   if (e==1)
6
   {
7
      stoptimer();
8
    time=TCNT1; //zeit auslesen
9
    TCNT1=0; //register resetten
10
      MCUCR = (1<<ISC11); //Umschalten auf fallende flanke
11
    starttimer();
12
    c =~ c;  //bit invertieren
13
   }
14
   
15
   if ((time<260) && (time>200)) //wenn Zeit < timeshortmax und Zeit > timeshortmin
16
   {
17
       a <<= 1; //schieben
18
    if (c == -1)  //inverter
19
    {
20
    a |= 0;  //0 Schreiben
21
    }
22
    
23
    if (c == 0)
24
    {
25
    a |= 1;  //1 Schreiben
26
    }
27
   }
28
29
   }
30
   
31
   //First Read
32
   if (e==0)
33
   {
34
      starttimer();
35
    //a<<=1; //schieben
36
    a|=1; //1 schreiben
37
    e++;
38
    MCUCR = (1<<ISC10)|(1<<ISC11); //Umschalten auf steigende flanke
39
    //c =~ c;  //bit invertieren
40
   }
41
   
42
   tmp++; //Step by step debug
43
   
44
   if (tmp==3)
45
   {
46
      e++;
47
   }
48
49
}

Ich beschreibe mal kurz was das Programm macht. Am Anfang triggert der 
INT1 eingang auf die erste Fallende Flanke. Hier soll eine "1" in a 
geschrieben werden (Binär). Das Funtkioniert auch. Die Funktion mit der 
tmp Variable dient dazu nur eine bestimmte Anzahl von Flanken zu 
triggern (hier 3) und das ganze dannach zu beenden.

Nun zu dem Problem. Im 2. Durchlauf sollte das Programm eine "0" in a 
schreiben. Allerdings macht es das nicht. Wenn ich mir dannach den Wert 
von a über Uart ausgeben lasse steht 0 drin... Die time bedingung sei 
hierfür erfüllt. Da über Uart ja nicht "10" ausgegeben wird sondern das 
Dezimale Equivalent hätte ich eigentlich erwartet das eine "2" kommt.

Habt ihr eine Idee wo hier der Fehler stecken könnte?

Achja die Signallänge dauert etwa 880µs.

Grüße aus München
S3B1

von Krapao (Gast)


Lesenswert?

Wie sind a und c definiert?

a sollte volatile gekennzeichnet sein, wg. Sharing mit dem 
Hauptprogramm.
C sollte signed definiert sein wegen der Abfrage c == -1.

Von der Programmlogik her habe ich Verständnisprobleme. Über deinen e 
und dein tmp Mechanismus erwartest du 3 fallende Flanken 
hintereinander iM Abstand von time? Ist das ein Versuch eine 
spezielles Protokoll zu tracen?

Ich würde das komplett zurückfahren und zunächst eine grundsätzliche 
Flankenzählmaschine bauen.

Dabei aufpassen: Wenn a uint8_t definiert ist und du 8-mal a geschoben 
hast, ist a auch 0! Mit deinem Mechanismus kann ich nicht auf Anhieb 
sagen, wieviele Durchläufe die ISR sieht bevor du a im Hauptprogramm 
ausliest. Kannst du das?

Bei einem schnellen z.B. prellenden Signal kann die Zahl 8 sehr schnell 
erreicht werden!

von Sebastian H. (s3b1)


Lesenswert?

Hallo,

a ist als long definiert und c als int.

Ja richtig erkannt. :) Das wird tatsächlich ein Protokoll (RC5). Ich 
weiß auch das es hier massenhaft Programme dafür gibt aber ich möchte 
gerne meinen eigenen Ansatz programmieren (damit ichs auch gscheid lern 
:D)

Also aktuell mit dem tmp == 3 wird erst eine fallende, dann eine 
steigende und abschließen wieder eine fallende flanke beobachtet.

Das mit a als volatile werde ich später gleich mal testen.


Falls das nichts hilft programmier ich testweise eine Flankenzähler. Ich 
werde dann berichten wenn ich das mit a und volatile geändert hab. (Kann 
ich erst machen wenn ich daheim bin so etwa gegen 22:30)


Grüße
S3B1

von Sebastian H. (s3b1)


Lesenswert?

Hallo,

die sache mit volatile ist getestet. Hat leider keine Verbesserung 
gebracht. Interessanterweise kommt jetzt manchmal auch für a == -1. 
Keine Ahnung woran das wieder liegen könnte.

Wenn ich nur diesen Code mache dann kommt die richtige Zahl (je nachdem 
wieviele durchläufe, also wie groß tmp ist):
1
ISR(INT1_vect)
2
{
3
   {
4
      MCUCR = (1<<ISC10)|(1<<ISC11); //Umschalten auf steigende flanke
5
    
6
    //Working !!
7
    a <<= 1; //nach links schieben
8
    c =~ c;  //bit invertieren
9
10
    if (c == -1)  //inverter
11
    {
12
    a |= 1;  //1 Schreiben
13
    }
14
    
15
    if (c == 0)
16
    {
17
    a |= 0;  //0 Schreiben
18
    }
19
    c =~ c;  //bit invertieren
20
    tmp++;
21
   }
22
}

Das Problem ist das ist ja im Endefekt nichts anderes als das was oben 
steht... Außer das oben noch ne IF Schleife ist in der die Zeit 
abgefragt wird.

Ich werde mal den Flankenzähler Programmieren und dann bescheid geben ob 
der Funktioniert. Bin grad irgendwie am verzweifeln.

Grüße
S3B1

von Krapao (Gast)


Lesenswert?

Es hilft, wenn man die Rechenvorschrift in Prosa beschreibt. Danach 
schreibt man den Code. Die Prosa kann man als Kommentar in den Code 
aufnehmen und sich daran lang hangeln. Aus dem Code aus die 
Rechenvorschrift zu kommen ist nur bei trivialen Sachen einfach.

Dein Code in der ISR ist ja vom Design her nicht in der Lage eine 
komplette RC5 Kommandosequenz aufzuzeichnen. Ein wesentlicher Teil 
spielt sich im Anwendungsprogramm ab. Ich verstehe nicht, wie man Hilfe 
sucht, ohne den wesentlichen Code komplett zu zeigen.

von Sebastian H. (s3b1)


Angehängte Dateien:

Lesenswert?

Hallo,

hier der ganze Quellcode. Hoffe das es etwas hilft um das Problem zu 
finden. Der Teil ist momentan auskommentiert da ich ja aktuell den 
Flankenzähler Programmiere.

Soll ich noch einen Screenshot von dem Signal anhängen? Würde das auch 
noch etwas helfen?

Der Code in der ISR soll ja auch noch nicht das ganze Signal aufnehmen 
sondern erstmal nur 3 Flanken. Wollte damit testen ob der Code überhaupt 
funktioniert, was ja leider nicht der Fall ist.

Grüße
S3B1

von Sebastian H. (s3b1)


Lesenswert?

Nachtrag:
Das Hauptprogramm macht aktuell nichts anderes als das es mir über Uart 
die Werte der verschiendenen Variablen ausgibt. (zum Debuggen).

von Sebastian H. (s3b1)


Lesenswert?

Hallo,

doof das man nur Beiträge editieren kann die Jünger als 15 Minuten 
sind...


Habe jetzt den Flankenzähler programmiert und getestet. Der Funktioniert 
wunderbar. 11 Fallende und 11 Steigende Flanken werden registriert. So 
wie ich es auch auf meinem Oszi nachgezählt hatte.

Somit funktioniert also das Triggern auf die Flanken. Jetzt muss ich nur 
noch rausfinden warum die geschichte mit dem geposteten Code nicht 
funktioniert.


Grüße
S3B1

von Sebastian H. (s3b1)


Lesenswert?

Hab den Fehler gefunden. Weiß allerdings nicht wie ich das lösen kann.

Zur Hardware: Verwende einen Atmega 16


Zum Problem: Anscheinend macht der mir auch aus einem int32_t immer eine 
16bit Variable. Damit überläuft selbige und fängt bei - wieder an.
Wie kann ich mit AVR-GCC und dem ATmega 16 eine 32Bit Variable nutzen 
oder ist dies vielleicht sogar gar nicht möglich?

Habe folgende Includes:
#include <inttypes.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <inttypes.h>

damit sollten ja eigentlich auch 32 Bit Variablen gehen. Oder 
unterstützt vielleicht itoa nur 16 Bit?

Grüße
S3B1

von Stefan E. (sternst)


Lesenswert?

Sebastian H. schrieb:
> Oder
> unterstützt vielleicht itoa nur 16 Bit?

Ja.
Für int32_t ltoa nehmen.

von Oliver (Gast)


Lesenswert?

Natürlich kannst du 32-bit-Variablen nutzen. Aber:

int ist beim avr-gcc nunmal nur 16 bit, und itoa ist so definiert:

http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga4f6b3dd51c1f8519d5b8fce1dbf7a665

Ergo geht itoa nicht mit 32 bit. Aber...

da gibts ja noch ltoa ;)

Oliver

von Sebastian H. (s3b1)


Lesenswert?

You just made my day....

Danke :)

von Sebastian H. (s3b1)


Lesenswert?

So jetzt funktioniert alles. Danke an allen die mir geholfen haben.

Grüße
S3B1

von Sebastian H. (s3b1)


Lesenswert?

Hab da noch ne doofe Frage:

Beispiel:
1
while (1)
2
   {
3
      if (bla<1)
4
         {
5
            bla++;
6
         }
7
   }

Warum funktioniert dieser Code nicht aber folgender:
1
while (1)
2
   {
3
      if (bla<1)
4
         {
5
            bla++;
6
         }
7
      if (bla==1)
8
         {
9
            return 0;
10
         }
11
   }

Müssen in einer while schleife mind. 2 If schleifen vorkommen oder gar 
keine?

Weil rein funktionstechnisch macht es ja keinen großen unterschied oder?

Grüße
S3B1

von Karl H. (kbuchegg)


Lesenswert?

Sebastian H. schrieb:

>
> Warum funktioniert dieser Code nicht

Definiere "funktioniert nicht"

(und behalte dabei immer im Hinterkopf, dass ein optimierender Compiler 
alles mögliche im Code entdecken kann und sich kaum eine Gelegenheit 
entgehen lässt um Dinge, die keinen Sinn und kein Auswirkungen auf den 
Programmlauf haben, einfach wegzuoptimieren)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?


von Sebastian H. (s3b1)


Lesenswert?

Ich vermute das er die if schleife wegoptimiert weil sie wohl für den 
Compailer keinen sinn hat.

Nicht funktionieren heißt er macht kein bla++;

Hingegen wenn die zweite if schleife drin ist schon.

Grüße
S3B1

von Johann L. (gjlayde) Benutzerseite


Lesenswert?


von Sebastian H. (s3b1)


Lesenswert?

Danke nochmal. Habt mir sehr geholfen. Habe bei dem Projekt wieder jede 
Menge übers Programmieren gelernt.

Grüße
S3B1

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.