Interruptroutine funktioniert nicht richtig

#1399647
Lesenswert?

Kann mir jemand sagen warum dieser Code nicht funktioniert ?
Auf die Zeile -> while (bit_is_clear(PIND,PD2)); reagiert der Mega8 
nicht.
Es kommt jedesmal zum Überlauf in der Pausenroutine -> zähler ist dann 
10008

Die Routine soll 8 Bits an INT0 auswerten.
1 = 100us/300us Puls/Pause
0 = 300us/300us Puls/Pause
1
void Empfang_Bit(void)
2
{
3
  zaehler=0;
4
  status=1;
5
  do
6
    {
7
    zaehler++;
8
    if (zaehler > 10005) 
9
      {
10
        status=0;
11
        break;
12
      }
13
    }
14
  while (bit_is_set(PIND,PD2));
15
  if (zaehler<3000) 
16
   {
17
     rxbyte=rxbyte*2;
18
    rxbyte=rxbyte+1;
19
   }
20
   else
21
   {
22
     rxbyte=rxbyte*2;
23
   }
24
}
25

26
void Empfang_Pause(void)
27
{
28
  zaehler=0;
29
  status=1;
30
  do
31
    {
32
    zaehler++;
33
    if (zaehler > 10007) 
34
      {
35
        status=0;
36
        break;
37
      }
38
    }
39
  while (bit_is_clear(PIND,PD2));
40
}
41

42
ISR(INT0_vect) //Interruptroutine steigende Flanke an INT0
43
{
44
  uint8_t bitcnt;
45
  rxbyte = 0;
46
  Empfang_Bit();
47
  if (status==0) {rxbyte=0;return;}
48
  for (bitcnt=1;bitcnt<7;bitcnt++)
49
    {
50
    Empfang_Pause();
51
    if (status==0) {rxbyte=0;return;}
52
    Empfang_Bit();
53
    if (status==0) {rxbyte=0;return;}
54
    }
55

56
}

Gruß

Günter
#1399672
Lesenswert?

Guenter B. schrieb:

> Es kommt jedesmal zum Überlauf in der Pausenroutine -> zähler ist dann
> 10008

Wie stellst du das fest? Oder besser: wo? Ich vermute, dass du eine 
entsprechende Abfrage im main-Code hast.
Es gibt dann zwei Dinge:
1) Sind die beteiligten Variablen volatile deklariert?
2) Ist dir bewusst, dass nach dem Empfang der 8 Bits die ISR sofort 
wieder ausgeführt wird, und versucht weitere 8 Bits zu empfangen?
#1399799
Lesenswert?

Stefan Ernst schrieb:

> Wie stellst du das fest? Oder besser: wo? Ich vermute, dass du eine
> entsprechende Abfrage im main-Code hast.
Ja ich habe dort eine LCD-Ausgabe.

> Es gibt dann zwei Dinge:
> 1) Sind die beteiligten Variablen volatile deklariert?
Die Variablen habe ich gleich zu Beginn noch vor der Main-Routine als 
volatile deklariert.

> 2) Ist dir bewusst, dass nach dem Empfang der 8 Bits die ISR sofort
> wieder ausgeführt wird, und versucht weitere 8 Bits zu empfangen?
Ich habe mal drüber nachgedacht und zu Beginn der ISR CLI() und am Ende 
SEI()
gestzt, aber das mach der AVR ja eigentlich eh automatisch. Wie kann ich 
es sonst verhindern ?

Zumindest müste ja ein Byte ordentlich eingelesen werden.
Mit DDRD=0x00 habe ich PortD als Eingang deklariert.
Oder kann man den Pin nicht als INT0 deklarieren und gleichzeitig in der 
Routine seinen Status überprüfen ?
#1399810
Lesenswert?

Guenter B. schrieb:

>> Es gibt dann zwei Dinge:
>> 1) Sind die beteiligten Variablen volatile deklariert?
> Die Variablen habe ich gleich zu Beginn noch vor der Main-Routine als
> volatile deklariert.

mur einzelne Code-Fragmente posten ist zu 99% eine schlechte Idee...

>> 2) Ist dir bewusst, dass nach dem Empfang der 8 Bits die ISR sofort
>> wieder ausgeführt wird, und versucht weitere 8 Bits zu empfangen?
> Ich habe mal drüber nachgedacht und zu Beginn der ISR CLI() und am Ende
> SEI()
> gestzt, aber das mach der AVR ja eigentlich eh automatisch. Wie kann ich
> es sonst verhindern ?

afaik:
cli() wird schon gemacht, allerdings wird die nächste Flanke am INT 
trotzdem das entsprechende Bit INTF0 in GIFR setzen (es wird nur nicht 
zum Anfang der ISR gesprungen, weil eben cli() ), welches dann nach dem 
automatischen sei() am Ende der ISR den nächsten Interrupt auslöst. 
Versuch mal, das entsprechende Bit am Ende der ISR zu löschen...
#1399885
Lesenswert?

Justus Skorps schrieb:

> mur einzelne Code-Fragmente posten ist zu 99% eine schlechte Idee...

Hast recht.

Bin allerdings gerade unterwegs und habe den Code nicht vorliegen.

Der Rest des Programmes besteht momentan nur aus der Deklaration:

INT0 bei steigender Flanke
DDRD=0*00

und der Main-Routine:

Ausgabe von zaehler auf LCD zur Kontrolle

Günter
#1399893
Lesenswert?

Guenter B. schrieb:

> Zumindest müste ja ein Byte ordentlich eingelesen werden.

Aber selbst wenn ein Byte ordentlich eingelesen wird, siehst du das im 
main-Code nicht, weil sofort nach dem Ende der ISR der Interrupt wieder 
auslöst (*), und die Werte des erfolgreichen Einlesens überschreibt.

(*) Das Warum und die Beseitigung hat Justus schon gepostet.
Gast #1403536
Lesenswert?

>Es funktioniert durch Löschung des Interruptflags.

Um welchen Controller handelt es sich denn eigentlich?
Das Interrupt-Flag braucht man eigentlich nicht anfassen, wenn eine ISR 
vorhanden ist. Dann kümmert sich der Controller (meist) ganz alleine um 
die Flags.
Deine Lösung fällt aus meiner Sicht unter "fieses Gebastel"; das ist 
aber meine völlig unbedeutende Meinung, die ich einfach nur aus 
Geltungssucht loswerden musste.
#1403550
Lesenswert?

Es handelt sich um einen Mega8.
Das Problem war ja, dass der Controller beim 2 Bit des auszuwertenden 
Bytes schon wieder eine Interruptanforderung bekam.
Wenn die ISR 8 Bits oder eventuell auch die Störung auf der Leitung (das 
Signal wird per 8xxMHz-Funkmodul übertragen)abgearbeitet hat, setzte ich 
am Ende der ISR durch setzen des Interruptsflag das Interruptflag 
zurück.
Gast #1403835
Lesenswert?

>Wenn die ISR 8 Bits oder eventuell auch die Störung auf der Leitung (das
>Signal wird per 8xxMHz-Funkmodul übertragen)abgearbeitet hat, setzte ich
>am Ende der ISR durch setzen des Interruptsflag das Interruptflag
>zurück.

Und was machst du, wenn Störungen auftreten? Dann kommen deine Bits doch 
völlig durcheinander.

Oliver
#1403927
Lesenswert?

Oliver schrieb:

>
> Und was machst du, wenn Störungen auftreten? Dann kommen deine Bits doch
> völlig durcheinander.
>

Ich lebe damit :-)

Es kommen nur 3 von 256 Bitkombinationen in Betracht.
Wenn eine Störung zufällig mal eines dieser Bitmuster produziert, kann 
ich damit leben, da es sich nur um eine Anzeige handelt: Leer - Voll - 
Übervoll

Der Sender sendet alle 15 Minuten ein Lebenszeichen. Ausserdem sendet er 
bei Statusänderung den aktuellen Zustand.
Gast #1403955
Lesenswert?

>> Und was machst du, wenn Störungen auftreten? Dann kommen deine Bits doch
>> völlig durcheinander.

>Ich lebe damit :-)

Nun ja, nach meinem Verständnis deines Codeschnippels kommt das Programm 
nur alle 8 Impulse aus der ISR. Ein falsches Bit stört da vielleicht 
nicht, soweit hast du Recht, ein zusätzliches dagegen schon. Und bei 
externen Interrupts und/oder Funkstrecken soll das schon mal vorkommen.
Sobald sich da einmal eine Störung dazwischen gemogelt hat, geht nix 
mehr.

Oliver

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