Forum: Mikrocontroller und Digitale Elektronik Frage zu "USART Receive Complete" Atmega8


von Geyer (Gast)


Lesenswert?

Guten Abend zusammen,

ich Arbeite mich gerade mit dem Buch von Roland Walter in die AVR 
Microcontroller Technik ein.

Ich habe eine Verständnis Frage zu dem "USART Receive Complete" 
Interrupt.

Ich lebe in der Annahme das wenn ich zwei Zeichen zu meinem 
Microcontroller sende bei einer niedrigen Baudrate zwischen beiden 
Zeichen genug zeit sein sollte um das Hauptprogramm einige male 
durchlaufen zu können.
So wie ich es verstanden habe wird das "USART Receive Complete" 
Interrupt ausgelöst wenn ein byte im UDR fertig zur abfrage ist.
Im Interrupt sollte es dann nur ausgelesen werden und zum Hauptprogramm 
zurückkehren bis ein neues Zeichen komplett empfangen ist.

Wenn ich nun aber auf einen Schlag mehrere Zeichen sende z.B. "Hallo 
Welt", bleibt mein Microcontroller den kompletten Zeitraum in der 
Interrupt Routine und führt das Hauptprogramm nicht ein einziges mal 
aus, bis das letzte Zeichen empfangen wurde.

Könnte mir jemand erklären warum das so ist? Warum wird zwischen den 
Zeichen kein einziges mal das Hauptprogramm ausgeführt?

Lg
Geyer

von H.Joachim S. (crazyhorse)


Lesenswert?

Es liegt an deinem Programm.
Das was du erwarest ist genau das wie es normalerweise gemacht wird.

von g457 (Gast)


Lesenswert?

> Könnte mir jemand erklären warum das so ist?

Designfehler im nicht hergezeigten Code. Behelfsweise ein Bug an der 
selben Stelle.

von Geyer (Gast)


Lesenswert?

dann hier nochmal der Basic Programm Code.
Wenn ich nun mehr als 10 Zeichen sende wird das Hauptprogramm erst 
ausgeführt wenn alle Zeichen übertragen wurden.
1
$Regfile = "m8def.dat"
2
$Crystal = 3686400
3
$Baud = 9600
4
5
Dim s As String*10
6
7
On URXC OnRxD
8
Enable URXC
9
Enable Interrupts
10
11
Main:
12
  If Len(s)>9 Then
13
    Print s
14
    s=""
15
  End if
16
Goto Main
17
18
OnRxD:
19
  s=s+Chr(UDR)
20
Return

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Geyer schrieb:
> Wenn ich nun aber auf einen Schlag mehrere Zeichen sende z.B. "Hallo
> Welt", bleibt mein Microcontroller den kompletten Zeitraum in der
> Interrupt Routine und führt das Hauptprogramm nicht ein einziges mal
> aus, bis das letzte Zeichen empfangen wurde.

Nö, tut er nicht. Er ist sogar 99.999% der zeit im Hauptprogramm. 
Jedesmal wenn ein einzelnes zeichen empfangen wurde, springt er in den 
Interrupt-Handler, speichert das Zeichen, und kehrt wieder zurück, 
solange bis das nächste Zeichen empfangen wurde.

Allerdings wartet dein Hauptprogramm und tut solange nichts, bis 10 
zeichen empfangen wurden.

von H.Joachim S. (crazyhorse)


Lesenswert?

Geyer schrieb:
> OnRxD:
>   s=s+Chr(UDR)
> Return

ups, das sieht aber irgendwie bösartig aus...
Was passiert denn, wenn sich gerademal keiner um s kümmert? Frisst s den 
gesamten RAM?

Die Lösung für dein eigentliches Problem steht ja bei Michael - also 
neue suchen :-)

von Geyer (Gast)


Lesenswert?

Aber auch wenn ich 20 Zeichen sende, bekomme ich erst eine Rückmeldung 
wenn alle 20 Zeichen gesendet wurden. Er gibt mir keine 10 zurück wenn 
diese angekommen sind, sondern erst wenn alle 20 angekommen sind. Und 
dann eben auf einen Schlag die 20. Ergo hat er den Test ob der String 
länger als 9 ist wohl nicht ausgeführt.

Ich habe aus neugier mal einen Buzzer im Hauptprogramm summen lassen, 
und während ich Zeichen an den Microcontroller gesendet habe war der 
Buzzer komplett aus. Der Microcontroller hat das Hauptprogramm also 
nicht ausgeführt.

Auf jedenfall schon mal danke für die Hilfe :)
Aber irgendwas arbeitet hier gegeneinander.
Kann es vielleicht Probleme machen wenn während dem Empfangen von Daten 
schon zurück gesendet werden soll?

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Ich glaub dir nicht. Zumindest solange nicht, bis du nicht den 
kompletten Quellcode (soweit reduziert dass der Fehler noch auftritt) 
hier postest.

Kein uC bleibt freiwillig in der ISR. Außer du sagst ihm dass er soll. 
Merke: Das programm macht was du schreibst, nicht was du willst.

von Geyer (Gast)


Lesenswert?

Das ist der komplette Quellcode eins zu eins aus dem oben genannten Buch 
abgetippt. Ich bin dabei mich in das Thema einzuarbeiten, warum sollte 
ich da lügen? :)

Ich benutzen einen USB zu rs232 Konverter, kann dieser das Signal 
beeinflussen? eigentlich auch nicht oder?

Ich teste auf jedenfall nochmal den Code, und melde mich gleich nochmal 
ob der obige Zustand reproduzierbar ist.

von Geyer (Gast)


Lesenswert?

Gut, ich weis an welcher stelle das Problem verursacht wird.

Ich habe diesen Code genommen und anhand eines Buzzers an Pin PB0 
"erhöhrt" wann das Hauptprogramm durchlaufen wird (ton/stille) und wann 
nicht.
1
$regfile = "m8def.dat"
2
$crystal = 3686400
3
$baud = 9600
4
5
Dim S As String * 10
6
7
8
Ddrb.0 = 1
9
10
On Urxc Onrxd
11
Enable Urxc
12
Enable Interrupts
13
14
Main:
15
   If Len(s) > 9 Then
16
      Print S
17
      S = ""
18
   End If
19
   Portb.0 = Not Portb.0
20
   Waitms 5
21
Goto Main
22
23
Onrxd:
24
   S = S + Chr(udr)
25
Return


Wenn der Code wie oben genannt durchläuft ist der Buzzer wenn ich ihm 
z.B. 300 Zeichen sende über einen eindeutigen Zeitraum komplett aus.
Wenn ich den "Print S" befehl weg lasse, und sonst alles gleich ist, 
bleibt der Buzzer auch während 300 an, aber auf einer geringeren 
Frequenz.

Ich habe mich nun auch etwas Informiert:
Der Print befehl Pausiert das Programm bis sämtliche Zeichen welche 
gesendet werden sollen auch tatsächlich raus sind.

Daraus meine Annahme:
Da in dem Beispiel der Print befehl erst ausgelöst wird wenn mindesten 9 
Zeichen zu schreiben sind und die Eingehenden Zeichen etwa in der 
Gleichen Frequenz eingehen wie ausgehende wird der String während er im 
Print Vorgang ist konstant verlängert bis keine Zeichen mehr eingehen 
und der Print befehl das String ende erreicht. Während also der 
Interrupt mehrere male ausgelöst wird bleibt das Hauptprogramm sobald es 
das erste mal den Print befehl erreicht immer an dieser Stelle und führt 
bis alle Zeichen eingegangen sind das Hauptprogramm kein einziges mal 
mehr komplett aus.

Vielen Dank für diese Hilfe zur Selbsterkenntnis :)
Ich hab den Fehler einfach an der Falschen stelle gesucht.

Hoffentlich stößt irgendwer einmal auf das hier und erspart sich dadurch 
das elendigliche Fehlersuchen suchen :)
und bitte unterstellt keinem Anfänger mehr das Lügen.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Geyer schrieb:
> Während also der
> Interrupt mehrere male ausgelöst wird bleibt das Hauptprogramm sobald es
> das erste mal den Print befehl erreicht immer an dieser Stelle und führt
> bis alle Zeichen eingegangen sind das Hauptprogramm kein einziges mal
> mehr komplett aus.

Klingt vernünftig! Leider hab ich das PRINT übersehen...

Geyer schrieb:
> und bitte unterstellt keinem Anfänger mehr das Lügen.

Keine Angst, ich hab dir nicht "Lüge" unterstellt. Es ist nur leider so, 
dass hier dauernd (mehrmals täglich) eins von diesen (oder beides 
zusammen) passiert:

a) Code wird nicht reinkopiert sondern abgeschrieben, beim Abschreiben 
passieren Fehler, und wir suchen dann Fehler wo keiner ist

b) Code wird unvollständig gepostet. Es fehlen Deklarationen, ISR, ... 
oft stekt der Fehler in diesen weggelassenen Stellen, und dann müssen 
wir wieder raten.

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.