Hallo,
folgende Ausgangssituation:
-Mikrocontroller ATMega168/USBtoUART Converter/Programmierung mit AVR
GCC
-PC/USB Schnittstelle/Programmierung c#
Ich möchte zwischen Mikrocontroller und PC Daten austauschen.
Im Mikrocontrollerprogramm habe ich erfolgreich die UART Lib von Peter
Fleury implementiert.
Auf der PC Seite läuft die Ankopplung auch soweit.
Es sollen nun eine Reihe 16 und 32 Bit UInt Werte übertragen werden.
Soweit so gut.
In der Hauptschleife des Mikrocontroller Programms lese ich nun, wie im
Muster der Lib angegeben, den Empfangsbuffer aus. Eigentlich wollte ich
ein Startbyte definieren um die Datenübertragung zu
synchronisieren/starten , d.h. den Empfangsbuffer in ein Array packen
und nach Empfang aller Zeichen entsprechend auslesen.
Da ich nun aber die 32/16Bit UInt als Absolutwerte übertrage (vorher
entsprechend in Einzelbytes aueinander gebröselt) kann jede Kombination
zwischen 0x00 und 0xFF auftreten. Ein "freies" Startbyte ist also so
nicht möglich.
Wie löst man soetwas?
Habt Ihr Tipps für mich?
Vielen Dank
Ernst
Umwandeln in ASCII ist schon ein bisschen krass. Du koenntest anstatt
von 8N1 9N1 verwenden und das uebrige Bit als Start-Indikator verwenden.
Oder Du machst es ueber die Zeit (Pause nach jeder kompletten
Uebertragung).
Volker
Man kann sich natürlich auch noch ein Startbyte freischaufeln.
zb. 0xFF wird nie in den Daten übertragen (oder irgendein anderer Wert
der möglichst selten vorkommt. Oft ist es ja so, dass bestimmte Bytes
häufig auftreten, andere wiederrum seltener)
0xFF ist das STartbyte
muss in den Daten 0xFF übertragen werden, so wird stattdessen zb 0xFE
0x01 übertragen. Da jetzt 0xFE eine Sonderrolle zukommt, wird das
ursprüngliche 0xFE als 0xFE 0x00 übertragen.
Baut man diese Substitution tief unten in die Softwarelayer ein, so ist
das alles für darüberliegende Softwareschichten transparent und sie
merken nichts davon.
ich schrieb:
> und was ist wenn man 0xFE 0x00 senden will?
Was hinter dem 0xFE kommt tangiert ja die Substitution nicht.
0xFE wird durch 0xFE 0x00 ersetzt.
Angenommen der Sender möchte diese Bytesequenz auf den Weg bringen
0xFF 0xFE 0x00
Seine Sendefunktion übernimmt die Substitution:
0xFF wird durch 0xFE 0x01 ersetzt, 0xFE wird durch 0xFE 0x00 ersetzt.
Noch ein 0xFF als Startbyte davor.
Damit geht über die Leitung:
0xFF 0xFE 0x01 0xFE 0x00 0x00
Beim Empfänger wird 0xFF als Startbyte aussortiert. Die Abfolge 0xFE
0x01 wird durch 0xFF ersetzt, die Abfolge 0xFE 0x00 wird durch 0xFE
ersetzt. Aus der Empfangsroutine purzeln also raus
Start of Daten
0xFF 0xFE 0x00
Also genau das, was der Sender seiner Senderoutine übergeben hat (+ eine
Kennung für: ein neuer Datensatz hat angefangen)
Hängt auch davon ab, was für Daten Du übertragen willst. Wenn es
binärdaten sind, wirst Du ja ne feste Paketgröße verwenden, d.h. Du
kannst ndein Paket mit einem ASCII Frame mit startund endzeichen
einpacken, in dem als z.B. zweiter parameter die Länge des Binärblock
kommt.
Falls nach dieser Länge nicht Dein endbyte kommt, rückmeldung an den PC
bitte paket noch mal schicken.
Die 255 als Startbyte definiertst musst Du z.B. die 254 noch als
Excapezeichen missbrauchen, soll heißen wenn Du eine 245 oder 255 senden
willst musst Du z.B. 254 und danach eine 1, bzw. 254 und eine 2 oder was
Du als Code eben nehmen willst senden.
Gruß
Tom
Hehe...
Mit der Methode von Karl Heinz wird der Overhead ja ziemlich
unkalkulierbar. Und wenn einem das nichts ausmacht, weil man sowieso
keine festen Wiederholungraten braucht, kann man auch gleich die Option
mit der Zwangspause zwischen zwei Uebertragungen nehmen. Ist vermutlich
einfacher zu implementieren. ;) Hinzu kommt dass eine solche Pause zum
Synchronisieren sowieso alle paar Bytes erfolgen sollte.
Abgesehen davon ist der Overhead bei Uebertragung von nur einer 16- und
einer 32-Bit-Zahl mit relativ hoher Wahrscheinlichkeit schon groesser
als bei der Methode mit dem zusaetzlichen Bit. Koennte man ja mal genau
ausrechnen, wenn's wirklich auf jede Millisekunde ankommt.
Dann koennte man noch ueberlegen, eine zusaetzlichen Pin zu benutzen
(auf der EIA-232-Seite hat man da ja eh welche, der Mikrocontroller
koennte auch noch einen Pin frei haben), der den Beginn einer
Uebertragung signalisiert.
Volker
Thomas Burkhart schrieb:
> Hängt auch davon ab, was für Daten Du übertragen willst.> [...]
Hat er doch geschrieben. Ein paar 16- und 32-Bit-Zahlen. Ansonsten siehe
meinen vorherigen Beitrag. ;)
Volker
Karl heinz Buchegger schrieb:
> Man kann sich natürlich auch noch ein Startbyte freischaufeln.>> zb. 0xFF wird nie in den Daten übertragen (oder irgendein anderer Wert> der möglichst selten vorkommt. Oft ist es ja so, dass bestimmte Bytes> häufig auftreten, andere wiederrum seltener)>> 0xFF ist das STartbyte> muss in den Daten 0xFF übertragen werden, so wird stattdessen zb 0xFE> 0x01 übertragen. Da jetzt 0xFE eine Sonderrolle zukommt, wird das> ursprüngliche 0xFE als 0xFE 0x00 übertragen.> Baut man diese Substitution tief unten in die Softwarelayer ein, so ist> das alles für darüberliegende Softwareschichten transparent und sie> merken nichts davon.
Dadurch dass ich Werte von 0x00 ... 0xFF übertragen muss, gibt es da
kein Zeichen welches weniger oft vorkommt. Wahrscheinlich verstehe ich
den Zusammenhang nicht, aber müsste dann nicht ein anderes Zeichen
"frei" sein um ein Zeichen frei zu schaufeln und damit habe ich wieder
den Salat, da ja keins frei ist.
Ich hatte schon überlegt die Bytes in zwei Einzelbytes zu Splitten und
danach wieder zusammen zu bauen. Also bei einem 0xFF einmal 0x0F und
danach nochmal 0x0F zu übertragen. Somit hätte ich alle Werte über 0x0F
frei (quasi als Kennungen).
Ist so etwas üblich?
Gruß
ernst
So wird es z.b. bei hldc gemacht
http://de.wikipedia.org/wiki/High-Level_Data_Link_Control
Um zu vermeiden, dass innerhalb des Datenbereichs oder der Prüfsumme das
Opening flag bzw Closing flag auftritt, wird Bitstopfen (bit stuffing)
oder zero insertion angewandt. Dies bedeutet, dass innerhalb des Rahmens
nach fünfmaligem Auftauchen der '1' eine '0' eingefügt wird, um eine
Verwechslung mit einem Flag zu verhindern. Auf Empfängerseite wird eine
'0' nach fünfmaligem Auftreten der '1' einfach wieder gelöscht.
Volker Schulz schrieb:
> Hehe...>> Mit der Methode von Karl Heinz wird der Overhead ja ziemlich> unkalkulierbar.
Ich sagte doch, dass das nur dann Sinn macht, wenn man einige Bytewerte
nur relativ selten braucht. Wenn jedes zweite Byte substituiert wird,
macht es nicht viel Sinn.
> Und wenn einem das nichts ausmacht, weil man sowieso> keine festen Wiederholungraten braucht, kann man auch gleich die Option> mit der Zwangspause zwischen zwei Uebertragungen nehmen. Ist vermutlich> einfacher zu implementieren. ;)
Kommt drauf an.
Da musst du wieder eine Uhr mitlaufen haben
technikus schrieb:
>> 0xFF ist das STartbyte>> muss in den Daten 0xFF übertragen werden, so wird stattdessen zb 0xFE>> 0x01 übertragen. Da jetzt 0xFE eine Sonderrolle zukommt, wird das>> ursprüngliche 0xFE als 0xFE 0x00 übertragen.>> Baut man diese Substitution tief unten in die Softwarelayer ein, so ist>> das alles für darüberliegende Softwareschichten transparent und sie>> merken nichts davon.>> Dadurch dass ich Werte von 0x00 ... 0xFF übertragen muss, gibt es da> kein Zeichen welches weniger oft vorkommt.
In den meisten Fällen gibt es das aber.
Und selbst wenn tatsächlich alle Bytewerte in gleicher Häufigkeit
auftauchen, so frisst dir die Substitution nur 2/256-tel der
Übertragungskapazität.
> den Zusammenhang nicht, aber müsste dann nicht ein anderes Zeichen> "frei" sein um ein Zeichen frei zu schaufeln und damit habe ich wieder> den Salat, da ja keins frei ist.
Nein.
Der Trick besteht darin, dass man eine definierte Sequenz von 2 Zeichen
hintereinander als 1 Zeichen missbraucht.
> danach wieder zusammen zu bauen. Also bei einem 0xFF einmal 0x0F und> danach nochmal 0x0F zu übertragen.
Und du machst dir Sorgen weil 2 speziell ausgesuchte Bytewerte länger
zur Übertragung benötigen?
> Somit hätte ich alle Werte über 0x0F> frei (quasi als Kennungen).
Da kannst du auch gleich ASCII übertragen. Hat dann den Vorteil, dass du
mit einem Terminal auch mitlesen kannst.
Karl heinz Buchegger schrieb:
> Volker Schulz schrieb:>> Hehe...>>>> Mit der Methode von Karl Heinz wird der Overhead ja ziemlich>> unkalkulierbar.>> Ich sagte doch, dass das nur dann Sinn macht, wenn man einige Bytewerte> nur relativ selten braucht. Wenn jedes zweite Byte substituiert wird,> macht es nicht viel Sinn.
Ich bezog mich ja auch auf des Fragestellers 16- oder 32-Bit-Ints. Und
da reicht's schon wenn bei je einer Zahl nur ein Byte substituiert wird.
Deine Loesung ist ja in der Datenkommunikation auch durchaus ueblich,
hier wuerde ich aber einen anderen Ansatz verfolgen. War alles andere
als boese gemein!
>>> Und wenn einem das nichts ausmacht, weil man sowieso>> keine festen Wiederholungraten braucht, kann man auch gleich die Option>> mit der Zwangspause zwischen zwei Uebertragungen nehmen. Ist vermutlich>> einfacher zu implementieren. ;)>> Kommt drauf an.> Da musst du wieder eine Uhr mitlaufen haben
Nicht zwingend. Wenn man sowieso dauernd pollt ob Daten reingekommen
sind, kann man auch einfach zaehlen wie oft das nicht der Fall war. Bei
einem Interrupt "on receive" wird das natuerlich nix. ;)
Volker
technikus schrieb:
> Ich hatte schon überlegt die Bytes in zwei Einzelbytes zu Splitten und> danach wieder zusammen zu bauen. Also bei einem 0xFF einmal 0x0F und> danach nochmal 0x0F zu übertragen. Somit hätte ich alle Werte über 0x0F> frei (quasi als Kennungen).> Ist so etwas üblich?
Neee.. damit verdoppelst Du ja das Datenvolumen und laesst pro Byte 3
Bits voellig ungenutzt rumliegen. Dann doch lieber 9N1, oder?
Volker
Ich würde einfach Hex-Zeichen übertragen, dann wären die ganzen schönen
ASCII-Steuerzeichen frei, jedes uint16 wäre 4 Zeichen und ein uint32
wäre 8 zeichen lang.
Und nachdem hier noch kein Wort zur benötigten Bandbreite/Datenrate
aufgetaucht ist, darf ich das ohne Einschränkung tun. Es ist m.E. immer
Käse, wenn auf einer seriellen Schnitte binäre Daten rumtigern. Man tut
sich dann beim Mithören via Terminal immer so schwer... ;-)
Thomas Burkhart schrieb:
> Ich würde ein festes Frameformat verwenden, was spricht denn dagegen?
Im Grunde gar nichts :-)
Denn genau darum geht es ja: Wie synchronisierst du dich denn mit dem
'fixen Frameformat'. Woran erkennst du 100% zuverlässig den Frameanfang.
Und zwar auch dann, wenn zwischendurch mal der Stecker gezogen und
wieder eingesteckt wird.
Ist man erst mal synchron, dann ist das alles sowieso Makulatur.
Interessant sind die Fälle, in denen ein Benutzer sein Anzeigegerät
irgendwo anstopselt und auch noch korrekte Daten erwartet.
"Zuerst Gerät A einschalten und dann erst Gerät B, alles andere ist
Benutzerfehler" konnte man zuletzt in den 60-er Jahren des letzten
Jahrhunderts in die Gebrauchsanweisung schreiben. Heutzutage erwarten
Benutzer, dass sie sich ohne Abschalten einfach einstöpseln und Dinge in
beliebiger Reihenfolge einschalten können. Und dann muss alles immer
noch sauber funktionieren.
Lothar Miller schrieb:
> Es ist m.E. immer> Käse, wenn auf einer seriellen Schnitte binäre Daten rumtigern. Man tut> sich dann beim Mithören via Terminal immer so schwer... ;-)
d´accore
Ganz zu schweigen von der elenden Rumrechnerei auf Byteebene bei der
Fehlersuche. Und dann noch Hi-Byte zuerst / Low Byte zuerst?
Wird eine Serielle eingesetzt, dann soll es auf ein paar ms auf oder ab
nicht ankommen :-)
Karl heinz Buchegger schrieb:
> Lothar Miller schrieb:>> Es ist m.E. immer>> Käse, wenn auf einer seriellen Schnitte binäre Daten rumtigern. Man tut>> sich dann beim Mithören via Terminal immer so schwer... ;-)>> d´accore>> Ganz zu schweigen von der elenden Rumrechnerei auf Byteebene bei der> Fehlersuche. Und dann noch Hi-Byte zuerst / Low Byte zuerst?>> Wird eine Serielle eingesetzt, dann soll es auf ein paar ms auf oder ab> nicht ankommen :-)
Und so'n Hex-Zeichen wird natuerlich nicht binaer uebertragen, oder wie?
Und byteweise auch nicht? Und wenn doch, ist die Reihenfolge der Bytes
nochmal wo festgeschrieben? ;)
Aber ich glaube, wir koennen erst nach weiteren Angaben von technikus
den ultimativen Loesungsvorschlag waehlen.
Volker
Volker Schulz schrieb:
> Karl heinz Buchegger schrieb:>> Lothar Miller schrieb:>>> Es ist m.E. immer>>> Käse, wenn auf einer seriellen Schnitte binäre Daten rumtigern. Man tut>>> sich dann beim Mithören via Terminal immer so schwer... ;-)>>>> d´accore>>>> Ganz zu schweigen von der elenden Rumrechnerei auf Byteebene bei der>> Fehlersuche. Und dann noch Hi-Byte zuerst / Low Byte zuerst?>>>> Wird eine Serielle eingesetzt, dann soll es auf ein paar ms auf oder ab>> nicht ankommen :-)>> Und so'n Hex-Zeichen wird natuerlich nicht binaer uebertragen, oder wie?> Und byteweise auch nicht? Und wenn doch, ist die Reihenfolge der Bytes> nochmal wo festgeschrieben? ;)
Nun ja. Festgeschrieben nicht.
Aber die übliche Konvention ist es dann doch, dass der Text "123" als
hundert drei und zwanzig zu lesen ist.
Insofern ist die Übertragung von
"PA358,876;"
schon sehr eindeutig und lässt relativ wenig Spielraum für
Fehlinterpretation.
> Aber ich glaube, wir koennen erst nach weiteren Angaben von technikus> den ultimativen Loesungsvorschlag waehlen.
Ganz abgesehen davon, dass es "Die ultimative Lösung" nicht gibt :-)
Hallo,
erst einmal vielen Dank für eure rege Beteidigung!
Ihr macht es einem Hobby Programmierer ja ganz schön schwer ;-)
Um es konkret zu machen:
Ich möchte
- 2x 32Bit UInt
- 4x 16Bit UInt
übertragen. Im Mikrocontrollerprogramm sollen die Werte dann in ein
EEPROM geschrieben und ein Reset ausgelöst werden.
Auf Anforderung des PC´s sollen die Daten dann zum PC gesendet und im
GUI angezeigt werden.
Die Werte werden alle paar Schaltjahre angepasst und sollen nur zur
Konfiguration an die Umgebung dienen.
Volker Schulz schrieb:
>> Ich hatte schon überlegt die Bytes in zwei Einzelbytes zu Splitten und>> danach wieder zusammen zu bauen. Also bei einem 0xFF einmal 0x0F und>> danach nochmal 0x0F zu übertragen. Somit hätte ich alle Werte über 0x0F>> frei (quasi als Kennungen).>> Ist so etwas üblich?>> Neee.. damit verdoppelst Du ja das Datenvolumen und laesst pro Byte 3> Bits voellig ungenutzt rumliegen. Dann doch lieber 9N1, oder?
und
Lothar Miller schrieb:
> Ich würde einfach Hex-Zeichen übertragen, dann wären die ganzen schönen> ASCII-Steuerzeichen frei, jedes uint16 wäre 4 Zeichen und ein uint32> wäre 8 zeichen lang.
schließt das eine nicht das andere aus? Wenn ich hex Zeichen übertrage,
brauche ich doch für ein Byte, z.B. 0xFE, zwei hex Zeichen. Also 'F' und
'E'.
Volker Schulz schrieb:
> Und so'n Hex-Zeichen wird natuerlich nicht binaer uebertragen, oder wie?> Und byteweise auch nicht? Und wenn doch, ist die Reihenfolge der Bytes> nochmal wo festgeschrieben? ;)>> Aber ich glaube, wir koennen erst nach weiteren Angaben von technikus> den ultimativen Loesungsvorschlag waehlen.
Ich verstehe im Moment wohl zu wenig.
Fest steht, dass ich 16Bytes übertragen muss. Bei der Möglichkeit 1Byte
in die oberen 4Bit und unteren 4Bit zu trennen, müsste ich demnach
32Bytes übertragen. <---Meint ihr das mit??? > Ich würde einfach
Hex-Zeichen übertragen
So hätte ich ne Menge anderer Zeichen, z.B. für die Anforderung Daten
zum PC senden, frei.
Gruß
ersnt
Karl heinz Buchegger schrieb:
> Nun ja. Festgeschrieben nicht.> Aber die übliche Konvention ist es dann doch, dass der Text "123" als> hundert drei und zwanzig zu lesen ist.
Hehe.. da stimme ich zu. Lothar, mit dem du d'accord gegangen bist,
hatte aber vorgeschlagen HEX-ASCII zu uebertragen. Und da sind durchaus
verschiedene Konventionen ueblich. Und bei der Byteorder gehoert es
eigentlich zum guten Ton, sie der Bitorder gleichzustellen, aber es
haelt sich eben noch lange nicht jeder daran.
> Ganz abgesehen davon, dass es "Die ultimative Lösung" nicht gibt :-)
Fuer genau ein Problem ist die Moeglichkeit der ultimativen Loesung aber
zumindest gegeben... Obwohl ich mir da auch nicht mehr 100%-ig sicher
bin, seit ich dieses Forum kenne. ;)
Auf jeden Fall macht's Spass mit Euch zu diskutieren.
Volker
technikus schrieb:
> Volker Schulz schrieb:>>> Ich hatte schon überlegt die Bytes in zwei Einzelbytes zu Splitten und>>> danach wieder zusammen zu bauen. Also bei einem 0xFF einmal 0x0F und>>> danach nochmal 0x0F zu übertragen. Somit hätte ich alle Werte über 0x0F>>> frei (quasi als Kennungen).>>> Ist so etwas üblich?>>>> Neee.. damit verdoppelst Du ja das Datenvolumen und laesst pro Byte 3>> Bits voellig ungenutzt rumliegen. Dann doch lieber 9N1, oder?>> und>> Lothar Miller schrieb:>> Ich würde einfach Hex-Zeichen übertragen, dann wären die ganzen schönen>> ASCII-Steuerzeichen frei, jedes uint16 wäre 4 Zeichen und ein uint32>> wäre 8 zeichen lang.>> schließt das eine nicht das andere aus? Wenn ich hex Zeichen übertrage,> brauche ich doch für ein Byte, z.B. 0xFE, zwei hex Zeichen. Also 'F' und> 'E'.
Juppa.. Das eine hab ja auch ich gesagt, das andere Lothar. Und wir
schliessen uns anscheinend gerne gegenseitig aus. ;)
Der Vorschlag von Lothar ist im Prinzip das, worauf Du auch schon
gekommen bist.
Die Loesung wird so auch funktionieren, sie verschwendet eben nur 3 Bit
pro Byte. Wenn Du aber nur wenige Daten und die auch nicht besonders
schnell uebertragen musst, ist's so das einfachste.
Viel Erfolg!
Volker
technikus schrieb:
> Um es konkret zu machen:> Ich möchte> - 2x 32Bit UInt> - 4x 16Bit UInt> übertragen. Im Mikrocontrollerprogramm sollen die Werte dann in ein> EEPROM geschrieben und ein Reset ausgelöst werden.>> Auf Anforderung des PC´s sollen die Daten dann zum PC gesendet und im> GUI angezeigt werden.>> Die Werte werden alle paar Schaltjahre angepasst und sollen nur zur> Konfiguration an die Umgebung dienen.
Ganz klar: per ASCII Zeichen übertragen.
Schon alleine aus dem Grund, weil nach ein paar Schaltjahren das
Einstellprogramm nicht mehr auffindbar ist und es dann jedes
Billigsdorfer Terminalprogramm auch tut. Zeitkritisch ist das ganze
offenbar auch nicht.
Protokoll:
Einleitender Buchstabe, der bestimmt welche Aktion ausgeführt werden
soll
Dann die Zahl (oder Zahlen, zb mit Komma getrennt - meinetwegen auch als
Hex-Zahl) und hinten nach noch ein \n. So kann nichts passieren und zum
Entwickeln muss das Frontend-GUI auch noch nicht fertig sein.
Der µC empfängt eine Befehlszeile als String, holt sich die Einzelteile
raus, wandelt die Stringrepräsentierung der Zahlen in echte Zahlen um
(das sind 4-Zeiler) und führt die Aktion aus, bzw. umgekehrt: er liefert
seine Werte wieder als ASCII Zahl (itoa ist dein Freund).
Das bischen Aufwand der Textübertragung würde ich eingehen. Alleine die
unabhängige Testbarkeit der µC Ebene und der PC Ebene wäre mir das schon
wert.
Zum besseren Verstaendnis:
Lothar wuerde HEX-ASCII uebertragen. Also anstatt 0x0F wuerde er den
Buchstaben F uebertragen. Aber das shiftet im Prinzip nur Deinen
Vorschlag nach oben.
Volker
> Lothar wuerde HEX-ASCII uebertragen.> Also anstatt 0x0F wuerde er den Buchstaben F uebertragen.
Ich würde das nicht, ich mache das ;-)
Eben so, dass ich das mit jedem xyz-beliebigen Terminal anzeigen und
mithorchen könnte (zur Not an einem mechanischen mit Glocke 7).
In C gibts für die "erlaubten" Zeichen die Funktionen/Makros isalnum()
oder etwas entschärft isprint(). Alle Andere sind für mich Steuerzeichen
;-)
Karl heinz Buchegger schrieb:
> Ganz klar: per ASCII Zeichen übertragen.> Schon alleine aus dem Grund, weil nach ein paar Schaltjahren das> Einstellprogramm nicht mehr auffindbar ist und es dann jedes> Billigsdorfer Terminalprogramm auch tut. Zeitkritisch ist das ganze> offenbar auch nicht.>>> Protokoll:> Einleitender Buchstabe, der bestimmt welche Aktion ausgeführt werden> soll> Dann die Zahl (oder Zahlen, zb mit Komma getrennt - meinetwegen auch als> Hex-Zahl) und hinten nach noch ein \n. So kann nichts passieren und zum> Entwickeln muss das Frontend-GUI auch noch nicht fertig sein.> Der µC empfängt eine Befehlszeile als String, holt sich die Einzelteile> raus, wandelt die Stringrepräsentierung der Zahlen in echte Zahlen um> (das sind 4-Zeiler) und führt die Aktion aus, bzw. umgekehrt: er liefert> seine Werte wieder als ASCII Zahl (itoa ist dein Freund).
O.K. meine Idee war ja die oberen und unteren 4 Bit zu trennen.
Die Idee hatt eich nur, weil ich da weiß, wie ich das im Programm
umsetzen könnte.
Die c# Seite habe ich nun entsprechend angepasst. Erst wird ein
Startzeichen gesendet. Darauf hin sende ich die Daten als Hex in
Einzelzeichen.
Z.B.
'#' 'F' 'F'
was ja 255 entspricht. Wie baue ich denn jetzt die Daten so zusammen,
dass ich ein Byte im EEPROM füllen kann?
Ich nehme mal an, dass empfangspuffer ein Array vom Typ Byte und nicht
vom Typ Char ist. Also ist der Inhalt von empfangspuffer[0] nicht 'F'
(der Buchstabe) sondern 0x0F (der Hex-Wert), oder?
Binaer sieht der Inhalt dann so aus: 0b00001111.
Analog gilt das natuerlich auch fuer empfangspuffer[1].
Nun nimmst Du das Byte mit den 4 hoeherwertigen Bits und machst einen
left shift um 4 Stellen. Nehmen wir mal an, empfangspuffer[0] hat die
hoeherwertigen Bits, dann: empfangspuffer[0] << 4. Und nun werden die
beiden noch ver-odert um die niederwertigen Bits anzuhaegen:
empfangspuffer[0] | empfangspuffer[1]. Heraus kommt dann 0xFF bzw.
0b11111111.
Fertig.
Volker
technikus schrieb:
> Die c# Seite habe ich nun entsprechend angepasst. Erst wird ein> Startzeichen gesendet. Darauf hin sende ich die Daten als Hex in> Einzelzeichen.> Z.B.>> '#' 'F' 'F'>> was ja 255 entspricht. Wie baue ich denn jetzt die Daten so zusammen,> dass ich ein Byte im EEPROM füllen kann?>>
1
>//zusammen 255 dezimal
2
>empfangspuffer[0];//Inhalt 'F'
3
>empfangspuffer[1];//Inhalt 'F'
4
>
Mach dir eine Funktion, die einen 'Buchstaben' wieder in sein
numerisches Äquivalent umwandelt
1
unsignedcharToNum(chardigit)
2
{
3
if(digit<='9')
4
returndigit-'0';
5
6
returndigit-'A'+10;
7
}
damit sollte es jetzt nicht weiter schwer sein, die Zahl wieder
zusammenzusetzen
Das Beispiel 0xFF ist jetzt ein wenig blöd, weil man High und Low-Nibble
nicht mehr unterscheiden kann... :-/
Nehmen wir mal 0xA5 = 165dez --> ASCII '#' 'A' '5' --> in C
1
empfangspuffer[0];// Inhalt 'A' Hex-Zahl in Großbuchstaben!!
Volker Schulz schrieb:
> Ich nehme mal an, dass empfangspuffer ein Array vom Typ Byte und nicht> vom Typ Char ist. Also ist der Inhalt von empfangspuffer[0] nicht 'F'> (der Buchstabe) sondern 0x0F (der Hex-Wert), oder?
O.K. das war mein erster Ansatz, hier war mir klar wie ich das erledige
;-)
Durch oben stehende Diskussion wollte ich aber jetzt das Datenpaket als
Zeichen '0'...'9' 'A'...'F' senden. Das heißt als Char
z.B. '0' = 48 ; 'A' = 65
ich müsste also aus
technikus schrieb:
> Volker Schulz schrieb:>> Ich nehme mal an, dass empfangspuffer ein Array vom Typ Byte und nicht>> vom Typ Char ist. Also ist der Inhalt von empfangspuffer[0] nicht 'F'>> (der Buchstabe) sondern 0x0F (der Hex-Wert), oder?>> O.K. das war mein erster Ansatz, hier war mir klar wie ich das erledige> ;-)>> Durch oben stehende Diskussion wollte ich aber jetzt das Datenpaket als> Zeichen '0'...'9' 'A'...'F' senden. Das heißt als Char
Du bist ja leicht zu beeinflussen! Und das Frame-Start-Bit hat auch
gleich ein eigenes Byte bekommen! Ihr seid ja alle so dekadent! Koennen
wir ja auf 5N1 runtergehen... ;)
Aber zum Zurueckkonvertieren aus HEXASCII wurde ja alles Wichtige
gesagt. Zum besseren Verstaendnis schauste hier:
http://www.asciitable.com/
Freut mich dass wir eine Loesung gefunden haben, auch wenn's nicht meine
war. Aber eine ultimative, sozusagen! ;)
Volker
Karl heinz Buchegger schrieb:
> [...]> damit sollte es jetzt nicht weiter schwer sein, die Zahl wieder> zusammenzusetzen>>
1
>unsignedcharToNumber(chardigit1,chardigit2)
2
>{
3
>return(ToNum(digit1)*16)+ToNum(digit2);
4
>}
5
>
Ah, das interessiert mich jetzt doch noch. Nicht dass hier einer der
Beteiligten Wert auf Effizienz legen wuerde ;), aber ich programmiere
die AVRs generell in ASM, daher ruehrt die Frage:
Was macht der C-Compiler aus
1
ToNum(digit1)*16
?
Einen echten Shift oder multipliziert der tatsaechlich zu Fuss? Und wie
sieht das auf einem AVR ohne Hardware-Multiplizierer aus?
Volker
Volker Schulz schrieb:
> Was macht der C-Compiler aus>
1
>ToNum(digit1)*16
2
>
> ?> Einen echten Shift
Du kannst dich darauf verlassen, dass der Compilerbauer seinem Kindchen
die Fähigkeit mitgegeben hat, einfache Multiplikationen mit 2-er
Potenzen zu erkennen und durch Shifts zu ersetzen, wenn es möglich und
schneller ist. Aber Compiler erkennen auch komplexere Fälle und ersetzen
diese durch Shift-Additionssequenzen, wenn dies möglich UND tatsächlich
schneller ist.
(zb: 10 * x <==> ( ( x << 2 ) + x ) << 1 )
Wenn ein Compiler diese simple Optimierung nicht kann, besteht die
Lösung nicht darin, selber Hand anzulegen sondern den Compiler zu
wechseln. Denn dann ist er Müll.
Fazit: Solche Low-Level Optimierungen überlasst man besser dem Compiler.
Als Programmierer schreibt man so, wie es für den Programmierer am
besten zu lesen ist und wie es der Situation am besten entspricht.
Bei obigem ist es so ein Grenzfall:
Logisch gesehen wäre beides akzeptabel.
Die Sichtweise: Die Zahl ergibt sich, indem das Nibble zurechtegschoben
wird
Aber auch die Sichtweise: Bei einer Zahl zur Basis 16 unterscheiden sich
die einzelnen Stellen durch einen Faktor 16.
Ursprünglich hatte ich einen Shift, hab dann aber umgedreht, als in
seiner letzten Anfrage die Frage auftauchte, wie man aus 'F' 'F' die
Dezimalzahl 255 zusammenbaut.
Karl heinz Buchegger schrieb:
> Volker Schulz schrieb:>>> Was macht der C-Compiler aus>>
1
>>ToNum(digit1)*16
2
>>
>> ?>> Einen echten Shift
Das ist ja schonmal gut. Kann man in C auch einen SWAP veranlassen? Dann
muesste man ja nochmal 75% der cycles einsparen...
Ich weiss, ich bin pedantisch.... Aber einer muss ja mal fragen! ;)
Volker
Volker Schulz schrieb:
> Das ist ja schonmal gut. Kann man in C auch einen SWAP veranlassen?
Das musst du ausprobieren.
AUf Hochsprachenebene gibt es keine einzelne Operation, die einem SWAP
entsprechen würde. Das geht nur mit einer Kombination. Von daher halte
ich die Chance eher für gering. Aber wie heißt es so schön: Du sollst
dich nicht täuschen.
Hmm. Einen Kaffee später
Die Operation
uint8_t i;
i = 16*i;
könnte man ja mit der Assemblersequenz
swap i
and i, 0xF0
implementieren. Wenn der Optimizer das so sieht, steigen die Chance auf
deinen Swap wieder.
Bei einem reinen AVR Compiler würde ich das als gar nicht mal so
schlecht sehen.
Das Problem:
C fordert, dass 16*i in int gerechnet wird. Der gcc als
Universalcompiler für alle Maschinen, hält sich natürlich daran. D.h. er
hat das zusätzliche Problem, dass sich zwischendurch die Berechnung (in
diesem Fall unnötigerweise) auf 16 Bit aufbläst um dann vom Optimizer
wieder auf 8 Bit zurechtgestutzt zu werden. Und wir wissen, dass dieses
Zurechtstutzen schon manchmal in die Hose geht :-(
(Und nein. Letztes Problem würde auch dann auftauchen, wenn da ein
expliziter Shift stehen würde)
Und in diesem spieziellen Fall waere ja sogar nur der SWAP noetig und
man koennte sich das AND sparen, da das obere Nibble (dank der
dekandenten Uebertragungsweise) ja sowieso nichts anderes als 0 sein
kann. Aber das kann der Compiler natuerlich nicht wissen. ;)
Volker
Noch mal zur ursprünglichen Fragestellung. Wozu der aufwand mit
Codierung von start/stoppzeichen wenn ich ein frameformat verwenden kann
in dem jeweils drin steht wie lange mein Datenblock ist.
Gruß
Tom
Thomas Burkhart schrieb:
> Noch mal zur ursprünglichen Fragestellung. Wozu der aufwand mit> Codierung von start/stoppzeichen wenn ich ein frameformat verwenden kann> in dem jeweils drin steht wie lange mein Datenblock ist.
Weil der Empfaenger im Zweifel nicht weiss wo der Frame anfaengt... Und
somit natuerlich auch nicht, wo die Laenge steht.
Volker
Thomas Burkhart schrieb:
> Noch mal zur ursprünglichen Fragestellung. Wozu der aufwand mit> Codierung von start/stoppzeichen wenn ich ein frameformat verwenden kann> in dem jeweils drin steht wie lange mein Datenblock ist.
Und als Beispiel:
Du klinkst dich in eine Übertragung ein und empfängst
04 00 03 05 02 01 08 56 03 ...
welches ist die richtige Interpretation?
Du weißt nicht, was vor dem 04 kam. Sind diese 04 die letzten Bytes
eines vorhergehenden Datensatzes oder sind sie dein Längenbyte?
ist das zb so zu lesen
.. 04 00 // wird verworfen
03 05 02 01
08 56 03 ....
oder vielleicht so
.. 04 00 03
05 02 01 08 56 03
...
oder eventuell so
.. 04 00 03 05
02 01 08
56 03 ...
oder eventuell gar
04 00 03 05 02
01 08
56 03 ...
Je nachdem ergeben sich ganz unterschiedliche Interpretationen, wenn man
nicht sicher sein kann, dass das erste Byte, welches empfangen wird,
auch tatsächlich das erste Byte deines Frames ist.
Wenn alles glatt läuft und der Empfänger aufnahmebereit ist ehe der
Sender zu senden anfängt, hast du den Fall nicht. Aber im Fehlerfall
kommt das schon vor. zb: Die Übertragung läuft schon, wenn sich der
Empfänger aufschaltet, Kabel wird von der Putzfrau abgezogen und wieder
aufgesteckt. Der Empfänger war durch Berechnungen zu lange beschäftigt
und hat ein Byte verschlafen, Bufferüberlauf beim Empfänger, etc...
> wenn ich ein frameformat verwenden kann> in dem jeweils drin steht wie lange mein Datenblock ist.
Wozu ein aufwendiges Frameformat (incl. entsprechend aufwendiger
Auswertung) definieren, wenn es einfacher geht? Was könnte einfacher
sein als nur auf das Ende-Zeichen zu warten, und dann die vorhergehenden
Zeichen auszuwerten?
1
if(UCSRA&(1<<RXC)){// Zeichen über SIO angekommen?
2
charch=UDR;
3
if(ch==STX){// Wenn STX: Schreibzeiger zurücksetzen
4
idx=0;
5
}
6
else{
7
if(ch==ETX){// Endezeichen -- in 0 umwandeln zur Stringterminierung
8
ch=0;
9
datavalid=1;
10
}
11
buf[idx]=ch;
12
if(idx<MAXCHAR-1)idx++;// Schutz vor Pufferüberlauf
Lothar Miller schrieb:
>> wenn ich ein frameformat verwenden kann>> in dem jeweils drin steht wie lange mein Datenblock ist.> Wozu ein aufwendiges Frameformat (incl. entsprechend aufwendiger> Auswertung) definieren, wenn es einfacher geht? Was könnte einfacher> sein als nur auf das Ende-Zeichen zu warten, und dann die vorhergehenden> Zeichen auszuwerten?
Darum ging es ja die ganze Zeit: Es sollten volle 8 Bit uebertragen
werden und es war kein Platz fuer Steuerzeichen da. ;)
Karl heinz Buchegger schrieb:
> [...]> Und als Beispiel:> Du klinkst dich in eine Übertragung ein und empfängst> [...]
Fairerweise muss man aber auch anmerken dass das "Einklinken" bei
serieller Uebertragung ohnehin nicht ganz unproblematisch ist. Das kann
immerhin auch in der Mitte von einem Byte passieren und synchronisieren
kann sich der Empfaenger erst nach einer entsprechenden Pause zwischen 2
Bytes (die so aber in der Spec nirgendwo explizit gefordert wird).
Volker
Volker Schulz schrieb:
> Darum ging es ja die ganze Zeit: Es sollten volle 8 Bit uebertragen> werden und es war kein Platz fuer Steuerzeichen da. ;)
Aber davon sind wir doch aus pragmatischen Gründen schon lange
abgekommen, dekadent wie wir sind... ;-)
Lothar Miller schrieb:
> sein als nur auf das Ende-Zeichen zu warten, und dann die vorhergehenden> Zeichen auszuwerten?>
1
>if(UCSRA&(1<<RXC)){// Zeichen über SIO angekommen?
2
>charch=UDR;
3
>if(ch==STX){// Wenn STX: Schreibzeiger zurücksetzen
4
>idx=0;
5
>}
6
>else{
7
>if(ch==ETX){// Endezeichen -- in 0 umwandeln zur
8
>Stringterminierung
9
>ch=0;
10
>datavalid=1;
11
>}
12
>buf[idx]=ch;
13
>if(idx<MAXCHAR-1)idx++;// Schutz vor Pufferüberlauf
14
>elseoverflow=1;
15
>}
16
>}
17
>
Fast.
Ich würde hier
> if(ch==ETX) { // Endezeichen -- in 0 umwandeln zur> Stringterminierung> ch=0;> datavalid=1;> }
noch eine Überprüfung reinsetzen, ob das STX überhaupt gesehen wurde und
den Datensatz erst dann freigeben (und die STX-gesehen Kennung wieder
zurücksetzen).
Lothar Miller schrieb:
> Volker Schulz schrieb:>> Darum ging es ja die ganze Zeit: Es sollten volle 8 Bit uebertragen>> werden und es war kein Platz fuer Steuerzeichen da. ;)> Aber davon sind wir doch aus pragmatischen Gründen schon lange> abgekommen, dekadent wie wir sind... ;-)
Jaja... ICH hab das ja auch nicht wieder aufgewaermt... :)
Volker
> Ich würde hier... noch eine Überprüfung reinsetzen, ob das STX überhaupt> gesehen wurde und den Datensatz erst dann freigeben (und die STX-gesehen> Kennung wieder zurücksetzen).
Das ist in meiner Original-Routine schon drin. Es werden die STX und die
ETX mitgezählt, und nur bei Gleichstand gilt das Telegramm als gültig.
Dazu kommt dann noch eine Kontrolle der Prüfsumme und eine Längenprüfung
des gesamten Telegramms (über den idx)... ;-)
Volker Schulz schrieb:
> Du bist ja leicht zu beeinflussen! Und das Frame-Start-Bit hat auch> gleich ein eigenes Byte bekommen!
Ich bin eben nur Hobby Programmierer und bei meinen Spielereien auf
euch angewiesen. Deswegen auch schnell beeinflussbar ;-)
Ob jetzt 10 oder 30 Bytes übertragen werden ist bei meiner Anwendung
auch egal.
Die Mikrocontroller Seite programmiere ich die Tage, PC (c#) Seite
steht.
Ein interessanter Beitrag ist das hier geworden!
Tolles Forum ;-)
Ich danke allen Beteiligten!
Gruß
ernst
Volker Schulz schrieb:
> Jaja... ICH hab das ja auch nicht wieder aufgewaermt... :)>> Volker
Ok,ok, ich hatte nicht mitbekommen, dass Ihr jetzt komplett in Hex
übertragt. Dachte Ihr seid noch am wilden escapen.
Das Problem mit dem Aufsetzen war mir schon klar. Nur wenn ich weiß wie
lang meine Pakete sind (geht natürlich nur wenn das immer gleich ist)
dann weiß ich nach wie vielen Bytes spätestens wieder mein Header kommen
müsste und wenn der da nicht kommt, dann muss bei Sender nachgefragt
werden.
Aber wie ihr schon gesagt habt, wir sind dekadent und wollen am Analyser
ja mitlesen können :-)
Gruß
Tom
Thomas Burkhart schrieb:
> Ok,ok, ich hatte nicht mitbekommen, dass Ihr jetzt komplett in Hex> übertragt. Dachte Ihr seid noch am wilden escapen.
ASCII ist das Schlüsselwort. Ob da jetzt Hex-Zahlen hin und her
flutschen oder Dezimalzahlen spielt keine Rolle. Hauptsache als Text
(wodurch die restlichen Buchstaben des Alphabets als Steuerzeichen frei
werden)
> Das Problem mit dem Aufsetzen war mir schon klar. Nur wenn ich weiß wie> lang meine Pakete sind (geht natürlich nur wenn das immer gleich ist)
damit haben wir schon Voraussetzung Nummer 1
> dann weiß ich nach wie vielen Bytes spätestens wieder mein Header kommen> müsste und wenn der da nicht kommt, dann muss bei Sender nachgefragt> werden.
und das ist dann Voraussetzung Nummer 2
Und wie gehst du das Problem an, dass du ein falsches Byte als Start
deines Headers (woran erkennst du denn den?) fehlinterpretierst?
Und dann kommt da noch Voraussetzung Nummer 3:
Der Sender muss in der Lage sein auf dich zu hören, seine aktuelle
Übertragung abzubrechen und dir garantiert einen Frameanfang
vorzusetzen.
Mit dezidierten Start/Stop Sequenzen, die eindeutig erkennbar sind,
braucht es all diese Voraussetzungen nicht. Der Sender schickt einfach
raus und der Empfänger kann eindeutig, auch nach einem Fehler, den
Frameanfang im Datenstrom finden.
> Aber wie ihr schon gesagt habt, wir sind dekadent und wollen am Analyser> ja mitlesen können :-)
Und falls wir das nicht wollen, sind wir auch dekadent genug, den
Datenstrom so aufzubereiten, dass der Empfänger keine Rückfragen braucht
:-) Wir sind nämlich nicht nur dekadent sondern auch faul :-) Wird
Funktionalität nicht benötigt (weil überflüssig), muss sie im Sender
auch nicht implementiert werden. Der Empfänger muss keine wilden
Verrenkungen machen um festzustellen ob nicht eigentlich schon ein
Header vorliegen müsste etc.
Im Vergleich dazu ist die Auswertung von Start /Stopp Bytes im Empfänger
geradezu ein Spaziergang.
Ein kleiner Schritt für Sender/Empfänger. Ein großer Schritt für die
Interpretationssicherheit beim Empfänger.
Für 11Bytes Nutzdaten sende ich jetzt 22+1Byte(Startzeichen). Dafür habe
ich jetzt noch einige Zeichen frei um andere Aktionen im Controller
auszuführen.
Gruß
ernst
technikus schrieb:
> es läuft :-))
Das freut mich!
>
1
>//22 Byte angekommen?
2
>if(i==22)
3
>return1;
4
>else
5
>return0;
6
>
7
>
Es waere vielleicht noch sinnvoll, das innerhalb des aeusseren If-Blocks
zu packen und danach die funktion zu verlassen. Denn:
1.) wird i ja nur zu 22 wenn auch vorher ein Zeichen empfangen wurde
und
2.) bleibt i ja 22 bis dann wieder ein neues Start-Byte empfangen wurde.
und wenn es gar nicht erst in den If-Block geht, kannste ja immer 0
zurueckgeben.
>
Volker Schulz schrieb:
> Es waere vielleicht noch sinnvoll, das innerhalb des aeusseren If-Blocks> zu packen und danach die funktion zu verlassen. Denn:>> 1.) wird i ja nur zu 22 wenn auch vorher ein Zeichen empfangen wurde>> und>> 2.) bleibt i ja 22 bis dann wieder ein neues Start-Byte empfangen wurde.>> und wenn es gar nicht erst in den If-Block geht, kannste ja immer 0> zurueckgeben.
Also so?
Das oben gepostete Beispiel hatte ich "mal eben" so zusammen getippt.
Der Fehler ist nicht aufgefallen, da ich, nachdem ein kompletter Frame
angekommen ist, einen Reset des Controllers ausführe indem der Watchdog
angeschmissen wird und in eine Endlosschleife verharrt. Nach einem Reset
ist i ja wieder 0...trotzdem blöd...
Volker Schulz schrieb:
> Wenn es das gewuenschte Ergebnis liefert: Gut. Aber woher weiss> "ToNumber" denn wie es das konvertieren soll?
1
unsignedcharToNumber(chardigit1,chardigit2)
2
{
3
return(ToNum(digit1)*16)+ToNum(digit2);
4
}
5
6
7
unsignedcharToNumber(chardigit1,chardigit2)
8
{
9
return(ToNum(digit1)*16)+ToNum(digit2);
10
}
=> Hatte ich ja oben von Karl Heinz "geklaut".
Gruß
Ernst
technikus schrieb:
> Volker Schulz schrieb:>> Es waere vielleicht noch sinnvoll, das innerhalb des aeusseren If-Blocks>> zu packen und danach die funktion zu verlassen. Denn:>>>> 1.) wird i ja nur zu 22 wenn auch vorher ein Zeichen empfangen wurde>>>> und>>>> 2.) bleibt i ja 22 bis dann wieder ein neues Start-Byte empfangen wurde.>>>> und wenn es gar nicht erst in den If-Block geht, kannste ja immer 0>> zurueckgeben.>> [...]>> Also so?>> Das oben gepostete Beispiel hatte ich "mal eben" so zusammen getippt.> Der Fehler ist nicht aufgefallen, da ich, nachdem ein kompletter Frame> angekommen ist, einen Reset des Controllers ausführe indem der Watchdog> angeschmissen wird und in eine Endlosschleife verharrt. Nach einem Reset> ist i ja wieder 0...trotzdem blöd...
Ja, so hatte ich mir das gedacht. Haette ja sonst im besten Falle nur
Zeit gekostet, im schlimmsten Falle haettest Du aber einen Datensatz X
Mal ausgewertet. Aber bei einem Reset faellt das natuerlich nicht auf.
;)
> Volker Schulz schrieb:>> Wenn es das gewuenschte Ergebnis liefert: Gut. Aber woher weiss>> "ToNumber" denn wie es das konvertieren soll?>> [...]>> => Hatte ich ja oben von Karl Heinz "geklaut".
Ahja, verdammt... Hatte nur noch den Namen der eigentlichen Funktion
"ToNum" im Sinn und dachte, Du machst ploetzlich was anderes... ;)
Volker
Karl heinz Buchegger schrieb:
> Protokoll:> Einleitender Buchstabe, der bestimmt welche Aktion ausgeführt werden> soll> Dann die Zahl (oder Zahlen, zb mit Komma getrennt - meinetwegen auch als> Hex-Zahl) und hinten nach noch ein \n. So kann nichts passieren und zum> Entwickeln muss das Frontend-GUI auch noch nicht fertig sein.> Der µC empfängt eine Befehlszeile als String, holt sich die Einzelteile> raus, wandelt die Stringrepräsentierung der Zahlen in echte Zahlen um> (das sind 4-Zeiler) und führt die Aktion aus, bzw. umgekehrt: er liefert> seine Werte wieder als ASCII Zahl (itoa ist dein Freund).
Hallo,
ich denke das passt hier weiter ganz gut in den Thread.
Im PC Programm erwarte ich jetzt ebenso die Werte als Hex codierten
String.
Karl Heinz hatte geschrieben dass itoa hier mein Freund ist.
Ich möchte jetzt die Daten, auf Aufforderung vom PC, zum PC senden.
Ich nutze nun unten stehenden Code:
1
charpuffer[5];
2
charsendData[23];
3
4
//--Startzeichen
5
strcpy(sendData,"#");
6
7
//--Frequenz Stufe 1
8
itoa(frequenz1.value8.b4,puffer,16);
9
strcat(sendData,puffer);
10
11
itoa(frequenz1.value8.b3,puffer,16);
12
strcat(sendData,puffer);
13
14
itoa(frequenz1.value8.b2,puffer,16);
15
strcat(sendData,puffer);
16
17
itoa(frequenz1.value8.b1,puffer,16);
18
strcat(sendData,puffer);
19
20
21
//usw.
22
23
//--Daten senden
24
uart_puts(sendData);
25
uart_puts("\n");
Erstens erzeugt itoa hier kleine Buchstaben wie z.B. ff für 255.
Ich kann das relativ einfach im c# Programm auf Großbuchstaben umbauen,
hätte nur gerne die gleiche Formatierung wie im Sendeframe vom PC zum
Mikrocontroller, also Großbuchstaben.
Zweitens werden keine Nullen im String angehangen wenn die Variable
1
frequenz1.value8.bx=0;
Da ich aber den kompletten Inhalt übertragen möchte,
z.B.
'#' '0' '0' '0' '0' '0' '0' 'F' 'F'
für 255
passt itoa so nicht.
Trotz Forensuche habe ich nicht wirklich eine Lösung gefunden die mir
das gewünschte Ergebnis liefert.
Ich könnte mir da mit If abfragen ob da ne null drin ist und dann
"händisch" die nullen im String anhängen. Jedoch gefällt mir diese
Lösung nicht.
Gibt es da etwas fertiges?
Gruß
ernst
Hallo Lothar,
ich hätte es erwähnen sollen, sprintf kannte ich schon und hatte ich
auch damals in der Schule benutzen müssen. Da sich der Code aber so
ungemein aufbläht, suche ich nach etwas anderem.
Gruß
Ernst
Allerdings komme ich im moment nicht an die Harware ran.
Ich habe noch nie mit Strings als "Rückgabewert" in Funktionen
gearbeitet, von daher kann das hier auch großer Mist sein.
Feedback?
Gruß
ernst
Du darfst auch ohne Einschränkungen leserlich so schreiben:
1
if((n>>4)>9)
2
s[0]=(n>>4)-10+'A';
3
else
4
s[0]=(n>>4)+'0';
Dann hast du keine solchen Magic Numbers und siehst später besser, was
damit eigentlich gemeint ist...
Sonst kommst du irgendwann mal auf die Frage, was das soll:
1
if((n>>4)>9)
2
s[0]=(n>>4)+'7';
3
else
4
s[0]=(n>>4)+'0';
> Ich habe noch nie mit Strings als "Rückgabewert" in Funktionen> gearbeitet
Hier wird gar nichts zurückgegeben, da steht ein void als
Rückgabeparameter. Du manipulierst nur wie üblich über einen
char-Pointer ein (hoffentlich ausreichend großes) char-Array (aka.
String).
Danke!
Lothar Miller schrieb:
>> Ich habe noch nie mit Strings als "Rückgabewert" in Funktionen>> gearbeitet> Hier wird gar nichts zurückgegeben, da steht ein void als> Rückgabeparameter. Du manipulierst nur wie üblich über einen> char-Pointer ein (hoffentlich ausreichend großes) char-Array (aka.> String).
Deswegen Rückgabewert in ""
ernst