Forum: Mikrocontroller und Digitale Elektronik problem mit hex und int


von Sven (Gast)


Lesenswert?

Hallo,

ich versuche gerade eine mit meinem msp430f149 eine uhr zu basteln.

habe dazu mal das rtc-beispiel von ti aufgegriffen. funktioniert auch
soweit, aber....

ich möchte die sekunden, minuten usw. auf meinem display ausgeben.

die sekunden werden als hex gezählt von 0x00 bis 0x59. nun würde ich
halt gerne die sekundenvon 0-59 auf dem display ausgeben. wenn ich nun
die sekunden varible in einen string umwandle und ausgebe, erhalte ich
für die 0x59 eine 89 auf meinem display.

ich habe keine idee, wie ich die hexwerte 0x00 bis 0x59 als 0-59 auf
dem display ausgeben kann. im prinzip müsste ich die hex zahlen in int
umwandeln und dann die int int einen string, um es auf dem display
auszugeben. für int in string habe ich eine funktion.

allerdings wie bekomme ich auch 0x00 bis 0x59 in 0-59?

Gruß
Markus

von inoffizieller WM-Rahul (Gast)


Lesenswert?

ich gehe mal von C aus:

unsigned char Sekunde = 0x59;

unsigned char SekundeZehner;
unsigned char SekundeEiner;

SekundeEiner = (Sekunde & 0x0F) + '0';
SekundeZehner = (Sekunde >> 4)  + '0';

von thkais (Gast)


Lesenswert?

Werden die Werte in BCD gezählt? Dann ist das eine recht einfache Sache,
denn die Zehner-Stelle steht im high-Nibble und die Einer-Stelle im
Low-nibble.
Dann wäre die Zehnerstelle (wert >> 4) + 0x30
und die Einerstelle (wert & 0x0F) + 0x30
Die 0x30 ist das Ascii-Offset.

von johnny.m (Gast)


Lesenswert?

> werden als hex gezählt von 0x00 bis 0x59

Also als gepackter BCD-Code? Wenn Du da sicher bist, dann brauchst Du
nur die beiden Halbbytes durch Maskierung und Schieben zu isolieren und
getrennt in Zeichen umzuwandeln (ich vermute jetzt mal, es handelt sich
um ASCII-Zeichen?!?). Wenn Du jetzt noch sagst, in welcher
Programmiersprache das ganze sein soll, wäre das hilfreich...

von Markus (Gast)


Lesenswert?

hallo,

das ganze ist in c.

ich nutze die rtc von ti. timerA als sekundentakt.

dürfte bcd sein.

gruß
markus

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Erster...

von Marco Reinert (Gast)


Lesenswert?

Hallo,

ich habe ein ähnliches Problem. Allerdings sind die Zahlen, die ich
verarbeiten muss nicht nur zweistellig sondern vierstellig. also z.b.
0x1234. Für die Umwandlung in Int habe ich die Lösung für die Einer und
Zehner-Stelle aus diesem Thread schon aufgegriffen. Gibts auch die
Möglicheit, die Hunderter und Tausender-Stelle umzuwandeln? Ich komme
mit den Zahlensystemen noch nicht so ganz zurecht. Wäre auch klasse,
wenn mir jemand erklären könnte, wie die Umrechnungen Zustande kommen.

Vielen Dank schonmal.

Marco

von johnny.m (Gast)


Lesenswert?

Wenn das auch gepackter BCD-Code ist, dann geht das im Prinzip genau so
wie oben, nur in vier Schritten, z.B.:

unsigned char i, stellen[4];
unsigned int schieb, wert = 1234;

schieb = wert; //Übernahme des umzurechnenden Wertes

for(i = 0; i < 4; i++)
{
    //Übernehme letzte 4 Bit in stelle:
    stellen[i] = (schieb & 0x0F) + '0';
    schieb >>= 4; //Schiebe schieb um eine Stelle nach rechts
}

stellen[0] ist jetzt '4', stellen[1] ist '3' usw.

von Marco Reinert (Gast)


Lesenswert?

Hallo,

also wenn ich das richtig verstehe, drehe ich die vierstellige zahl
erst einmal um, so dass die Tausender hinten stehen und die Einer vorne
und dann kann ich den Code von weiter oben zur ermittlung der Einer und
Zehner wieder anwenden.
 Oder liege ich da daneben?

Marco

von johnny.m (Gast)


Lesenswert?

Da wird nix "umgedreht". Wenn es sich beim Ausgangswert tatsächlich um
gepackten BCD-Code handelt (was ich mal angenommen habe), dann sieht die
Zahl 0x1234 in Binärdarstellung (also so, wie sie im Speicher abgelegt
ist) so aus:
0001 0010 0011 0100
Das ganze steht in einer unsigned int-Variable mit 16 Bit. Wenn man
versucht, einen int in einem char zu speichern, dann werden die 8 MSB
(also die höherwertigen Bits, in der Darstellung links) weggeschmissen
und die hinteren 8 Bit in der 8-Bit-char-Variable gespeichert.

Wenn man also das auf die Zahl oben anwendet, hat man nach dem ersten
Schritt in stellen[0] den Wert "0011 0100" stehen. Da man aber nur
die Einer-Stelle haben will, maskiert man das ganze mit 0x0F (also
binär 0000 1111), so dass die linken vier Bit wegfallen (Danach steht
in stellen[0] im Beispiel "0000 0100", also "4" dezimal). Dann
addiert man das ASCII-Zeichen für '0' (0x30) zu der Zahl hinzu und in
stellen[0] steht das ASCII-Zeichen für die Ziffer '4' (Das geht
deshalb, weil die Ziffernzeichen im ASCII-Code hintereinander stehen
und die '0' dem Code 0x30 entspricht, also die 4 z.B. der 0x30 + 0x04
= 0x34)

Anschließend schiebt man den Inhalt der Ursprungsvariablen um 4
Binärstellen nach rechts (schieb >>= 4;), so dass man jetzt die
10er-Stelle ganz hinten hat (im Bsp.: "0000 0001 0010 0011"). Dann
wiederholt man die Prozedur von oben. Mit den 100ern und 1000ern dann
das ganze noch mal.

In stellen[0] stehen dann die 1er (1 == 10^0), in stellen[1] die 10er
(10 == 10^1) usw., also in stellen[i] die "10^i-er". Noch Fragen?

von Pete Nerlinger (Gast)


Lesenswert?

dafür gibts auch fertigen code

von johnny.m (Gast)


Lesenswert?

@Pete:
Tolle Information! Es gibt so ziemlich für alles fertigen Code! Aber
für einen Einsteiger ist es imho sinnvoller, zu verstehen, wie etwas
funktioniert, und zwar von den Grundlagen an! Und das hier genannte
Problem ist ein Grundlagenproblem, das jeder Programmierer auch ohne
fertigen Code lösen können sollte. Wenn mans so sieht ist das, was oben
steht, auch "fertiger Code", nur eben verständlich kommentiert...

von Pete Nerlinger (Gast)


Lesenswert?

jo erfinde das RAD jedesmal neu....träumer.armes deutschland.

von Thomas K. (thkais)


Lesenswert?

Pete: Jo, armes Deutschland. Mit cut & paste kommt man weiter.
Vor allem ist Deine Info echt sinnvoll, denn Du hast auch verraten, WO
es den fertigen Code gibt. Ich vermute mal, nicht bei Dir - denn Du
schreibst ja nur ab und weißt nicht, was Du da überhaupt abschreibst.
Super.

von Info-Matiker (Gast)


Lesenswert?

> Pete: Jo, armes Deutschland. Mit cut & paste kommt man weiter.
> Vor allem ist Deine Info echt sinnvoll, denn Du hast auch
> verraten, WO es den fertigen Code gibt.

Das ist so ziemlich eines der größten und für mich erschreckensten
Handicaps heutzutage - die teilweise vollkommene Unfähigkeit, sich
selbst die gewünschten Informationen zu beschaffen, und das, obwohl es
im Internetzeitalter so viel einfacher ist, als noch vor 20 Jahren. Das
ist aber nicht auf Deutsche beschränkt. Überall in Foren findet man
zuhauf Fragen, deren Formulierung alleine schon länger dauert, als die
Google-Suche nach der Antwort gedauert hätte.
Es wird dann von den "Wissenden" erwartet, daß sie sämtliche
Grundlagen hundertmal erklären, obwohl es schon Tausende von
Erklärungen zum Nachschlagen gibt oder Informationen aus Datenblätter
abschreiben, weil der Fragesteller zu faul war, das Datenblatt selbst
zu lesen.

von Marco Reinert (Gast)


Lesenswert?

Nochmal zum Verständnis. dann könnte man das doch auch so machen oder?


char einer;
char zehner;
char hunderter;
char tausender;

einer= (wert & 0x0F) + 0x30;
zehner= ((wert >>4)& 0x0F) + 0x30;//so stehen die zehner hinten
                                      // (0000 0001) 0010 0100
                                                     0000 1111 (0x0F)

hunerter= ((wert >>8)& 0x0F) + 0x30;//so stehen die hunderter hinten
                                      // (0000 0000) 0001 0010

tausender=((wert >>12)& 0x0F) + 0x30; //so stehen die tausender hinten
                                      // (0000 0000) 0000 0001

im prinzip müsste das dann doch egal sein, ob ich wei oder drei mal um
vier verschiebe oder ob ich einmal um 8 oder 12 verschiebe oder stehe
ich da auf der leitung?

von Thomas K. (thkais)


Lesenswert?

Der Code müßte so laufen. Im Prinzip ist es egal, wie und wann Du
shiftest. Man müsste mal nachschauen, ob der Compiler einen solchen
Code nicht sogar schon optimiert - ansonsten müßte man nachhelfen. Wenn
es auf 20-30 Taktzyklen mehr oder weniger nicht ankommt, würde ich mir
in dieser Hinsicht keine Sorgen machen.

von Profi (Gast)


Lesenswert?

Anstatt wert<<4 oder wert>>4 kann man auch den ASM-Befehl SWAP
verwenden:

#define uc unsigned char
#define ui unsigned int
struct stru{uc lo,hi;}st;
union unio{ui wo;st;}un; /* Turbo-C versteht das, gcc auch??*/

inline uc swap(uc wert){
  /*hierfür sollte der µC den Befehl SWAP verwenden*/
  return wert>>4 | wert<<4;
  }

void main(void){
  un.wo=0x3456; /*union word*/
  printf("\r\n%4x %4x %4x %4x",un.hi,un.lo,un.wo,un);
  printf("\r\n%c %c %c %c",'0'|swap(un.hi)&15,'0'|un.hi&15,
                           '0'|swap(un.lo)&15,'0'|un.lo&15);
  }

Weiß jemand, wie das geht, den SWAP hierfür zu gewinnen?

von Simon K. (simon) Benutzerseite


Lesenswert?

>>Anstatt wert<<4 oder wert>>4 kann man auch den ASM-Befehl SWAP
verwenden:

Quatsch, der GCC jedenfalls macht das automatisch.

von Chief Brady (Gast)


Lesenswert?

@Pete
> jo erfinde das RAD jedesmal neu....träumer.armes deutschland.

Genau! Und Taschenrechner gibt's auch. Wozu eigentlich Mathe in der
Schule lernen?

von Karl H. (kbuchegg)


Lesenswert?

Exakt.
Wer das Prinzip erst mal verstanden hat (und das ist nicht
schwer), schreibt den 4-Zeiler schneller als du nachdenken
kannst wie und wo du den 'fertigen Code' zuletzt benutzt
hast und wieder herkriegst.
Ich würde sogar soweit gehen dass jemand der diesen 4-Zeiler
nicht im Halbschlaf hinkriegt, sich nicht Programmierer schimpfen
sollte. Das ist jetzt ausdrücklich nicht auf den Sven
gemünzt, der lernt noch. Das sind absolute Grundlagen.

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.