Moin moin,
ich habe eine (?) Frage zur HW UART Kommunikation und vor allem zur
interpretierung der gesendeten Zahlen.
Ich muss von einem PC aus eine Dezimalzahl vorgeben, die dann im Atmel
als Anzahl der Schleifendurchläufe einer For-Next Schleife eingesetzt
wird.
Diese Zahl liegt zwischen 0 und 999999.
Auf dem PC wird die Zahl über ein Labview Programm über die RS232 in HEX
gesendet.
Wie bekomme ich nun die Zahl in eine Variable, mit der die For-Next
Schleife arbeiten kann?
Unten ist das Programm, mit dem ich momentan etwas experimentiere, aber
es kann nur einen Tastendruck verarbeiten.
Wie kann ich z.B. 50.000 aus den vom PC gesendeten HEX Zahlen in eine
Variable quetschen? Das kommt ja soweit ich weiß als String an.
Ich wäre für gute Tipps sehr sehr dankbar!
$regfile = "m8def.dat"
$crystal = 16000000
$baud = 115200
Dim i As Byte
Dim A As Byte
Config Portb.3 = Input
Portb.3 = 1
Do
If Usr.rxc = 1 Then 'Wenn Byte empfangen...
I = Udr 'Byte aus UART auslesen
End If
If Pinb.3 = 0 Then 'wenn Taster gedrückt, wird die
'Schleife gestartet
For A = 0 To I
Print "Durchlauf Nr.: " ; A '"A" zeigt den ASCII Wert des
'gedrückten Buchstabens Bsp.
'ENTER = 13 => 13 Durchläufe
Next
Waitms 200
End If
Loop
End
So vielleicht:
>Do
A=0
Loop
>If Usr.rxc = 1 Then 'Wenn Byte empfangen...> I = Udr 'Byte aus UART auslesen
if i<>13 A = A*10+(asc(i)-'0')
>End If
until I = 13;
Loop
Die Schleife endet mit dem Drücken der Enter-Taste.
>Fehler über Fehler. Das hilft mir leider nicht weiter.
Das liegt vermutlich daran, dass ich keine Ahnung von Bascom habe, und
du keine vom Programmieren...
>Mehr als "hängengeblieben!" fällt mir dazu nicht ein. Geh ins Bett!
OK:
Es läuft so, dass man die Zeichen, die von der seriellen Schnittstelle
empfangen werden in Zahlen wandelt.
Der Zahlenwert eines Zeichens wird in manchen Basic-Dialekten mit
"ASC()" bestimmt (das Gegenteil dazu ist "chr()").
>A=0>Loop>If Usr.rxc = 1 Then 'Wenn Byte empfangen...> I = Udr 'Byte aus UART auslesen> if i<>13 A = A*10+(asc(i)-'0')>End If>until I = 13;
Etwas Quatsch steht da auch (war aus der Hüfte geschossen...):
>asc(i) - '0' sollte eher i-asc("0") heissen (asc("0") müsste 48 sein siehe hier: http://de.wikipedia.org/wiki/Ascii)
Eine "1" steht im ASCII-Zeichensatz an der Stelle 49.
Eine "2" steht im ASCII-Zeichensatz an der Stelle 50.
.
.
.
Durch die Subtraktion wird also aus dem ASCII-Wert ("0"..."9") ein
numerischer Wert (0...9).
A = A*10 sollte klar sein.
A = A*10 +(i-48) auch...
Diese Abfrage soll einfach so lange erfolgen bis die Entertaste (I=13)
empfangen wurde.
Ist das kompliziert?
Ja ist es leider.
Ich will 999.999 vom PC aus in HEX senden und im Atmel in eine For
Schleife einsetzen.
...
Variable = UDR '(999.999 geht natürlich so nicht! Hilfe!!)
For I = 0 To Variable
blablabla
Next
...
> Ich will 999.999 vom PC aus in HEX senden
Was schickst du genau?
Schickst du die Zahl in einer Textform
oder schickst du sie in binärer Form?
Wenn du also eine Zahl 48 hast, was kommt
über dann über die Schnittstelle:
Ein String, sprich eine Abfolge von ASCII Zeichen mit
dem Inhalt '4' '8' oder schickst du nur 1 Byte mit
dem Inhalt 48.
Die Angabe von Hex in deiner Frage macht hier nicht wirklich
Sinn. Entscheidend ist erstmal: Textform oder Binärform.
>Was soll der Atmel in einer sooo ungeraden Schleife?
Ok, die Schleife soll eine bestimmte Anzahl von Messzyklen an IGBTs
abarbeiten.
Die sollen im Einschaltverhalten geprüft werden und werden mit 150A
bestromt, bis sie sich auf eine bestimmte Temperatur erhitzt haben und
dann wird noch anderer Kram gemacht, um den es erstmal nicht geht.
Die Anzahl der Zyklen will ich per PC an den uC übermitteln.
>Die Angabe von Hex in deiner Frage macht hier nicht wirklich>Sinn. Entscheidend ist erstmal: Textform oder Binärform.
Das glaub ich gerne, ich bin nämlich momentan sehr verwirrt.
Es ist so, dass in Labview (kennst Du das Programm? Ist graphische
Programmierung in Richtung Messtechnik würde ich mal so sagen.) Daten
über die RS232 geschickt werden können.
Soweit ich es rausfinden konnte, werden die Daten in HEX über das Kabel
geschickt. Das hab ich mit dem Programm "Free Serial Monitor" oder so
ähnlich gemacht.
Wenn ich z.B. die Entertaste drücke, wird ein 0D gesendet, also HEX.
Darum hab ich davon geredet.
Wenn das erstmal egal ist, um so besser.
Es muss nur möglich sein, dass ich Zahlen bis 999999 (999 tausend, nicht
999,999!) von PC aus als Variable in die For Next Schleife bekomme.
Ich habe gelesen dass man ein Feld anlegen kann, in dem dann ein String
mit einer bestimmten Anzahl von Bytes gespeichert wird. Das ist
prinzipiell ja schonmal ganz gut.
Dann würde ich ja einen String so deklarieren:
Dim Zyklenanzahl as String * 6
Des weiteren habe ich gelesen, dass man das Feld dann an einer
bestimmten Stelle speichern kann und dann von der Stelle als Byte wieder
auslesen und dann hat man es schon in eine Zahl gewandelt.
Aber da ich erst seit kurzem uCs Programmiere, bin sitz ich wie das
Schwein vorm Uhrwerk.
Eigentlich wollte ich nicht soviel schreiben, weil das wahrscheinlich
keiner bis zum Ende liest, aber ichhoffe es hilft weiter.
nochmal in kurz:
Es muss nur möglich sein, dass ich Zahlen bis 999999 (999 tausend, nicht
999,999!) von PC aus als Variable in die For Next Schleife bekomme.
(Ob ich nun als String, HEX oder Byte von PC aus sende ist egal, das
kann ich in Labview machen wie ich will, denk ich, die Umsetzung im uC
ist das Problem)
Tut mir Leid, das hab ich jetzt vergessen:
>Wenn du also eine Zahl 48 hast, was kommt>über dann über die Schnittstelle:>Ein String, sprich eine Abfolge von ASCII Zeichen mit>dem Inhalt '4' '8' oder schickst du nur 1 Byte mit>dem Inhalt 48.
Die 48 bekomme ich bis jetzt über einen Tastendruck, also als ASCII '4'
und '8' (wenn ich das richtig verstanden habe.)
Mit dem Programm, dass den Serialport abhören kann, sieht man aber, dass
die Zahl 48 in HEX gesendet wird. Aber das ist ja vielleicht egal und
interessiert nicht weiter. ich wollte nur irgendwie verstehen, wer da
was wie sendet.
>Wenn ich z.B. die Entertaste drücke, wird ein 0D gesendet, also HEX.>Darum hab ich davon geredet.
Womit hast du das festgestellt?
Es wird ein EINZIGES Byte übertragen. Ob HEX, DEC oder Binär - Das sind
alles nur verschiedene Darstellungsformen für eine Zahl.
Gehen wir von einer "normaldummer Mensch"-lesbaren Variante aus:
Dezimale Schreibweise.
Falls du dir inzwischen die ASCII-Tabelle angeguckt haben solltest,
wirst du festgestellt haben, dass die '9' an der Stelle 0x39 = 57 dec
steht. (Momentan aber irrelevant).
Deine 999999 würde dann als 0x39 0x39 0x39 0x39 0x39 0x39 übertragen
werden.
Um dann noch festzustellen, dass alle Ziffern übertragen wurden, sendet
man hinten dran noch ein Enter (CR = "Carriage return = 0x0D).
So, jetzt wollen wir Zahlen empfangen:
Dim i As Byte
Dim A As Byte 'kann Zahlen zwischen 0 und 255 enthalten, LONG wäre
passender...
Config Portb.3 = Input
Portb.3 = 1
Do
A = 0;
Do
If Usr.rxc = 1 Then 'Wenn Byte empfangen...
I = Udr 'Byte aus UART auslesen
if (I <> 13) AND (I>=ASC("0")) AND (I<=ASC("9")) Then
I = I-ASC("0")
A = A*10
A = A+I
END IF
End IF
LOOP UNTIL I = 13 'Enter wurde gedrückt
If Pinb.3 = 0 Then 'wenn Taster gedrückt, wird
die
'Schleife gestartet
For I = 0 To A
Print "Durchlauf Nr.: " ; I '"A" zeigt den ASCII Wert des
'gedrückten Buchstabens Bsp.
'ENTER = 13 => 13 Durchläufe
Next
Waitms 200
End If
Loop
End
Könnte sein, dass da jetzt noch irgendwelche Syntax-Fehler drin sind...
> Die 48 bekomme ich bis jetzt über einen Tastendruck, also als ASCII '4'> und '8' (wenn ich das richtig verstanden habe.)>> Mit dem Programm, dass den Serialport abhören kann, sieht man aber, dass> die Zahl 48 in HEX gesendet wird
Vergiss das HEX. Das ist eine ganz normale Textübertragung.
HEX ist nur eine Darstellungsform für Zahlen, bzw
in diesem Fall für Codes. Entscheidend ist aber was diese
Codes bedeuten. Und bei dir ist:
Eine Code -> Ein Buchstabe -> Eine Ziffer der Zahl die
du Übertragen willst.
Auf der Gegenstell musst du die Zahl wieder zusammensetzen.
Du nimmst jedes Zeichen einzeln entgegen, ziehst den
ASCII Codefür '0' davon ab und 'summierst' alles auf.
Total = 0
while( nächstes Zeichen von der UART gehört noch zur Zahl )
Total = 10 * Total + ( nächstes Zeichen - '0' )
Die Umsetzung in BASCOM musst du delbst besorgen.
Ah ich seh grade, Rahul war schon so freundlich
Ok, das sind schonmal gute Tipps. Ich werde mich da nachher mal
ranmachen, ich habe ersmal mit dem Rest des Programms weiter gemacht.
Viele Dank soweit!
So, durch die unglaublich tollen, geradezu übermenschlich guten Tipps
von Rahul rennt der Hase.
Vielen Dank an Karl Heinz. :)
Hier der Code für Leute, die das gleiche Problem haben:
------------------------------------------------------------------------
--
$regfile = "m8def.dat" 'uC = Mega8
$crystal = 16000000 'Takt des Quarzes
$baud = 9600 'Baud Rate für UART
Dim I As Byte 'In diesem Byte wird die aktuell
'ankommende Zahl (in ASCII) gespeichert
Dim A As Long 'Eingabe bis 2147483647
Print "Soweit so gut."
Do
A = 0 'A wird nach vor jeder neuen Ausgabe
'initialisiert
Do
If Usr.rxc = 1 Then 'Byte über UART empfangen...
I = Udr 'Byte aus UART auslesen und in I schreiben
If I <> 13 And I >= 48 And I <= 57 Then
'Wenn Byte nicht 13 (ASCII für "Enter")
und
'>= 48 (ASCII für "0") und <= 57 (ASCII
für
'9) dann
I = I - 48 'ziehe 48 (ASCII für "0") davon ab
'(Bsp.: Aus 49 (ASCII für "1") wird
'A = 49 - 48 = 1 (nun dezimal))
A = A * 10 'Zehnersystem!
A = A + I 'Aufaddierung der Zahlen
End If
End If
Loop Until I = 13 'Enter wurde gedrückt
If I = 13 Then
Print "Aktueller Wert: " ; A 'Nun wird die eingegebene Zahl wieder
'auf dem PC angezeigt.
I = 0
End If
Loop
End
------------------------------------------------------------------------
--
Nachdem du jetzt weist, was da abgeht:
Bascom wäre nicht Bascom, wenns dafür nicht schon
was Fertiges gäbe.
Wenn die Zeichen in einem String gesammelt werden,
dann kann man ganz einfach die Funktion Val benutzen,
die dann den String in eine Zahl umwandelt:
Dim Instring as String*10
Dim Varval as Integer
Instring = " 781"
Varval = Val(Instring)
'Varval = 781
Für das Sammeln von Zeichen von der Uart bis zum Return
gibt es sicherlich auch etwas.