PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Mehrere Zeichen aus dem seriellen Buffer lesen.



tobimc
25.07.2004, 13:19
Hi

Ich habe ja gestern diese Serielle komunniktionsgeschichte gebaut.
Jetzt gibt's wieder ein Problem:
Wie kann ich mehrere _Zeichen_ in EINE String Variable lesen?
mit Inkey() geht das wunderbar. Ich möchte nur 3 Zeichen od. mehr auf einmal einlesen...
Nicht das ihr jetzt denkt. Es muss aus dem Buffer sein.

Ich verwende einen Atmel AT90S4433.

Liebe Grüße und DANKE schon mal...,
Tobi

tobimc
25.07.2004, 14:44
HI

wisst ihr nicht wie ich meine?
Also nich ein Erklärungsversuch:

Ich möchte dem Slave Prozessor Befehle schicken. Die sollen
mind. 3 Zeichen lang sein. Und diese 3 Zeichen will ich auf einen Rutsch aus dem Seriellen-Input-Buffer lesen und in eine String-Variable schreiben, sodass ich sie schön auswerten kann.

Das geht doch beim PC auch. Ich schick dem "Hallo Computer" über RS232 und der gibt's auf einmal aufm Bildschirm aus.

Wisst ihr jetzt was ich meine?

Wo sind die BASCOM-Spezialisten?? :)

Freue mich über jede Antwot... ;)

Liebe Grüße, und Danke schon jetzt...

Tobi

Freiheitspirat
26.07.2004, 11:53
Suchst Du so etwas in der Richtung ?


Config Serialin = Buffered , Size = 3
Taste = Inkey()
While Taste > 0
String = String + Chr(taste)
Taste = Inkey()
Wend

tobimc
26.07.2004, 13:47
HI Freiheitspirat

Der Code sieht gut aus.
das Problem ist, das er auf meinem momentanem System nicht funktioniert. Hast du ihn getestet?

Welche Variablentypen haben 'Taste' und 'String'? String -> String, aber wie groß?

Meine Master sendet ununterbraochen "res" in einer Endloßschleife.
Wenn der Slave das Erkennt, sol eine LED angehen.

Liebe Grüße und Danke schon mal!, Tobi

Freiheitspirat
26.07.2004, 14:59
Taste ist Byte und String ist halt String, Länge natürlich so lang, das Deine Befehle rein passen, selbiges gilt natürlich auch für den "Size" im "Config".
Sind Deine gesendeten Befehle mir "CR" abgeschlossen ?
Dann natürlich ein Byte mehr vorsehen und ggf. einen Gruppenwechsel einproggen.



If Taste = 13 then
If String = 'res' then
Gosub Ledan
End If
String = ""
End If


Wenn Du weitere Hilfe brauchst, mußt Du mir aber schon sagen, was genau NICHT funktioniert, ich kann nicht hellsehen.

Woraus besteht Dein "System" ?
Hast Du Compilererrors ?
Kannst Du überhaupt Daten per RS232 empfangen ?
Ich kenn den AT90S4433 nicht genau, aber er kann doch den "Config Serial" oder ?


P.S.:
Kommt ein Anwender zu Systemadministrator und sagt: "Mein Rechner funktioniert nicht."
Fragt der Administrator: "Was haben Sie denn gemacht ?"
Anwender: "Gar nichts !"
Administrator: "Sehen Sie, dann kann auch nichts funktionieren..."

tobimc
26.07.2004, 20:08
Hi Freiheitspirat!

Ich habe keine Compilerprobleme.
Als ich Config Serialin usw. in den SLAVE-code eingefügt habe,
was der Code schlagartig um 4% größer, und funktionierte nicht mehr.

Mein System:

Der Masterprozessor (Mega16) sendet über UART zum Slave Befehle.
Der Slave(AT90S4433) soll auf die antworten.

Der AT90S4433 funktioniert mit einstelligen Kommandos tadellos.

Mastercode:



Dim C As Byte
Dim D As String * 5
$baud = 9600


Sound Portd.2 , 100 , 1000
Wait 1

Begin:

Do
Print "1"
D = Inkey()

If D = "2" Then
Sound Portd.2 , 1000 , 500
Waitms 50
Print "3"
Exit Do
End If

Loop



Do
D = Inkey()

If D = "4" Then
Sound Portd.2 , 1000 , 1000
Waitms 50
Print "res"
Exit Do
End If
Loop

Goto Begin

End


^^ Der Master sendet "1" in einer Endloßschleife, bis der Slave mit 2 antwortet.
Dann sendet er genauso 3 und wartet, bis der slave mit 4 antwortet.
Dann sendet er "res" ein Resetbefehl. Den soll der Slave empfangen und wieder an den Anfang des Programms springen.



$baud = 9600
$crystal = 8000000

Config Serialin = Buffered , Size = 3

Dim A As Byte
Dim B As Byte
Dim C As String * 5

Waitms 1250

Begin:

Do
B = Inkey()

If B = "1" Then
Portd.2 = 1
Print "2"
Exit Do
End If
Loop

Portd.2 = 0

Do
B = Inkey()

If B = "3" Then
Portd.2 = 1
Print "4"
Exit Do
End If
Loop

Portd.2 = 0

'While B > 0

'C = C + Chr(b)
'B = Inkey()

'If C = "res" Then
' Portd.2 = 1
'Wait 2
'Print "4"
'Exit Do

End If
Loop
'Wend

Goto Begin

End


Hier das Gegenstück.
Das untere ist der Versuch, das res Kommando mit deiner Methode zu empfangen.
Wie gesagt: Wenn das Config-Kommando gesetzt ist, geht nix mehr.

Ich weis nicht, ob ein \cr mitgeschickt wird.
Wie du siehst, benutze ich den normalen Print-Befehl.

Weist du jetzt, das du wissen musst, um mir zu helfen?????
Wenn nicht, sag's mir!

Danke, bis hier...

Liebe Grüße, Tobi

Freiheitspirat
26.07.2004, 22:33
Hallo tobimc,

Dein Code sieht gar nicht so schlecht aus.
Es gib zwei Sachen, die Du noch berücksichtigen mußt:

1. Inkey() liefert den Zeichencode nicht das Zeichen zurück !
Der Zeichencode (oder ASCII-Code) ist numerisch (Byte)
Z.B. 65 = "A", 66="B"; 48="0", 49="1" ; 32=Space,13=CR
Umwandeln kann man ihn mit chr() und ungekehrt mir asc(), also:
If chr(Inkey()) = "1" then
ist das selbe wie
If Inkey() = 49 then
ist das selbe wie
If Inkey() = asc("1")

2. CR = cariage return / Entertaste
Wenn man ein Terminalprogramm hat, in dem man die Zeichen per Tastatur eingibt, ist das Drücken der Entertaste = Zeichen 13
Der Printbefehl kann entweder mit oder ohne Semikolon geschrieben werden.
Bei Print "Hallo"; Print "Welt" wird beides direkt nacheinander ausgegeben (HalloWelt).
So wie Du es machst wird an jedes Print ein chr(10) und chr(13) angehängt, um in eine neue Zeile (10=LF/Line feed) und ein Enter(13) automatisch mit zu schicken.

Probiere mal am besten ein kleines Programm mit
Do while true
x = inkey()
print x ; chr(X)
Loop
und sehe Dir das Ergebnis in einem Terminalfenster Deines PC's an, während Du ein paar Tasten drückst...

tobimc
27.07.2004, 11:41
Hi Freiheitspirat!

Das mit dem ASCI-Code habe ich mir fast gedacht.
Aber wiso funktionniert der Code dann mit einstelligen
Zahlen?

Ich kann im moment meinen PC nicht anschließen, der MAX ist noch nicht ganz fertig.

Wie müsste der Slave-Code aussehen, wenn man es richtig macht?
Ich bin noch nicht so stark in Bascom.

Er soll einfach das "res" Komanndo empfangen und dann
irgendetwas tun

Für einen kleinen Codeschnipsel wäre ich dir sehr sehr dankbar!!!!!

Vielen Dank bis hier,

Liebe Grüße, Tobi

Freiheitspirat
27.07.2004, 12:17
Aber wiso funktionniert der Code dann mit einstelligen
Zahlen?

Die Definition Byte ist numerisch
Die Definition "1" ist ein String

Der BASCOM-Compiler ist so tolerant, das er automatisch den String "1" in einen numerischen Wert umwandelt.
Andere Compiler geben einen Fehler aus, denn richtig wäre ja wie gesagt:
B=inkey()
If B = asc("1") Then
Bei Strings mit größeren Längen (z.B. "res") würde das nicht mehr gehen.
(Ich bin mir jetzt nicht sicher ob ein Compilefehler kommt, oder nur der erste Buchstabe ("r") konvertiert wird)



Für einen kleinen Codeschnipsel wäre ich dir sehr sehr dankbar!!!!!


Die Codeschnipsel habe ich Dir doch gegeben, soll ich Dir etwa Dein ganzes Programm schreiben ???



$baud = 9600
$crystal = 8000000

Config Serialin = Buffered ,Size = 20

Dim A As Byte
Dim B As String * 1
Dim C As String * 20

Waitms 1250

Begin:

C = ""
Do
A = Inkey()
B = chr(A)
C = C + B

If B = "1" Then
Portd.2 = 1
Waitms 1250
Portd.2 = 0
Print "2"
C = ""
End If
If B = "3" Then
Portd.2 = 1
Waitms 1250
Portd.2 = 0
Print "4"
C = ""
End If
If C = "res" Then
Portd.2 = 1
Waitms 1250
Portd.2 = 0
Print "4"
End If
if A = 13 then
C = ""
end if
Loop

tobimc
27.07.2004, 14:03
HI Freiheitspirat!!!

Ich möchte einfach, wenn ich im einen Prozessor 'Print "res" ' sage,
dass dann im anderen in einer String-Variablen "res" steht.
Und wenn ich im einen Prozessor "mot" printe,
dass im anderen, in einer Variablen "mot" steht.

Das kann doch nicht so schwer sein.
Mit ascii und allem drum und dran ist ja gut, ich möchte einfach nur
den String, den ich beim einen gesendet habe, im anderen in einer
(String) Variablen haben.

Konkret:
Nach der einmaligen Anwendung von Inkey() ist dann der Inputbuffer wieder gelöscht?
Muss ich es mehrmals aufrufen...
etc.
Oder ist Inkey dazu total ungeeignet und ich muss eine do loop schleife mit input machen?

Fragen über fragen.

Danke bis hier und danke an jeden, der mir eine Lösung weis!!!

Liebe Grüße, Tobi

Freiheitspirat
27.07.2004, 15:54
Wenn Du das obige Programm nutzt, hast Du doch z.B. "res" oder "bot" oder was auch immer in Variable C !?!?!

Also nochmal ganz langsam:
Jedes auf der RS232 empfangene Zeichen wird in einem Buffer (max. Länge z.B. Size=20) gespeichert.
Wenn es mehr Zeichen gibt, werden die Ersten wieder überschrieben, vorausgesetzt sie sind nicht mit inkey() abgeholt.
Mit inkey() holst Du Dir nacheinander den ASCII-Code des jeweils ersten Zeichens (das verschindet dann aus dem Buffer).
Falls inkey() = 0 ist, gibt es keine weiteren Zeichen.
Natürlich mußt Du die einzelnen Zeichen in einer Schleife abholen.
Entweder in einer Endlosbearbeitung (do loop) oder in einer Unterfunktion solange wie Inkey() > 0 ist (Dabei auf ausreichende Buffergröße achten, damit nichts verloren geht).


Das kann doch nicht so schwer sein.


Tut mir leid, aber einfacher kann ich es nicht erklären.

tobimc
27.07.2004, 19:02
HI Freiheitspirat!

Sorry, ich war vorher etwas gereizt...
Ich hoffe, du verzeihst mir das...

Wäre es möglich, dass CR bzw. LF die entscheidende IF-Abfrage stören und C dann ungleich "res" ist?

Ich were das jetzt noch mal langsam und überlegt testen...

Liebe Grüße und DANKE! Tobi

tobimc
28.07.2004, 11:56
Hi Freiheitspirat!!

also ich habe da mal ein bisschen programmiert...



$baud = 9600
$crystal = 8000000

'Config Serialin = Buffered , Size = 5

Dim A As Byte
Dim B As String * 5
Dim C As String * 20

Dim N As Byte

Begin:

N = 0


Do
A = Inkey()

If A = 0 Then
Else
C = C + Chr(a)
A = 0
N = N + 1
End If

Loop Until N = 3

Portd.2 = 0
Waitms 250

'If C = "" Then

Do
Portd.2 = 1
Waitms 250
Portd.2 = 0
Waitms 250
Loop

'End If

Goto Begin
End


Das Einlesen ist mit Schleife wie ihr das so geschrieben habt.
Es hat plötzlich funktioniert, als ich config serialin weggelassen hab(deshalb auch nur als comment)!!! Das ist wohl der Fehler gewesen.
Der 4433 verträgt wohl kein config serialin.

Aber es gibt da noch ein kleines Problem...

Die Schleife mit Inkey() soll 3 Zeichen abholen.
Diese werden mit print "r" ; "e" ; "s" bzw.

Print "r"
Waitms 100
Print "e"
Waitms 100
Print "s"

vom Master aus gesendet.
Wenn Zählvariable N = 3 ist (3 Zeichen sollten im String stehen)
Sollte die Einleseschleife abgebraochen werden.
Wenn ich dem Master sage, er soll nur 1 Zeichen senden("r"), wird die Schleife aber trozdem unterbrochen. und die LED (portd.2) fängt an zu blinken.

Nun. Was läuft hier nicht so ganz richtig?
Wir sind kurz vor dem Ziel!!!

Liebe Grüße und DANKE schon jetzt!

Tobi

Freiheitspirat
28.07.2004, 12:40
Nun. Was läuft hier nicht so ganz richtig?
Wir sind kurz vor dem Ziel!!!


Die Antwort haben wir bereits diskutiert.
Siehe nochmal unter der Beschreibung vom CR / LF

Print "r" = 114 13 10 = 3 Zeichen = BlinkBlinkBlink

tobimc
28.07.2004, 13:26
Hi Freiheitspirat!

Also sollte ich mit printbin arbeiten??
Ich teste mal...

Liebe Grüße, Tobi

tobimc
29.07.2004, 10:37
Hi

ES FUNKTIONIERT!!!!!

DANKE an Freiheitspirat, der unter aufwendung unglaublicher Geduld
die Sache mit CR/LF in meinen Dickschädel geklopft hat!!

DANKESCHÖN!!

Liebe Grüße, Tobi