Forum: Mikrocontroller und Digitale Elektronik C - Frage ;-) (BIN2BCD)


von Dom (Gast)


Lesenswert?

Hi,

bin vorgestern mal angefangen AVR's mit C (Codevision) zu
programmieren. Die Syntax erinnert mich sehr an PHP.
Ich möchte einen 16 bit Integer zu 5 BCD Digits wandeln:

Müsste doch eigentlich so funktionieren, oder?


  bcd10000=temp / 10000 ;
  temp2=temp % 10000 ;
  bcd1000=temp / 1000;
  temp2=temp % 1000 ;
  bcd100=temp / 100;
  temp2=temp % 100 ;
  bcd10=temp / 10;
  temp2=temp % 10 ;
  bcd1=temp ;

temp ist int und enthält die zahl die umgewandelt werden soll,
die anderen unsigned char

Bin für jede Hilfe dankbar.

Dominik

von crazy horse (Gast)


Lesenswert?

unsigned char  bcd[5];
for (loop=0;loop<5;loop++)
    {bcd[loop]=temp%10;
     temp=temp/10;
     }

von Dom (Gast)


Lesenswert?

crazy horse:
Habe mal fünf 7-Segmentanzeigen angeschlossen und gemultiplext, aber
irgendwie funktionieren deine Routinen genauso wenig wie meine?!?!
Die Routinen zum Multiplexen sind 100%ig richtig, weil wenn ich dem
array bcd[n] irgendwelche Zahlen zuweise werden die korekt angezeigt.

Gruß, Dominik

von Rahul (Gast)


Lesenswert?

poste doch mal deinen Code, Dom!
Dann können sich auch andere mit dem Thema befassen.
Gruß Rahul

von crazy horse (Gast)


Lesenswert?

doch, das funktioniert schon. Es gibt andere Lösungsmöglichkeiten, die
schneller arbeiten, aber das ist erstmal die übersichtlichste. Wenn es
bei dir nicht funktioniert, liegt es nicht an dieser Routine, sondern
an einem anderen Programmteil oder an der Hardware. Im Blindflug wird
dir keiner weiter helfen können.

von Malte Marwedel (Gast)


Lesenswert?

Wenn du 7-Segment Anzeigen direkt ansteuerst (ohne zusätzlichen IC)
musst du dann noch mit einer Tabelle ermitteln welche LEDs bei welcher
Ziffer leuchten müssen. Denke aber mal dass du daran gedacht hast.

Folgende Routine hab ich mal für eine 4 Stellige 7-Segment-Anzeige
verwendet(die Werte für segcodierung müssten entsprechend an deine
Schaltung angepasst werden):

void setsegments(void) {//berechnet die ziffern
const u08 segcodierung[10] =
{0x6f,0x28,0x5d,0x79,0x3a,0x73,0x77,0x29,0x7f,0x7b};
u16 ziffer,temp01;//zu zeigender Wert
ziffer = 0;
if (dispmode == 0) {
  ziffer = hours*100+minutes;
}
if (dispmode == 1) {
  ziffer = day*100+month;
}
if (dispmode == 2) {
  ziffer = showwhour*100+showwminute;
}
//umrechnen
temp01 = segcodierung[(ziffer/1000)%10];
if ((temp01 == 0x6f)&&(dispmode == 0)){ //vorstehende Null entfernen
  temp01 = 0;
}
segment[0] = temp01;
segment[1] = segcodierung[(ziffer/100)%10];
segment[2] = segcodierung[(ziffer/10)%10];
segment[3] = segcodierung[ziffer % 10];
}

von Dom (Gast)


Lesenswert?

Erstmal: Danke für die bisherigen Antworten!

Also wie gesagt, die Routinen zum multiplexen sind 100%ig okay. Ich
verwende nen BCD zu 7-Segment-Decoder der an PORTB[0..3] angeschlossen
ist. Die einzelnen Anzeigen werden über NPN-Transistoren eingeschaltet,
deren Basen an PORTD[0,1,4,5,6] (Ich brauche PD2 und PD3 für externe
INT's) angeschlossen sind.
Wie gesagt, bin Anfänger in C und habe µC's bisher nur in ASM
programmiert (Leider habe ich noch keinen Delphi, bzw. Pascal -
Compiler für AVR gefunden). Ich weiß, dass man den Teil für die Wahl
der Anzeige noch verkürzen kann, aber darum geht es mir erstmal nicht.
Achja, ich verwende nen AT90S2313 und CodeVisonAVR, hier die
Hauptschleife:

while (1)
      {

   temp2=12345;


for (loop=0;loop<5;loop++)
    {bcd[loop]=temp2%10;
     temp2=temp2/10;
     }

    ++anzeige ;
    if (anzeige == 6) anzeige=1;

    switch (anzeige) {
    case 0: temp1=0;
    break;
    case 1: temp1=1;
    PORTB=bcd[4];
    break;
    case 2: temp1=2;
    PORTB=bcd[3];
    break;
    case 3: temp1=16;
    PORTB=bcd[2];
    break;
    case 4: temp1=32;
    PORTB=bcd[1] ;
    break;
    case 5: temp1=64;
    PORTB=bcd[0];
    break;
    };
    PORTD=temp1;
    delay_ms(3);
    };


}


Wenn temp2 = 12345 wird auf den Anzeigen 55385 angezeigt.

Gruß, Dom

von Dom (Gast)


Lesenswert?

Nachtrag:

temp2=12345 wird korekt angezeigt, aber z.B. bei 33333 wird nur bei der
Zehnerstelle eine Null angezeigt und die restlichen Anzeigen sind aus
(sind wohl Pseudotetraden).

von crazy horse (Gast)


Lesenswert?

"Wenn temp2 = 12345 wird auf den Anzeigen 55385 angezeigt.
Nachtrag:
temp2=12345 wird korekt angezeigt"
Was denn nun?
Programm sieht richtig aus, wenn auch etwas umständlich.
Pseudotetraden können nicht auftreten, und wenn nur eine Ziffer
angezeigt wird, wird das wohl heissen, dass der Prozessor steht. Noch
irgendwelche (fehlerhafte) Interrupts laufen? Variablen richtig
deklariert?

von Dom (Gast)


Lesenswert?

Wenn ich bei "Nachtrag" schreibe, dass die 12345 doch richtig
angezeigt werden, dann wird das wohl auch gemeint sein?!?!!?

Natürlich können Pseudotetraden auftreten, a bis f sind beim BCD Code
Pseudotetraden. Ist das angelegte Datenwort am BCD zu 7Segm. Decoder
eine Pseudotetrade, dann werden alle Segmente dunkeln geschaltet.
Wenn der Prozessor stehen würde, dann würde wenn überhaupt nur eine
Anzeige leuchten. Da aber mehrere bzw. alle Ziffern etwas anzeigen ist
das nicht der Fall.

Interrups sind deaktiviert, Variablen sind so deklariert:

int temp2;
unsigned char temp1;
unsigned char  bcd[6];
unsigned char loop;

von crazy horse (Gast)


Lesenswert?

bleib mal ruhig, du hast doch geschrieben, dass 55385 angezeigt wird.
Wenn die BCD-Variablen nur mit xxx=x%10 beschrieben werden, können
keine Pseudotetraden entstehen.

"wird nur bei der Zehnerstelle eine Null angezeigt und die restlichen
Anzeigen sind aus"
Deswegen dachte ich an die Möglichkeit, dass der Prozessor stehen
bleibt. Und dann kommt das nach:
"Wenn der Prozessor stehen würde, dann würde wenn überhaupt nur eine
Anzeige leuchten. Da aber mehrere bzw. alle Ziffern etwas anzeigen ist
das nicht der Fall."

Hast du noch Restalkohol? Stellst hier was in den Raum, behauptest im
nächsten posting das Gegenteil.
Ich mach jetzt einen auf Feiertag, und du solltest dir deine Sachen mal
ins AVR-Studio laden, dann wirst du sehen, wo der Hase im Pfeffer liegt,
ich habe keine Lust mehr zum Rätselraten.

von Dom (Gast)


Lesenswert?

"Hast du noch Restalkohol? Stellst hier was in den Raum, behauptest im
nächsten posting das Gegenteil."

Mir scheint eher, dass du den Restalkohl hast. Ich habe mich nur direkt
korrigiert, wenn du damit nicht klar kommst...

Einen schönen Feiertag noch!

Gruß, Dominik

von Dom (Gast)


Lesenswert?

Hab den Fehler gefunden ;-)

temp2 war vom typ int. int geht ja von -32768 bis 32767, dann ist es
klar, das Zahlen ab 32768 nicht gehen. mit unsigned int funktioniert es
tadellos.

Gruß, Dominik

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.