PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : UART empfangen



hacker
12.01.2006, 17:39
Hi,

ich will ganze Strings empfangen können. Auf der Suche bin ich dann auf den Befehl "Input" gestoßen. Wie funktioniert dieser Befehl? So wie ich das aus dem Beispieldateien von Bascom rauslese, wartet dieser Befehl immer, bis ein Sting empfangen wurde. Also wenn nix kommt, geht im Programm auch nicht weiter? Oder muss ich den Befehl immer wieder abfragen, also so ne Art Pollen. Aber dann gehn mit ja unter Umständen Daten verloren...was nicht so schön wäre. Das beste wärs natürlich, wenn der Befehl Interrupt gesteuert wäre...aber ich glaube nicht, dass das der Fall ist...oder doch? Könnt ihr mir dann noch einen alternativen Befehl nennen, der Interrupt gesteuert ist? (nach Möglichkeit, wo man gleich ganze Strings empfangen kann. Nicht alle Zeichen einzeln empfangen und dann zu einem String zusammen zu fügen. Das mach ich dann, wenns sonst überhaupt keine Alternative mehr gibt.)

Gruss Hacker

BlueNature
12.01.2006, 17:46
Servus!

Input blockt dir den Programmfluss, ist also nicht gut. Mußt das über den UART machen, die Register und Funktinen findest du im betreffenden Datenblatt des AVR's. Interrupts sind hardwaregrundlage im AVR, also löst das eintreffen eines neuen Bytes einen Int aus den du nutzen kannst, aber eben immer nur ein Byte und alles von 0 bis 255!

Grüße Wolfgang

Rage_Empire
12.01.2006, 18:22
Schau mal in der Hilfe nach:
Input
Waitkey
Inkey

chr-mt
12.01.2006, 18:48
Noch ein netter Befehl: "Timeout"
Wenn der controller auf Daten per Input wartet, aber keine kriegt, dann bleibt er normalerweise stur in der Input Routine stecken.
Mit Timeout kann man festlegen, wann der Input Befehl übersprungen wird, falls keine Daten kommen.
Hab's nur gelesen, aber noch nicht ausprobiert.

Gruß
Christopher

hacker
12.01.2006, 19:01
Ich muss jetzt leider weg und kann das nicht alles ausprobieren. Danke schonmal für eure Antworten. Wahrscheinlich wirds dann doch drauf rauslaufe, dass ich die einzelnen Bytes zusammen fügen muss.

Gruss Hacker

BlueNature
13.01.2006, 07:28
Servus Hacker!

Machs besser Byte für Byte von Hand, dann kannst das neue Byte im UART-Int-Vektor abholen und in ein Byte-Array schreiben nacheinander wie es kommt und dann meinetwegen zu einem String zusammenbauen aus der Folge der ASCII-Zeichen mit einer Wandlung von Byte-Wert in Zeichen das es für einen String passt.

Kannst dir so deine Bytes ecoen lassen:

Do
TmpByte = Waitkey()
Print Chr(TmpByte);
Loop

Oder diekt (ASCII-Code):

Do
TmpByte = Waitkey()
Print TmpByte;
Loop

Grüße Wolfgang

oe9vfj
13.01.2006, 10:06
Eine Möglichkeit ist den String im Hintergrund zu empfangen und INPUT nur dann aufzurufen, wenn das Zeilenende-Zeichen (&H0D) empfangen wurde.
Für den Hintergrundempfang gibt es bei BASCOM-AVR den Befehl SERIALIN (Schau dazu in der Hilfe nach). Da gibt es neues Feature, welches eine Anwenderroutine aufruft, wenn ein bestimmtes Zeichen (z.B. Zeilenende) empfangen wurde.


Config Serialin = Buffered , Size = 80 , ByteMatch = 13
Dim CR_Received as Byte
Diese Zeile legt einen Buffer von 80 Zeichen an, bindet die ISR-Routine ein, welche die Zeichen im Hintergrund empfängt und ruft Serial0CharMatch auf, wenn das Zeichen mit den ASCII-Code 13 (=Carriage Return/Zeilenende) empfangen wurde.
Nach dem Label Serial0CharMatch kann der Anwender einen Programmteil implementieren und mit RETURN abschließen, welcher die gewünschte Aktion beim Empfang des bestimmten Zeichens ausführt.
Da dieses aber in der Interruptroutine ausgeführt wird, sollte hier nur ein Flag (Byte CR_Reiceived ist 0 oder 1) gesetzt werden, welches dann in der Anwendung selbst abgefragt wird.


Serial0CharMatch:
CR_Received = 1
return
Zu beachten ist, dass in dieser Interrupt-Routine nur die Register r0, r16, r24, r25, r26 und r27 gerettet sind. Daher können in diesem Programmteil entweder nur diese Register verwendet werden oder die entsprechenden Register müssen zusätzlich mit PUSH/POP gerettet werden. Da diese Wertzuweisung CR_Received = 1 aber nur r24 verwendet, muss hier nichts weiter unternommen werden.


Im Hauptprogramm kann wie in folgendem Code-Teil angeführt auf die Eingabe einer kompletten Zeile reagiert werden:


' Hauptschleife
DO

' anderer Programmcode
'------------------------------------------------------------------
Disable Interrupts
If Cr_received = 1 Then
Cr_received = 0 ' ISR-Flag zurücksetzen
Enable Interrupts
Input EmpfangsString
' Nun kann der String weiterbehandelt werden
Else
Enable Interrupts ' Keine Zeilenende, Interrupt wieder einschalten
End If
'------------------------------------------------------------------

' anderer Programmcode

LOOP

End


Damit die Interrupt-Routine und das Hauptprogramm nicht gleichzeitig das Flag CR_Received ändern, wird hier während der Abfrage und Änderung der Interrupt gesperrt.

Noch eine Bemerkung:
Der in Serialin definierte Empfangsbuffer muss natürlich die Länge der längsten Eingabezeile (plus einige Reservebytes) haben.

super_castle
13.01.2006, 11:26
verbinde rtx mit int0 unf benutze den int0 ausgaberoutine..


Castle

BlueNature
13.01.2006, 13:04
Servus Castle!

Wozu soll das gut sein den RXD mit INT0 zu verbinden? Bei jedem Bitwechsel in den seriellen Daten triggert dir da nur der INT0 und springt in den INT0-Vektor. Wozu gibts denn extra den UART-Int-Vektor? Der triggert wenn wirklich Daten sicher da sind und ist extra dafür vorgesehen worden. Der INT0 ist eine reine Performance-Vernichtung und übel umständlich.

Grüße Wolfgang

super_castle
13.01.2006, 13:31
Einfach für den Anfänger...

Int0 Falling
Enable Int0
Enable Interrupts

Do
Print "was sonst noch läuft..." ' zum PC
WaitMs 255
Loop

End

Interrupt Int0(), Save 2
Disable Int0
Input serielle_vom_pc
Cls
Lcd serielle_vom_pc ' ausgabe auf LCD
Reset Int0
Enable Int0
End Interrupt

hacker
13.01.2006, 14:42
Danke für eure Antworten. Werd jetzt jedes einzelne Byte mit Interrupt empfangen und setzt die dann als String zusammen.

Gruss Hacker