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