Problem mit Interrupt

OP #2555340
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
Gast #2555652
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!
OP #2555831
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
OP #2556034
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
Gast #2556124
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.
OP #2556543
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
Angehängte Dateien:
OP #2556633
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
OP #2558482
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
OP #2558952
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren