Forum: Mikrocontroller und Digitale Elektronik Per UART Zahlenwert an Mega8 schicken (BASCOM)


von Stefan (Gast)


Lesenswert?

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

von Rahul, der Trollige (Gast)


Lesenswert?

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.

von Stefan (Gast)


Lesenswert?

Fehler über Fehler. Das hilft mir leider nicht weiter.

von Rahul, der Trollige (Gast)


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

Toller Post, deshalb frage ich ja hier.

Mehr als "hängengeblieben!" fällt mir dazu nicht ein. Geh ins Bett!

von Rahul, der Trollige (Gast)


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

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

von Jürgen C (Gast)


Lesenswert?

Hallo,

schau mal in der Bascom Hilfe  mit der Suche nach
"Val" und "Uart" jeweils das erste Ergebnis an.

Gruß

Jürgen

von Karl H. (kbuchegg)


Lesenswert?

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

von Rahul, der Trollige (Gast)


Lesenswert?

>Ich will 999.999 vom PC aus in HEX senden und im Atmel in eine For
>Schleife einsetzen.

Was soll der Atmel in einer sooo ungeraden Schleife?

von Stefan (Gast)


Lesenswert?

>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)

von Stefan (Gast)


Lesenswert?

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.

von Rahul, der Trollige (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

> 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

von Stefan (Gast)


Lesenswert?

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!

von Rahul, der Trollige (Gast)


Lesenswert?

>Ok, das sind schonmal gute Tipps.
Natürlich sind das gute Tipps! Die komme ja auch von Karl Heinz und mir.

von Rahul, der Trollige (Gast)


Lesenswert?

Falls du es noch nicht gefunden haben solltest:
http://avrhelp.mcselec.com/bascom-avr.html

von Stefan (Gast)


Lesenswert?

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
------------------------------------------------------------------------ 
--

von Karl H. (kbuchegg)


Lesenswert?

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.

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.