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