Hallo zusammen, ich habe da eine Frage. Ich bekomme von meinem Timer einen Wert, der in Hex abgespeichert wird. Vorweg: ich weiß, dass für den µController alle "Zahlen" und "Zeichen" in binär abgespeichert werden. Also hat dez, hex,... nichts mit einer Berechnung etc. zu tun. Ich möchte aber diese Zahl in dezimal auf meiner LCD anzeigen (benutze einen LPC2368). Ich habe ein bisschen im Internet geschaut und in C gibt es ja die Funktion "printf" mit der ich dann eine beliebige Zahl in einer beliebigen Form anzeigen lassen kann. Aber ich denke, der "printf" - Befehl würde mir nicht viel bringen, da ich ja am LCD etwas anzeigen lassen möchte. Sollte ich da "zwingend" eine Funktion schreiben, die mir das ganze dann umwandelt? Ich habe mir da auch schon Gedanken gemacht. Ich weiß ja, wie man die Umrechnung durchzieht. Aber ich weiß jetzt nicht genau, wie ich die Ziffer "auseinander" ziehen könnte. Zur Vereinfachung meiner komischen Schreibweise: Hex: 0x1DA2 -> 2*16^0 + A(oder 10)*16^1 + D*16^2 + 1*16^3 (ergibt 7586) Müsste ich dann irgendwie in einer Schleife eine Maskierung durchführen? Wo die Stellen einfach bei jedem Durchlauf verschoben wird? Und bei den Werten "A,B,C,D,E,F" müsste ich hierfür ein Switch Case machen? Könntet ihr mir einen Anhaltspunkt geben? Das wäre wirklich sehr nett :) Ich möchte auch keine fertigen Lösungen oder sowas, keine Sorge ;) Gruß
Merve B. schrieb: > Könntet ihr mir einen Anhaltspunkt geben? Es gibt die Funktion "itoa"
:
Bearbeitet durch User
Ganz sicher nicht printf(). Das ist die absolut schlechteste Wahl. Eine eierlegende Wollmilchsau. Die verbraucht viel zuviel resourcen.
Merve B. schrieb: > Hex: 0x1DA2 > -> 2*16^0 + A(oder 10)*16^1 + D*16^2 + 1*16^3 (ergibt 7586) So wird das aber nichts, da der µC die Zahl 7586 wieder als binär speichert. Wenn du es gerne gern ohne die oben genannten Funktionen machen willst:
1 | str[0]=(zahl/10000)+'0'; |
2 | zahl=zahl%1000; |
3 | str[1]=(zahl/10000)+'0'; |
4 | zahl=zahl%1000; |
5 | str[2]=(zahl/100)+'0'; |
6 | zahl=zahl%100; |
7 | str[3]=(zahl/10)+'0'; |
8 | str[4]=(zahl%10)+'0'; |
9 | str[5]=0x00; |
:
Bearbeitet durch User
> (printf) Die verbraucht viel zuviel resourcen.
Wie kommst Du darauf? Wieviel Ressourcen zur Verfügung stehen, weisst Du
doch gar nicht!
Stefan us schrieb: >> (printf) Die verbraucht viel zuviel resourcen. > > Wie kommst Du darauf? Wieviel Ressourcen zur Verfügung stehen, weisst Du > doch gar nicht! Dafür, dass man es mit 4 Divisionen und 5 Additionen lösen kann, brauch sprintf viele Ressourcen...
Max H. schrieb: > Stefan us schrieb: >>> (printf) Die verbraucht viel zuviel resourcen. >> >> Wie kommst Du darauf? Wieviel Ressourcen zur Verfügung stehen, weisst Du >> doch gar nicht! > Dafür, dass man es mit 4 Divisionen und 5 Additionen lösen kann, brauch > sprintf viele Ressourcen... Was bei einem ARM7 mit 512kB Flash so gut wie keine Rolle spielt. Man kriegt ja auch was dafür. Spätestens wenn man die Möglichkeiten im Formatstring ein einziges mal so richtig ausnutzen kann, hat es sich schon gelohnt.
Siebzehn Zu Fuenfzehn schrieb: > Ganz sicher nicht printf(). Das ist die absolut schlechteste Wahl. Ich habe sprintf mit float auch schon auf dem 8051 benutzt, funktioniert super. Das sind einmalig etwa 4kB Flash für die Lib.
Tut mir leid, dass ich spät antworte. Ich bedanke mich bei euch für die Hilfe. Ich werde es gleich ausprobieren :) DANKE
Also ich habe mal die sprintf() Funktion ausprobiert, bekomme aber den Fehler "Sensor.c(68): error: #167: argument of type "char *" is incompatible with parameter of type "char" lcd_putchar(wert1);" Hier ist mein Code
1 | #include <LPC23xx.h> /* LPC23xx definitions */ |
2 | #include "LPC2xxx_embedded.h" |
3 | #include "LCD.h" |
4 | //#include <math.h>
|
5 | //#include <stdlib.h>
|
6 | #include <stdio.h> |
7 | |
8 | double strecke = 3.0; |
9 | double v = 0.0; |
10 | int zeit = 16; |
11 | |
12 | char wert1[12]; |
13 | //char wert2[12];
|
14 | |
15 | int main(void) |
16 | {
|
17 | // short k;
|
18 | // short p;
|
19 | |
20 | lcd_init(); |
21 | lcd_clear(); |
22 | /*
|
23 | lcd_print("Zeit:");
|
24 | set_cursor(0,1); //Column = 0, Row = 1
|
25 | lcd_print("v:");
|
26 | */
|
27 | |
28 | v = strecke/ ((double)zeit); |
29 | v = ((int) (v*100.0 +0.5)) / 100.0; |
30 | |
31 | sprintf(wert1, "Zeit: %d",zeit); |
32 | lcd_putchar(wert1); |
33 | |
34 | // v*=100;
|
35 | |
36 | while (1) |
37 | {
|
38 | /* wert_hex1 = zeit;
|
39 | wert_hex2 = v;
|
40 |
|
41 | set_cursor (7, 0);
|
42 | hex_ascii_string(wert_hex1, wert_asc);
|
43 | for(k=0;k<3;k++)
|
44 | lcd_putchar(wert_asc[k]);
|
45 |
|
46 | set_cursor (7, 1);
|
47 | hex_ascii_string(wert_hex2, wert_asc2);
|
48 | for(p=0;p<3;p++)
|
49 | lcd_putchar(wert_asc2[p]);
|
50 | */
|
51 | |
52 | |
53 | }
|
54 | |
55 | |
56 | }
|
So wie ich es verstanden habe, ist die Variable "zeit" (integer) nicht kompatible. Aber was ich nicht verstehe, ist dass in dem Beispiel hier im Forum mit sprintf() es genauso gemacht worden ist. Kann mir vielleicht jemand einen Tipp geben?
lcd_putchar erwartet ein char als Argument, du gibst ihm ein char*. Ich kenne die genaue Definition von lcd_putchar nicht aber du musst das irgendwie anders machen -- das stellt nur ein einzelnes Zeichen dar, du hast aber mehrere.
char wert1[12]; // In "wert1" soll Dein String reingeschrieben werden sprintf(wert1, "Zeit: %d",zeit); // Schreibt den Sting rein. lcd_putchar(wert1); // putCHAR will aber nur EIN Zeichen sehen, keinen ganzen String
Ich habe statt "lcd_putchar" "lcd_print" geschrieben und es funktioniert. Ich bekomme zwar ein Warning, aber es geht jetzt. Kann mir trotzdem jemand erklären an was es lag? Würde mich interessieren. Und vielleicht auch, warum ich dieses Warning "Sensor.c(68): warning: #167-D: argument of type "char *" is incompatible with parameter of type "const unsigned char *" lcd_print(wert1);" bekomme. Das würde mich auch sehr interessieren. Man lernt ja nie aus ;) und ich muss wirklich noch vieeeel lernen.
Ändere char wert1[12]; in unsigned char wert1[12]; dann sollte die Warnung weggehen. Du übergibst einen Zeiger auf einen signed char, die Funktion will aber einen Zeiger auf einen unsigned char. Das macht der Compiler, gibt aber eine Warnung aus. Der vorherige Fehler lag daran dass char* und char zwei grundverschiedene Sachen sind. Am besten du suchst mal im Internet nach "c pointer" oder so, da wird das besser erklärt als ich das hier machen kann. Grüße, Sven
:
Bearbeitet durch User
@Sven B. Danke für die Erklärung. Ich habe es in unsigned char geändert, leider kommt immer noch die Warnung: "main.c(140): warning: #167-D: argument of type "char *" is incompatible with parameter of type "const unsigned char *" lcd_print(wert1);" So wie ich das verstanden habe, ist es nicht kompatibel. Heißt das, dass die Funktion lcd_print() einen "const unsigned char" übergibt? Danke, ich werde mich genauer über den Pointer informieren. Gruß
Merve B. schrieb: > @Sven B. Danke für die Erklärung. Ich habe es in unsigned char geändert, WAS hast du geändert? Den Datentyp beim Aufrufer oder den Datentyp in der Funktionsdeifnition? > leider kommt immer noch die Warnung: > > "main.c(140): warning: #167-D: argument of type "char *" is > incompatible with parameter of type "const unsigned char *" > lcd_print(wert1);" Gewöhn dir einfach an, dass die Datentypen zusammenstimmen müssen. Wenn du unsigned char hast (für alles, was sich lediglich mit dem Überbegriff 'Bytes' zusammen fassen lässt, dann zieh die unsigned char komplett durch. Wenn du lediglich char hast (für Einzelzeichen bzw. Texte), dann zieh das char quer durch die Bank durch. Ein Text "Hallo", ist mit dem Datentyp char beschrieben. Konkret hat sowas dann beim Aufruf den Datentyp char*, also Pointer auf char. > So wie ich das verstanden habe, ist es nicht kompatibel. Heißt das, dass > die Funktion lcd_print() einen "const unsigned char" übergibt? Die Funktion übergibt gar nichts. Die Funktion bekommt etwas. Die Codestelle, an der der Aufruf steht, die übergibt etwas. Es sind immer 2 Parteien beteiligt: Der Aufrufer und die Funktion selber. Ist doch nicht so schwer. Ist wie Stecker und Buchse. Und beide müssen eben zusammenpassen. Zusätzlich musst du noch unterscheiden zwischen einem einzelnen Zeichen - einem einzelnen char - und einem String. Ein String ist eine Abfolge von EInzelzeichen. Logischerweise muss dann auch da etwas mehr Verwaltungsarbeit rein, als in einem einzelnen Zeichen.
:
Bearbeitet durch User
@Karl Heinz Danke :) ich war nur etwas verwirrt, da ich alle meine Variablen mit dem selben Datentypen deklariert hatte und dann diese Warnung kam und dann auch noch "const" bei der Warnung stand. Gruß
Merve B. schrieb: > @Karl Heinz Danke :) ich war nur etwas verwirrt, da ich alle meine > Variablen mit dem selben Datentypen deklariert hatte und dann diese > Warnung kam und dann auch noch "const" bei der Warnung stand. Ein wenig nachdenken muss man bei der Programmierung schon. Manches geht zwar nach SChema 'F', vieles aber auch nicht. Und das const hat an dieser Stelle für den Aufrufer erst mal nichts zu bedeuten. Das const ist hier nur die Zusicherung der Funktion: Ich werde an den Daten, die du mir übergibst, nichts verändern - ich behandle sie als konstant. Das const ist nur insofern wichtig, als es damit ermöglicht, die Funktion so aufzurufen
1 | lcd_print( "Hallo World" ); |
Denn "Hallo World" ist ein konstanter String (ein String-Literal), welches als solches per Definition unveränderlich ist. Daher muss die Funktion die Zusicherung machen, nicht zu versuchen den String den sie bekommt zu verändern. Mit dem const macht sie genau diese Zusicherung. Du kannst dich also darauf verlassen, dass die Funktion nichts derartiges machen wird
1 | void lcd_print( const char* str ) |
2 | {
|
3 | strcpy( str, "juhu" ); |
4 | ....
|
5 | }
|
Das würde nie durch den Compiler gehen, denn sobald str ein const char* ist, klopft der COmpiler dem Programmierer von lcd_print auf die Finger, weil der dann nicht als das Ziel bei strcpy auftauchen kann. Genauer gesagt, bei allen Opertionen, in denen die Zeichen in str verändert werden würden. Und das wiederrum ist Vorausetzung dafür, dass man beim Aufruf ein String-Literal angeben kann, das je per Definition nicht verändert werden darf. (Für die Experten: Ja ich weiß, in C gibt es da eine Ausnahme, damit auch alter Code kompiliert, der noch vor Einführung von const in die Sprache geschrieben wurde. Ändert aber nichts am Prinzip und nicht immer sind die Dinge so einfach wie bei const char*, bei dem als einziges diese Ausnahme greift)
:
Bearbeitet durch User
Sehr gut erklärt -- ich kann nur nochmal kurz hinzufügen, dass das const dem Typ immer implizit hinzugefügt wird, wenn es irgendwo auftaucht. Es ist also nie ein Problem, ein nicht-const Foo als const Foo zu übergeben. Andersrum geht das allerdings aus genannten Gründen nicht. Man kann es allerdings weg-casten, also wirklich auf das const verlassen kann man sich nicht. Es ist mehr ein Hinweis.
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.