Hallo liebes Forum, ich habe ein kleine Problem bei dessen Lösung ihr mir evtl. helfen könnt. Ich arbeite mit einem Atmega8 und C. Ich versuche über UART einen String, den ich vorher in LabView erstellt habe zum µC zu schicken, ihn im µC zu zerlegen und am Ende 2 Bytes über SPI an ein DAC IC zu schicken um mir analoge Spannungen zu erzeugen. Wenn ich nun die 2 Bytes direkt über SPI sende, ohne über den UART etwas zu empfangen: SPI_MasterTransmit(0x02); SPI_MasterTransmit(0x80); Bekomme ich die korrekte Spannung ausgeben (die Kombination entspricht 1,55 Volt). Wenn ich mir aber nun mit Labview eine 2 und eine 80 schicke funktioniert das nicht mehr. Ich kann mir die 2 und die 80 auf dem Display anzeigen lassen um sicherzustellen, dass alles auch korrekt ankommt. Wie schaffe ich es nun mir die beiden Hexzahlen in meine SPI_MasterTransmit Funktion einzubauen? Also quasi so: SPI_MasterTransmit(Byte1); SPI_MasterTransmit(Byte2); Soweit ich es verstehe sendet mir Labview ASCII Zeichen und ich möchte ja reine Hex Zahlen haben. Wie kann ich mir die 2 und die 80 in Hex zahlen umwandeln damit sie mein DAC auch so interpretiert? Eine 2 als ASCII ist ja auch eine 0x02 als Hex, die 80 ASCII ist ja aber als Hex eine 0x50, die ich ja nicht will. Außerdem bin ich mir unsicher wie das mit den angehängten Nullen ist am Ende der Zeichenketten. Ich zerlege den empfangenen String mit strtok. Ich komme hier leider nicht weiter. Herzlichen Dank für eure Tipps und Hilfen! Viele Grüße Hans
Hans L. schrieb: > Wenn ich mir aber nun mit Labview eine 2 und eine 80 schicke > funktioniert das nicht mehr. Was genau schickst du? Schickst du ASCII Zeichen, also '2', '8', '0'? Oder schickst du binär 2 Bytes vom PC an den µC? > Soweit ich es verstehe sendet mir Labview ASCII Zeichen und ich möchte > ja reine Hex Zahlen haben. In erster Linie sind das erst mal nur Zahlen. Hex ist eine SChreibweise, wie man eine Zahl darstellen kann, genauso wie Binär oder Dezimal. Aber Zahl ist Zahl. > Eine 2 als ASCII ist ja auch eine 0x02 als Hex Nö, ist sie nicht. Such dir eine ASCII Tabelle und sieh nach. > die 80 ASCII ist ja aber > als Hex eine 0x50, die ich ja nicht will. Ich bin mir immer noch nicht sicher, ob du jetzt in Textform verschickst oder als binäre Bytes. > Ende der Zeichenketten. Ich zerlege den empfangenen String mit strtok. Also doch Text? Eine einzelne Ziffer kannst du so in ihr numerisches Equivalent umformen number = digit - '0'; aus '2' wird so 2 aus '4' wird so 4 und aus '9' wird so 9 und um aus den Zeichen '2', '4' '9' die Zahl 249 zu erzeugen, rechnet man dann ganz einfach: 2*100 + 4*10 + 9 und das ergibt dann die Zahl 249 PS: Kleb nicht zu sehr an Hex. Du hast Zahlen! Du schickst vom PC einen String mit einer Zahl zum µC, der wandelt den String wieder in eine Zahl zurück, zerlegt die Zahl in ihre beiden Bytes und gibt die an den DA Wandler weiter. Die Textübertragung muss aber nicht in Form einer Hex-Darstellung sein. Zeig mal deinen Code und was du du dem µC tatsächlich schickst.
Hallo Hans, bei LabView gibts eine Funktion "Zahl nach String(Hexadezimal)". Weitere Umwandlungsfunktionen findest du in Funktionen: Programmierung -> String -> Konvertierung. Mfg Martin
Hallo, erstmal danke für die schnellen Antworten. Ich schicke einen String mit Labview der so aussieht: 1,82!188!2!80 Übersetzt bedeutet das: Trennzeiche ist !, die Spannung soll 1,82 Volt sein, das entspricht entspricht nach der Berechnungsformel aus dem DAC Datenblatt 188 ( 2*UREFIN*188/1023=1,82 ) ; UREFIN=4,98V. Insgesamt braucht der DAC 16 Bit. Diese setzen sich aus 4 Upper Dummy Bits, 10 Databits (188) und 2 extra Bits zusammen. Diese 16 Bit Kombination erstelle ich in Labview und teile sie in 2 x 8 Bit, das ergibt als Binär 00000010 oder 0x02 (Byte1) und 11110000, 0xF0 (Byte2). Wenn ich wie beschrieben das SPI_MasterTransmit(0x02); SPI_MasterTransmit(0x80); oder SPI_MasterTransmit(0b00000010); SPI_MasterTransmit(0b11110000); sende zeigt mein Voltmeter 1,82 Volt an. Wenn ich aber mit Labview über den UART einen String mit der 2 und der 80 oder Binärzahlen schicke und über SPI ausgeben will, als Byte1 und Byte 2 werden keine 1,82 Volt ausgegeben sondern 1,40V. Auf dem Display kann ich die Zahlen korrekt darstellen. Mein Code ist im Anhang, evtl. passiert der Fehler ja schon beim Teilen des Strings?
Sorry, aber was soll denn sowas im Code:
1 | while( (token = strtok(NULL,"!") )) |
2 | {
|
3 | ...
|
4 | }
|
Hans L. schrieb: > Auf dem Display kann ich die Zahlen korrekt darstellen. Dann liegt es wahrscheinlich daran, dass Du den String im uC falsch in einen HEX-Wert wandelst. Du müsstest also von "80" als String irgendwie zu 80h kommen. Schau Dir mal die Funktion atoi in der stdlib.h an. Hans L. schrieb: > Mein Code ist im Anhang, evtl. passiert der Fehler ja schon beim Teilen > des Strings? Beim Teilen kann ich mir nicht vorstellen, wenn die Zeichen richtig auf dem Display wiedergegeben werden. Aber wahrscheinlich wie oben schon gesagt in der Wandlung von String zu HEX. Grüße
Hans L. schrieb: > Hallo, > erstmal danke für die schnellen Antworten. > Ich schicke einen String mit Labview der so aussieht: 1,82!188!2!80 > Übersetzt bedeutet das: Trennzeiche ist !, die Spannung soll 1,82 Volt > sein, das entspricht entspricht nach der Berechnungsformel aus dem DAC > Datenblatt 188 ( 2*UREFIN*188/1023=1,82 ) ; UREFIN=4,98V. Insgesamt > braucht der DAC 16 Bit. Diese setzen sich aus 4 Upper Dummy Bits, 10 > Databits (188) und 2 extra Bits zusammen. Diese 16 Bit Kombination > erstelle ich in Labview und teile sie in 2 x 8 Bit, das ergibt als Binär > 00000010 oder 0x02 (Byte1) und 11110000, 0xF0 (Byte2). Kopfschütttel. Machs doch nicht so kompliziert. Dass du die 1,82 (übrigens: gewöhn dir an, dass wir mit Dezimalpunkten arbeiten und nicht mit einem Komma! In Programmiersprachen [ausser in bescheuerten Deutschen Übersetzungen und Excel] hat man immer einen Dezimalpunkt) noch mitschickst kann ich verstehen, weil du im µC nicht mit Floating Point arbeiten willst. Aber lass doch den µC die Aufteilung machen. Rechne im Labview aus 1.82 * 1023 / 2*UREFIN -> x und diese Zahl (korrigiert um die beiden Extrabits) schickst du zum µC. Der muss sowieso aus dem Text erst mal eine Zahl machen und die in die Bytes zerlegen, dass er sie zum DAC weiter geben kann. Da brauchst du dir wirklich keinen Kopf machen, dass du ihm das alles in Bytes aufbereitest. Das kostet den µC nur ein müdes Lächeln die Aufteilung zu machen. Und zum Testen per Textsenden aus Hyperterminal ist es auch einfacher. d.h. du schickst zum µC 1,82!640 fertig. Auf dem µC brauchst du auch kein strtok um den Text kompliziert auseinanderzunehmen. Der erste Teil ist klar: Vom Stringbeginn bis zum ! ist das Text, der auf die Anzeige muss. D.h. du fängst vorne in der Textzeile an und schiebst alle Zeichen auf das LCD, bis du auf den '!' stösst. Nach dem '!' kommt die Zahl, die zum DAC muss. Also holt man sich alle Zeichen, die zur Zahl gehören und baut sich die Zahl wieder als numerische Zahl zusammen. Die wird dann in High-Byte und Low-Byte aufgeteilt und zum DAC geschoben.
1 | uint16_t Value; |
2 | uint8_t HighByte, LowByte; |
3 | uint8_t charIndex; |
4 | |
5 | while(1) |
6 | {
|
7 | charIndex = 0; |
8 | |
9 | // der erste Teil ist der anzuzeigende Text
|
10 | lcd_setcursor(0,1); |
11 | while( stringbuffer[charIndex] && stringbuffer[charIndex] != '!' ) |
12 | lcd_char( stringbuffer[charIndex++] ); |
13 | |
14 | // den ! überlesen
|
15 | charIndex++; |
16 | |
17 | // nach dem ! geht es mit dem Wert weiter, der zum DAC muss
|
18 | // also erst mal aus dem Text eine numerische Zahl formen.
|
19 | // da die Zahl dezimal übertragen wird, setzen wir sie auch
|
20 | // wieder dezimal zusammen
|
21 | Value = 0; |
22 | while( isdigit( stringbuffer[charIndex] ) ) |
23 | Value = 10*Value + stringbuffer[charIndex++] - '0'; |
24 | |
25 | // den Wert in 2 Bytes aufteilen
|
26 | HighByte = Value >> 8; |
27 | LowByte = Value; |
28 | |
29 | // und zum DAC schicken
|
30 | SPI_MasterTransmit( HighByte ); |
31 | SPI_MasterTransmit( LowByte ); |
32 | }
|
ferig. Mehr brauchts dazu nicht. Klemm dich an dein Hyperterminal (oder was auch immer du sonst noch benutzt) und schick an den µC den Text 1.82!640(Return) und die 640 werden (aufgeteilt) in Bytes an den DAC weitergegeben. (als ein Byte mit dem Wert 0x02 und ein Byte mit dem Wert 0x80. Dran denken Hex ist NUR eine Schreibweise! In erster Linie hast du eine Zahl. Ob du sie als dezimal 640 schreibst oder hex 0x0280 ist gehupft wie gesprungen. Es ist immer dieselbe Zahl und hat daher auch dasselbe Bitmuster) Deine UART Empfangsfunktion funktioniert? So dass du in Stringbuffer IMMER (das ist zu jedem Zeitpunkt, selbst wenn eine Übertragung gerade im Gange ist) eine komplette Zeile zur Verfügung hast, die sich erst mit dem Empfang des Zeilenende Zeichens (zb einem Return) ändert? Denn wenn du einen String zerlegst, dann sollte der auch tunlichst vollständig sein. Und achte ein wenig mehr auf deine Programmformatierung! Speziell die Einrückungen. Es ist nämlich mehr als Zufall, dass immer ausgerechnet diejenigen mit dem scheuslichsten Code immer die sind, bei denen nix funktioniert.
Hallo, herzlichen Dank für die super Hilfe Karl Heinz. Das Programm funktioniert nun einwandfrei. Ich habe eine Weile gebraucht um das Programm zu verstehen, deshalb die späte Antwort. @ Der Neue: Was soll das? "Sorry, aber was soll denn sowas im Code:" Wie soll ich mit diesem Satz meine Fehler korrigieren oder verstehen wo meine Fehler liegen? Wenn ich es besser gewusst hätte, hätte ich es so nicht gemacht oder müsste hier gar nicht nachfragen. Mit so einem Satz wird hier Niemandem geholfen! Karl Heinz Antwort war absolut vorbildlich und zielführend. Ich habe meine Fehler erkannt, das Programm läuft und weitere Leser können Fehler durch diesen Thread evtl. vermeiden oder ihre Programme verbessern ohne einen neuen Thread zu erröffnen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.