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:> 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:
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.
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
doublestrecke=3.0;
9
doublev=0.0;
10
intzeit=16;
11
12
charwert1[12];
13
//char wert2[12];
14
15
intmain(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
@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.
@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
voidlcd_print(constchar*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)
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.