Forum: Mikrocontroller und Digitale Elektronik Hex in Dez Ausgabe


von Merve B. (student1990)


Lesenswert?

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ß

von Max H. (hartl192)


Lesenswert?

Merve B. schrieb:
> Könntet ihr mir einen Anhaltspunkt geben?
Es gibt die Funktion "itoa"

: Bearbeitet durch User
von Sven B. (scummos)


Lesenswert?

Es gibt auch sprintf, das schreibt in einen Buffer statt nach stdout.

von Purzel H. (hacky)


Lesenswert?

Ganz sicher nicht printf(). Das ist die absolut schlechteste Wahl. Eine 
eierlegende Wollmilchsau. Die verbraucht viel zuviel resourcen.

von Max H. (hartl192)


Lesenswert?

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
von Stefan F. (Gast)


Lesenswert?

> (printf) Die verbraucht viel zuviel resourcen.

Wie kommst Du darauf? Wieviel Ressourcen zur Verfügung stehen, weisst Du 
doch gar nicht!

von Max H. (hartl192)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Merve B. (student1990)


Lesenswert?

Tut mir leid, dass ich spät antworte. Ich bedanke mich bei euch für die 
Hilfe. Ich werde es gleich ausprobieren :)

DANKE

von Merve B. (student1990)


Lesenswert?

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?

von Sven B. (scummos)


Lesenswert?

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.

von NurEinGast (Gast)


Lesenswert?

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

von Merve B. (student1990)


Lesenswert?

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.

von Merve B. (student1990)


Lesenswert?

@Sven B.@NurEinGast
Danke! klingt logisch :)

von Sven B. (scummos)


Lesenswert?

Ä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
von Merve B. (student1990)


Lesenswert?

@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ß

von Karl H. (kbuchegg)


Lesenswert?

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
von Merve B. (student1990)


Lesenswert?

@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ß

von Karl H. (kbuchegg)


Lesenswert?

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
von Merve B. (student1990)


Lesenswert?

@Karl Heinz werde ich mir hinter die Ohren schreiben. Danke :)

von Sven B. (scummos)


Lesenswert?

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
Noch kein Account? Hier anmelden.