Hi, ich verzweifele gerade an einem Datentyp Problmen .... vielleicht hat ja jemand von euch eine Idee dazu. Also ich Werte die Drehimpulse eines Drehimpulsgebers aus um eine Uhr zu stellen. Das bereitstellen der Uhrzeit wird von einem DS1302 übernommen, der für seine "Uhr stellen" Routine Chars erwartet. (für 24.04.06 also 3 Char Variablen mit 24, 04 und 06 als Wert). So weit so gut .... wenn ich jetzt aber das Ergebnis der Drehimpulsroutine in ein char schreibe zählt er im hexadezimalem Format hoch ... wenn ich das Ergebnis in ein int schreibe zählt er Dezimal hoch ... doch dann bekomme ich ein Problem wenn ich den dezimalen Wert in die Char-Variable schreiben will, denn wenn ich die INT Variable in char umwandeln lasse habe ich wieder den Zahlenwert im Hex-Format. Also jetzt mal am Beispiel vom 24.05.06 - ich bekomme also 24 als Zählergebnis in meine Hilfsvariabeln - wenn ich nun mit sprintf die Int Hilfsvariable in ein char array schrieben lasse und dessen Inhalt in die Char-Variable (Uhr.dy = tmp;) dann bekomme ich glaube ich nur die Adresse des Array oder so jedenfalls kommt da nur mist raus .... - wenn ich die Hilfsvariable umwadeln lasse (uhr.dy = (unsigned char) tmp;) dann bekomme ich nicht 24 in uhr.dy sondern den entsprechenden Hex-Wert 18..... ich hoffe ich konnte das Problem versändlich wiedergeben und es gibt jemand der mit dami weiter helfen kann Vielen Dank Nils
vielleicht solltest du dir einfach mal die Format-Strings von "sprintf" angucken. Wenn man ein (unsigned) char hochzählt, passiert da exakt das gleiche als würde man ein (unsigned) Int hochzählen (bis auf den Übertrag von 255 -> 0).
Das hat mit den Datentypen an sich nichts zu tun. Für eine dezimale Darstellung muss der Zahlenwert in Dezimalstellen (BCD) umgewandelt werden. Daten im Controller sind zunächst immer binär bzw. hexadezimal (wobei das auch nur eine andere Darstellungsform ist). Ich kann mir jetzt nicht Dein komplettes Programm durchlesen, aber ich vermute mal (nach Deiner Beschreibung, ohne den Baustein zu kennen), dass Dein DS1302 gepackten BCD-Code erwartet. Du musst also erst umwandeln (z.B. Division durch 10 und Modulo 10). Du solltest vielleicht auch mal die Doku zur sprintf-Funktion zu Rate ziehen. Du benutzt (vermutlich) ein falsches Ausgabeformat. Die printf-Funktionen geben einen (ASCII-)Zeichenstring aus und keine Zahlen. sprintf ist für deine Zwecke also wahrscheinlich ungeeignet. Gruß Johnny
Hi, bin immer noch etwas verwirrt sprintf(tmp,"%d",wahl); // Int in Char arry tmp[3] schreiben printf("tmp: %s\n",tmp); // tmp ausgeben --> ergebnis wie im - Beispiel 24 uhr.date =tmp; // printf("date: %02bx\n",uhr.date); // Ergebnis irgend eine Zahl .... printf("date: %s\n",uhr.date); // Ergebnis ihrgen ein Komisches Zeichen wie könnte ich den den wert "24" wie er in der Int Variablen steht in die Char buxieren ?? Also das in dem Char dann auch wirklich "24" steht und nicht der Hex-Wert (18)??? MfG Nils
Hast du das mal ausprobiert: (ich kenne micht mit sprintf nicht aus, würde aber sowas ausprobieren). sprintf(tmp,"%d",uhr.date); printf("tmp: %s\n",tmp); 18 (hex) = 24 (dezimal) nur so am Rande... Zahlen < 32 (dezimal) sind im ASCII Steuerzeichen, die für Menschen eher schlecht lesbar sind... http://de.wikipedia.org/wiki/ASCII
Hi, @Rahul: Da hast du mich falsch verstanden. der int Wert steht in der Variablen "wahl" und eben diesen möchte in in die Char Variable uhr.date buxieren und zwar nicht deren zugehörigen Hexwert 18 sondern wirklich die 24. wenn ich mit der 18 was anfangen könnte könnte ich ja auch soetwas machen: uhr.date = (char)wahl; aber da bekomme ich dann eben nicht 24 sondern besagte 18 in uhr.date! ich will auch gar nicht unbedingt an der sprintf Variante festhalten das war einfach ein lösungsansatz von mir weil das mit dem cast nicht so geklappt hat wie ich mir das vorgestellt hab. Also wenn jemand vielleicht noch eine andere Lösung einfällt .... ich wäre um jede Idee dankbar MfG Nils
nee, muß uhr.date = (char) ((wahl / 10) | (wahl % 10)); heissen. Wie sieht date_s eigentlich aus?
Müsste es nicht eher heißen uhr.date = (char) (((wahl / 10) << 4) | (wahl % 10)); ? 24d / 10d = 2d 24d % 10d = 4d 2h << 4h = 20h 20h | 4h = 24h ...oder hab ich da was übersehen?
Ich verstehe dein Problem nicht wirklich... Der Controller kennt ja keinen unterschied zwischen hex und dezimal. Dem ist ja nur das binäre Datenformat bekannt. Die anderen sind ja nur andere schreibweisen dafür (in einem anderen Zahlensystem...) warum nimmst du nicht gleich ne char-Variable??? char zaehl = 0; wenn Drehgeber gedreht, dann zaehl++; falls zaehl >= 24, zaehl = 0; wenn fertig mit Eingabe, bin2dez(zaehl); bin2dez() macht dann das, was Rahul schon sagte, nämlich mod 10 und div 10, damit du die Stellen getrennt bekommst. (Für die Ausgabe musst du dann pro Zahl noch hex 30 dazuaddieren, damit du ASCII-Zeichen bekommst. Dezimal 48 geht auch ...)
> Karl-Heinz hat auch noch das "&" dabei.
Yep. Hab ich übersehen. Mir kam nur spanisch vor, daß die
Einzelteile ohne Offset zusammengewurschtet werden.
> Der Controller kennt ja keinen unterschied zwischen hex und dezimal.
Der Controller will anscheinend BCD haben.
D.h. unteren 4 Bits zählen von 0 bis 9, dann erfolgt ein
Übertrag in die oberen 4 Bits, die ebenfalls von 0 bis 0
zählen:
00 0000 0000
01 0000 0001
02 0000 0010
03 0000 0011
...
07 0000 0111
08 0000 1000
09 0000 1001
10 0001 0000
11 0001 0001
....
18 0001 1000
19 0001 1001
20 0010 0000
...
98 1001 1000
99 1001 1001
@Frank Schon richtig. Aber aus dem Gesta... des OP ergibt sich zwangsläufig dieser Schluss.
@Erdi: 15:31 habe ich zuerst gepostet, dann kam Karl-Heinz etwas später und dann waren da ein paar ziemlich zeitgleich. Bei dem "Controller" handelt es sich wohl um den DS1302 (RTC von Dallas). Der scheint sein Datum in BCD-Form zu erwarten. (hab noch nicht ins Datenblatt geguckt...)
Hi, hab eben mal die Lösung von Jonny.m getestet ... funktioniert;) vielen Dank Das ganze Projekt sieht überings folgendermaßen aus : DS1602 (nicht 1302) -------- 8052 ----------- 126x64 GLCD MfG Nils
Übrigens: Viele Leute nehmen an, hex, dez, und binär sind "zahlentypen". Das ist totaler Quatsch. Hexadezimal, Dezimal, Oktal, und Binär sind Arten, um Zahlen darzustellen. Der Controller unterscheidet nicht zwischen "0x18" oder "24" das ist für den die gleiche Zahl, belegt den gleichen Speicher, und die gleichen Bits werden gesetzt sein.
Moinsen, @ Frank Erdrich Das verstehe ich nicht ganz ... würde ja gerne direkt ne char variable nehmen (ich brauche ja auch eigentlich keine ganze int), aber wenn ich das tue steht zählt er ja in hex hoch ... also hätte ich nach 24 Rastschritten nicht die 24 in der zaehl-variablen stehen sondern die 18 (->0x18 == 24d). müsste ich dann nicht soetwas machen: char bind2dez(char zahl){ int tmp; tmp = (int)zahl; return (((((zahl/10)<<4)+0x30)|((zahl%10)+0x30)))); } produziert das nicht mehr code als die Lösung von Jonny.m ? MfG Nils
Erdi hat dir eine Lösung aufgezeigt, mit der man Zahlen für Menschen
sichtbar macht.
>produziert das nicht mehr code als die Lösung von Jonny.m ?
Versuch doch einfach mal, die beiden (Johnny's, Erdis und deine)
Varianten zu verstehen.
Achtung Nils, Du vermischt weiterhin Zahlencodierungen in ASCII, BCD und binär. Dein letzter Quelltext char bind2dez(char zahl){ int tmp; tmp = (int)zahl; return (((((zahl/10)<<4)+0x30)|((zahl%10)+0x30)))); } stellt den nicht funktionierenden Versuch dar, einen binär kodierten Zählerwert in ASCII umzukodieren. In ASCII belegt aber jede Dezimalstelle ein Byte. Ein char reicht also nicht zur Darstellung der Rückgabe. Auch die Ausgabe von sprintf ist immer ASCII. Du willst aber nicht in ASCII kodieren, sondern in BCD (Binary Coded Decimal), in dem immer 4 Bits eines Bytes als Dezimalwert verstanden werden. Korrekt würde also Dein Quelltext aussehen: char bind2dez(char zahl) { return ((zahl/10)<<4)) | zahl%10; } Das wird dann funktionieren, da ich ja praktisch nur den Code der anderen Poster verwendet habe.
@Nils: Du erzählst quatsch! Wie kann ein Prozessor "in hex hochzählen" ? Hexadezimal ist ein Zahlensystem, in welchem eine Zahl dargestellt werden kann. Dezimal 24 sind zwar Hex 18, aber auch nur, weil das Hexadezimalsystem von 0-F geht. Du kannst mit printf o.ä. ein Wert in Hex darstellen lassen (%x). Du kannst aber den Wert auch dezimal anzeigen lassen (%i, %u, %f...). Der Fehler muss irgndwo anders liegen. Um den Wert eines Registers (8-Bit) in Hex auszudrücken, brauch man 2 Byte (00...FF). In Dezimal brauch man 3 Byte (000...255).
Hi, @ Christian Das würde nicht funktionieren, da wenn ich eine Char Variable benutze steht ja eben nicht 24 als wert in der Variablen sondern 18..... Mit deinem Code ... würde ich ja nur: 18 / 10 = 1 <<4 = 10 | 18 % 10 = 18 @Simon ich wollte damit nicht sagen das der Prozessor in hex zählt, sondern lediglich das der Wert, wenn ich ein char benutze als hex Wert in der Char-Variablen steht ... Wenn ich ein int benutze werden die werte ja so dargestellt (8...9...10...11) Wenn ich ein char benutze (08...09...0A....0B...) Da habe ich es für einfacher gehalten zu sagen das er in Hex zählt.... MfG Nils
> wenn ich ein char benutze als hex Wert in der > Char-Variablen steht Unklar... 'n Char ist doch 'n Byte. Im Byte stehen 8 Bit. Der Controller/Computer sieht und verarbeitet nur diese Bits. Für den bitunkundigen Menschen könne die dargestellt werden als: - String mit 8 Binärziffern - String mit 2 Hexziffern - String mit 1 bis 3 Dezimalziffern - String mit 3 Oktalziffern - ASCII-Zeichen (1 Zeichen) - Bitmap mit 8 einfarbigen Grafikpixeln - Farbe eines 256-Farben-Grafikpixels - ... Trotzdem bleibt ein Byte doch ein Byte, das 8 Bits enthält und den (dezimalen) Zahlenwert von 0 bis 255 abbilden kann. In welchem Ausgabeformat dieser Zahlenwert nun betrachtet wird ist dabei nicht relevant. ...
Hello World, Ich werde wahnsinnig! @Nils Zitat: > Mit deinem Code ... würde ich ja nur: > 18 / 10 = 1 > <<4 = 10 > | 18 % 10 = 18 Was redest Du da für einen Käse? 1 << 4 ist nicht zehn sondern SECHZEHN! Oder bist Du jetzt so verwirrt, dass Du hex und dezimal kunterbunt mischst?
@Simon, ich hab's gesehen, deshalb mein leicht überspitzter Beitrag mit anderen Worten und aus einem anderen Sichtwinkel. Es ist aber auch nicht immer leicht, sich von einer einmal falsch eingeprägten Vorstellung zu trennen. Das erinnert mich an einen PC-Fall vor über 15 Jahren. Die Dame hat auf die Bibel geschworen, dass sie die Autoexec.bat, die ich ihr im Norton-Commander gezeigt hatte, NICHT verändert hatte. Sie tat es nämlich im Notapad von WINDOOF, und das hat keinen blauen Fensterhintergrund wie der NC, also ist es nicht die selbe Datei... ;-)
Christian beschreibt die ganze Zeit eine Umwandlungsroutine von Binär/hex nach BCD, merkt aber nicht, dass das die Lösung ist. Und Hannes erzählt Daumeier-Geschichten... Lustiger Thread. Soll ich auch noch ne PC-Geschichte erzählen? Eine etwas ältere Frau hat sich von einem Bekannten einen PC als Ersatz für ihre nochbetagtere Schreibmaschine zusammenstellen lassen. Alles wunderbar. Für mehr als Briefe und andere Dokumente zu schreiben, wurde der Rechner nicht benutzt. Irgendwann rief sie bei dem Bekannten an, und meinte der PC sei voll. Der Bekannte konnte sich das gar nicht vorstellen, da der Rechner eine 60GB-Platte hatte und noch nicht voll sein konnte (so groß ist das Word-Format auch nicht...). Als er sich den Rechner ansah, war der wirklich voll: Die nette Dame hatte alle ihre Dokumente auf dem Desktop gespeichert. Und der war voll...Nachdem er ihr dann gezeigt hat, wie das mit Verzeichnissen auf der Festplatte geht, war sie sehr erleichtert.
Zur (hoffentlich) endgültigen Klarstellung: Lieber Nils, 0x18 entspricht 24d, 10d entspricht 0x0a. Du dividierst 0x18 durch 0x0a. Sofern Du mit Windoof arbeitest, gibt es da im Zubehör einen Rechner, der ganz nett in allen üblichen Zahlensystemen rechnen kann (im wissenschaftlichen Modus) und auch zwischen diesen hin und her. Gib doch bitte mal im Dezimal-Modus ne 24 ein und klicke dann auf hexadezimal. Dann steht da 18. Dann gibst Du wieder im Dezimal-Modus eine 10 ein und gehst wieder in den hex-Modus. Dann steht da ein A. Wenn Du jetzt im hex-Modus 18 / A eingibst und auf = klickst, steht da, O Wunder, eine 2. Probier das mal aus, sonst reden sich hier noch alle den Mund fusselig. Noch mal: es sind nur unterschiedliche Darstellungsformen für EIN UND DIESELBE ZAHL. Im Controller-Speicher stehen NUR Nullen und Einsen! Wenn Du dem Compiler eine Zahl OHNE 0x, 0b oder führende Null übergibst, wird diese Zahl als dezimalzahl interpretiert und intern in Binär (bzw. Hex) umgerechnet. Eine Zahl, die mit 0x beginnt, wird als hexadezimal, eine mit einer führenden 0 als oktal interpretiert. Ein 0b weist auf eine Binärzahl hin. Der Compiler 'rechnet' ausschließlich in hex bzw. Binär und der Controller genauso. Dezimalzahlen werden grundsätzlich umgewandelt, da ein Computer Zahlensystemen, deren Basis keine Potenz von 2 ist, fürchterlich schlecht rechnen kann (Alle anderen oben genannten Zahlensysteme haben als Basis Potenzen von 2 und sind deshalb direkt binär darstellbar). Ich hoffe das ist jetzt wirklich klar. So lange Du das nicht verstehst, kannst Du nicht vernünftig mit µCs und Computern arbeiten. Also versuch es bitte! Gruß Johnny
Um es ganz konfus zu machen, der 8051 kann auch im gepackten Dezimalformat rechnen (je 4Bit = 0..9). Dazu hat er den Befehl "DA A" (decimal addition adjust). Irgendwo hab ich auch mal ne komplette Arithmetikbibliothek in packed BCD gesehen. Praktische Bedeutung hat dieses Format heutzutage aber nicht mehr. Ich habs auch noch nie verwendet. Peter
Der PIC hat IMHO auch ein Flag, das den Übertrag von 9->10 anzeigt. Kann aber auch sein, dass das den Übertrag von 0x0F -> 0x10 anzeigt...
Hi, ich habe das Problem, dank der vielen Antworten von euch, nun für mich lösen können. Ich benutze nen char und rechne den hex-Wert kurz vor der Anzeige auf dem LCD in dez um .... char bind2dez(char zahl){ switch (zahl%10){ case'a': return(((zahl/10)*16)+10); break; case'b': return(((zahl/10)*16)+11); break; case'c': return(((zahl/10)*16)+12); break; case'd': return(((zahl/10)*16)+13); break; case'e': return(((zahl/10)*16)+14); break; case'f': return(((zahl/10)*16)+15); break; default: return(((zahl/10)*16)+(zahl%10)); break; } } So, dass der Hex-Wert (z.B. 18) in den zugehörigen Dez-Wert (z.B. 24) umgewandelt wird. Mir ist schon klar das nach der Umwandlung dann eigentlich (0x24 = 0010 0100 = 36) in der Variablen steht, aber ich brauche es halt in diesem Format. Ich habe also kein Problem mit den einzelnen Zahlensystemen ... wie von einigen von euch angenommen ;) vielen Dank an euch MfG Nils
Um Else Kling (Annemarie Wendel) zu zitieren: "Wenn's scheee' macht!" (In diesem Fall "Wenn's funktioniert") Da würde mich aber mal interessieren, wie die Daten aussehen, die das LCD erwartet. Übrigens macht ((zahl/10) * 16) exact das gleiche wie ((zahl/10) << 4). Und mit (((zahl/10) <<4) | (zahl % 10)) kannst du dir die Switch-Case-Abfrage gleich sparen. Weiterhin bezweifle ich, dass "case 'a':" das gleiche wie "case 0x0A" ergibt...
>Ich habe also kein Problem mit den >einzelnen Zahlensystemen ... wie von einigen von euch angenommen Genau das beweist Du aber mit jedem neuen Post von Dir ;P SCNR
Lies dir erstmal n Buch zum Thema C durch.. Und vllt. mal bei Wikipedia gucken.. Und dann gleich nochmal Ascii lernen
Ich benutze nen char und rechne den hex-Wert kurz vor der Anzeige auf dem LCD in dez um .... Hallo? Das geht nicht. Um aus nem Wert ein Hex-Wert zu machen, brauchst du ein Array aus Charactern, einen sogenannten STRING. Das liegt daran, dass Buchstaben in dem Zahlenwert vorkommen ! Wie übergibst du denn deiner Funktion zB 3F hexadezimal?! Ohne String geht es definitiv nicht.
Außerdem würde mich noch interessieren, welches (anscheinend ausschließlich numerisches) Display die Daten in Dezimaler Form annimmt PS: hilf mir doch jemand, ihn zu überzeugen.
@Simon: Da er die Routinen für das Display nicht selber geschrieben hat, vermute ich, dass derjenige, der diese Routinen geschrieben hat, die Routinen so ausgelegt hat, dass sie BCD-Zahlen geliefert haben will. Das ist zwar aus der Fragestellung nicht ganz klar geworden, aber meine Kristallkugel ist gerade frisch aus der Wartung zurück...
Wovon überzeugen? Wir könnten auch für ihn das ganze Programm schreiben^^.. Aber ich denke, dass printf und so nicht zum Spaß da sind.. Vllt. wäre auch etwas Verständnis vom Threadstarter bzw. ne genauere Erläuterung, was das für ein Display ist etc. angebracht. Aber meine Glaskugel sagt gerade auch nichts mehr.
> PS: hilf mir doch jemand, ihn zu überzeugen.
Schon versucht (weiter oben), hat aber keinen Zweck, ist daher schade
um die Zeit. Vielleicht sollte man diesen Thread in die Rubrik
"Unterhaltung" verschieben.
Ansonsten bleibt nur noch ein Grundkurs, der mit Bits&Bytes beginnt.
Und wechsein...
...
@Nils: Deine Funktion bind2dez() ist völliger Schwachsinn. Du hast offensichtlich nichts, aber auch gar nichts verstanden: Eine Variable 'unsigned char' kann eine Zahl von 0 bis 255 speichern, eine Variable 'signed char' kann eine Zahl von -128 bis +127 speichern. In Deiner Funktion bind2dez() machst Du in der switch-Anweisung eine Modulo-Operation: zahl%10 Da kommt immer eine Zahl zwischen 0 bis 9 heraus. Wenn Du in C 'a' schreibst, bedeutet das, den ASCII-Wert vom Buchstaben 'a', also die Zahl 97. D.h. aus einem case('a') wird ein case(97). So, und jetzt kannst Du Dir überlegen, wann Deine ganzen case('x')-Fälle angesprungen werden. Nämlich nie, weil Du switch(zahl%10) hast...
Also ein Bit ist die kleinste logische Informationseinheit sie kann den Zustand 0 oder 1 annehmen. 4 zusammenhängende Bit werden als Nibble bezeichnet 8 zusammenhängende Bit als Byte Es gibt verschiedene Möglichkeiten ein Byte darzustellen jenachdem in welchen Zahlensystem und zu welcher Basis sie üblicherweise rechnen. Es böte sich da an binär Basis 2 oktanär Basis 8 dezimal Basis 10 SEHR verbreitet in der westlichen Welt hexadezimal Basis 16 Wichtig: Die Zahl ist immer das gleiche BITMUSTER eine andere Sache sind CODIERUNGEN z.B. BCD-Code GRAY-CODE etc.
@Hannes
> kann man die auch mit Römischen Zahlen darstellen?
Googelst Du mal nach 'Intercal'.
Ist eine der geilsten Sprachen die es gibt.
Und ja: numerische Ausgaben (und Eingaben?) werden mit
römischen Zahlen gemacht :-)
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.