Forum: Mikrocontroller und Digitale Elektronik Zahl in Ziffern zerlegen


von Felix G. (geerkins)


Lesenswert?

Hallo
ich bastle gerade an nem Programm für ne 7Segment anzeige
Um deine Zahl in ihre Ziffern zu zerlegen.
Dazu hab ich Dei ZAhl in nen char Aray geschrieben und lese jetzt die 
enstsprechende stelle wieder aus. Aber wie wandel ich die jetzt gelesene 
ZAhl wieder in en int wert um um sie dan anzuzeigen??
Danke
Felix

von Peter II (Gast)


Lesenswert?

Felix Geerkens schrieb:
> Dazu hab ich Dei ZAhl in nen char Aray geschrieben und lese jetzt die
> enstsprechende stelle wieder aus.

und warum?

 456 / 100       = 4
(456 % 100) / 10 = 5
(456 % 10 )      = 6

von Michael (Gast)


Lesenswert?

Felix Geerkens schrieb:
> Aber wie wandel ich die jetzt gelesene
> ZAhl wieder in en int wert um um sie dan anzuzeigen??

Für eine Siebensegmentanzeige brauchst du die Segmentcodes und die 
passen in ein Byte rein.

von Felix G. (geerkins)


Lesenswert?

Tag danke für die schnellen antworten.
@Peter geht des Wirklich kommt da dann nicht 4,56 raus??
@Michael danke für den Hinweis ich hatte oben blos int gschreiben um 
nicht weiter zu verwirren
Vielen Danke Felix

von Peter II (Gast)


Lesenswert?

Felix Geerkens schrieb:
> @Peter geht des Wirklich kommt da dann nicht 4,56 raus??

ja, weil es ja int's sind, dort kann kein Komma rauskommen.

von Felix G. (geerkins)


Lesenswert?

des heist bei unsigned char auch??

von Peter II (Gast)


Lesenswert?

Felix Geerkens schrieb:
> des heist bei unsigned char auch??

klar.

Aber das sind wirklich Grundlagen von C.

von Felix G. (geerkins)


Lesenswert?

Jep ich weis danke für die Hilfe
es ist peinlich das ich nicht selbst auf diese lösung gekommen bin und 
die frage mit char war auch nur zur absicherung

von Felix G. (geerkins)


Lesenswert?

So AHbs jetzt Reingeschrieben es geht soweit einziges Problem ist wenn 
ich eine zahl größer 10 anzeige kommt am der einser Stelle nurnoch sch.. 
raus
woran könte das liegen hier mal mein code:
1
#include   <avr/io.h>      //Grundfunktionen
2
#ifndef   F_CPU        //Vordefinieren für delay.h
3
#define   F_CPU 8000000UL    //Definition von F_CPU in Herz
4
#endif
5
#include   <util/delay.h>    //Warteschleifen
6
#include    <avr/interrupt.h>  //Interruptheader
7
8
typedef unsigned char byte;
9
10
//Hier kann man den Code an seine Siebensegment Anzeige anpassen
11
const byte Zahl[10] = {0b10000001, 0b11111001, 0b01000011, 0b01100001, 0b00111001, 0b00100101, 0b00000101, 0b11110001, 0b00000001, 0b00100001};
12
#define  Segm0_E 0
13
#define  Segm0_Z 1
14
15
16
17
int Berechnung(byte Stelle, byte Var)
18
{
19
byte y;              //y Rückgabewert
20
y = Var / Stelle;
21
return y;
22
}
23
24
25
void Anzeige(byte Stelle, byte Var,byte Segm)
26
{
27
28
  PORTD |= (1<<Segm);              //Jeweilige Anzeige Anschlaten
29
  PORTB=Zahl[Berechnung(Stelle, Var)];    //Zahl ausgeben
30
  _delay_ms(3);
31
  PORTD &= ~(1<<Segm);            //Anzeige weider Ausschalten
32
}
33
34
int main (void)
35
{
36
  //Registerinitialisierung
37
  //TCCR1A = 0b00000000;                      //Timer im CTC-Mode; Prescaler 256; CPU-Clock
38
  //TCCR1B = 0b00001100;                      //Timer im CTC-Mode; Prescaler 256; CPU-Cloc//k
39
  //TCCR1C = 0b00000000;                      //Timer im CTC-Mode; Prescaler 256; CPU-Cl//ock
40
  //TIMSK  = 0b01000000;                      //Interrupt bei Compare Match
41
  //OCR1A  = 31249;                        //genau eine Sekunde; Comparematch-Register
42
  DDRB   = 0b11111111;                      //Alles Ausgang; Siebensegmentanzeige
43
  DDRD   = 0b11111111;                      //PD4 und PD5 sind Eingänge
44
  //sei();                          //Interrupts an
45
  unsigned char Var = 0;
46
  int c = 0;
47
48
  PORTD = 0b11111111;
49
50
  //Hauptschleife
51
  while(1)
52
  {
53
    Anzeige(1, Var, Segm0_E);
54
    Anzeige(10, Var, Segm0_Z);
55
    c++;
56
    if (c == 10)
57
  {
58
    Var++;
59
      c = 0;
60
  }
61
  }
62
}

von Michael (Gast)


Lesenswert?

1
int Berechnung(byte Stelle, byte Var)
2
{
3
byte y;              //y Rückgabewert
4
y = Var / Stelle;
5
return y;
6
}

Das ist jetzt aber nicht die Funktion mit der du die Stelle berechnen 
willst oder?

Spielen wir das mal durch mit 213 und Stelle 1

213 / 1 = 213

mit Stelle 2

213 / 2 = 106 (die ,5 wird abgeschnitten)

mit Stelle 3

213 / 3 = auch falsch.

Denk doch mal nach. Du kannst die Stelle ja nicht einfach so berechnen. 
Wenndann muss du alle stellen berechnen.

Also 213 / 100 = 2 = hunderter
213 - (2(hunderter)*100) = 13
13 / 10 = 1 = zehner
13 - (1(zehner)*10) = 3
3 = einer

so geht das. Alternativ sind itoa oder sprinft: 
http://www.mikrocontroller.net/articles/FAQ#itoa.28.29_.28utoa.28.29.2C_ltoa.28.29.2C_ultoa.28.29.2C_ftoa.28.29_.29


Klar ?

von Felix G. (geerkins)


Lesenswert?

ops daran hab ich garnicht gedacht
dei sache ist die das ich die zentrale berechnung wenn möglich vrmeiden 
will und auch nicht wissen muss wie vile stellen meien anzeige bzw meien 
zahl hat ich. ich werde also nochmal darüber nachdenken müssen
felix
fals ihr ne ide habt wie ich des lösen kann schreibt es

von Felix G. (geerkins)


Lesenswert?

So jetzt die überarbeiter version mit atoi
1
#include   <avr/io.h>      //Grundfunktionen
2
#ifndef   F_CPU        //Vordefinieren für delay.h
3
#define   F_CPU 8000000UL    //Definition von F_CPU in Herz
4
#endif
5
#include   <util/delay.h>    //Warteschleifen
6
#include    <avr/interrupt.h>  //Interruptheader
7
#include  <stdlib.h>
8
typedef unsigned char byte;
9
10
//Hier kann man den Code an seine Siebensegment Anzeige anpassen
11
const byte Zahl[10] = {0b10000001, 0b11111001, 0b01000011, 0b01100001, 0b00111001, 0b00100101, 0b00000101, 0b11110001, 0b00000001, 0b00100001};
12
#define  Segm0_E 0
13
#define  Segm0_Z 1
14
15
16
/*char intToChar (int integer)
17
{
18
  return (char)integer+48;
19
}*/
20
21
22
int Berechnung(byte Stelle, int Var)
23
{
24
int y;              //y Rückgabewert
25
char Buffer [3];
26
itoa (Var, Buffer,10);
27
y = atoi(Buffer[Stelle]);
28
byte x = y;
29
return x;
30
}
31
32
33
void Anzeige(byte Stelle, byte Var,byte Segm)
34
{
35
36
  PORTD |= (1<<Segm);              //Jeweilige Anzeige Anschlaten
37
  PORTB=Zahl[Berechnung(Stelle, Var)];    //Zahl ausgeben
38
  _delay_ms(3);
39
  PORTD &= ~(1<<Segm);            //Anzeige weider Ausschalten
40
}
41
42
int main (void)
43
{
44
  //Registerinitialisierung
45
  //TCCR1A = 0b00000000;                      //Timer im CTC-Mode; Prescaler 256; CPU-Clock
46
  //TCCR1B = 0b00001100;                      //Timer im CTC-Mode; Prescaler 256; CPU-Cloc//k
47
  //TCCR1C = 0b00000000;                      //Timer im CTC-Mode; Prescaler 256; CPU-Cl//ock
48
  //TIMSK  = 0b01000000;                      //Interrupt bei Compare Match
49
  //OCR1A  = 31249;                        //genau eine Sekunde; Comparematch-Register
50
  DDRB   = 0b11111111;                      //Alles Ausgang; Siebensegmentanzeige
51
  DDRD   = 0b11111111;                      //PD4 und PD5 sind Eingänge
52
  //sei();                          //Interrupts an
53
  unsigned char Var = 0;
54
  int c = 0;
55
56
  PORTD = 0b11111111;
57
58
  //Hauptschleife
59
  while(1)
60
  {
61
    Anzeige(1, Var, Segm0_E);
62
    Anzeige(2, Var, Segm0_Z);
63
    c++;
64
    if (c == 10)
65
  {
66
    Var++;
67
      c = 0;
68
  }
69
  }
70
}
71
72
}
leider zeigt meine 7segm nur noch 0 an was mache ich falsch

von Michael (Gast)


Lesenswert?

Ja sagmal klickst du das Zeug nur zusammen? Lies mal ein C Buch oder 
zumindest die Referenz zu atoi und itao
1
int Berechnung(byte Stelle, int Var)
2
{
3
int y;              //y Rückgabewert
4
char Buffer [3];
5
itoa (Var, Buffer,10);
6
y = atoi(Buffer[Stelle]);
7
byte x = y;
8
return x;
9
}

Was soll das sein? Zuerst machst du aus dem Integer einen String und 
dann wieder einen Integer?

itoa ist richtig, macht dir aus dem Integer einen String aber der steht 
natürlich im ASCII Format in dem Array: 
http://www.asciitable.com/index/asciifull.gif

213 = 2,1,3,0 (binäre Null (\0) am Schluss immer bei Strings!)
abgelegt wird es also:
50,49,51,0
Diese Werte findest du in der Tabelle s.o. 49='1', 50='2', 51='3', ...

Wie kommt man von 49 auf 1? -> 48 Abziehen
Wie kommt man von 50 auf 2? -> 48 Abziehen
Wie kommt man von 51 auf 3? -> 48 Abziehen
....

blüht dir was ?

Zahl = ASCII Char - 48




Buffer[3] ist natürlich zu klein weil die binäre Null immer mit muss. 
Also Buffer[4] ist richtig. Mach mal ein C Tutorial - das sind absolute 
Basics.

itoa und atoi sind brutalst Speicher- und Geschwindigkeitsfressend. 
Darum realisiere lieber die Umrechnung wie ich sie dir oben 
vorgeschlagen habe. Die Divisionen brauchen schon lange genug.

von Wilhelm F. (Gast)


Lesenswert?

Felix Geerkens schrieb:

> leider zeigt meine 7segm nur noch 0 an was mache ich falsch

Geh das Programm mal manuell mit Papier und Stift schrittweise durch. 
Dann kommst du bestimmt drauf.

von Garden (Gast)


Lesenswert?


von Wilhelm F. (Gast)


Lesenswert?

Hier mal ein Programmbeispiel, wo eine größere Hexadezimalzahl 
ausgegeben wird:
1
/*******************************************************************************
2
DOES:    Print Dezimal (aus Kernighan/Ritchie: Programmieren in C)
3
         Rekursives Beispiel
4
         Könnte zur dezimalen Wandlung von Binärzahlen verwendet werden.
5
GLOBALS: none
6
RETURNS: none
7
*******************************************************************************/
8
void printd (unsigned long n)
9
{
10
/*
11
  if (n < 0)
12
  {
13
    putchar ('-');
14
    n = -n;
15
  }
16
*/
17
  if (n / 10)
18
  {
19
    printd (n / 10);
20
  }
21
  putchar (n % 10 + '0');
22
}
23
/******************************************************************************/

Einfach zur Ansicht.

von Fabian O. (xfr)


Lesenswert?

Das Programmbeispiel ist nur dafür gedacht, Rekursion zu erklären. In 
einer realen Mikrocontroller-Anwendung will man sich den Stack nicht so 
vollmüllen ...

von Michael (Gast)


Lesenswert?

Wer nicht iterativ programmieren kann kann es rekursiv schon gleich 
dreimal nicht :-D


Also jetzt mal im Ernst - jetzt kann ich echt nicht mehr zuschauen.
1
int Berechnung(unsigned byte digit, int inp_var)
2
{
3
 char buffer [4];                  // Buffer for itoa
4
 itoa (inp_var, buffer, 10);       // convert inp_var to char, dec
5
 return (Buffer[digit] - 48);     // convert char to number
6
}

von Wilhelm F. (Gast)


Lesenswert?

Fabian O. schrieb:
> Das Programmbeispiel ist nur dafür gedacht, Rekursion zu erklären. In
> einer realen Mikrocontroller-Anwendung will man sich den Stack nicht so
> vollmüllen ...

Da hast du Recht, wenn der Stack nur klein ist.

von Walter S. (avatar)


Lesenswert?

Michael schrieb:
> Also jetzt mal im Ernst - jetzt kann ich echt nicht mehr zuschauen.

das mag ja vielleicht funktionieren, schön ist aber was anderes

von Karl H. (kbuchegg)


Lesenswert?

Walter S. schrieb:
> Michael schrieb:
>> Also jetzt mal im Ernst - jetzt kann ich echt nicht mehr zuschauen.
>
> das mag ja vielleicht funktionieren, schön ist aber was anderes

Ausserdem ziemlich sicher nicht das was er will. Denn die fehlenden 
führenden 0-en machen ihm zu schaffen. Das ist bei LCD schon 'ein 
Problem', bei 7-Segment Anzeigen will man aber üblicherweise haben, dass 
die Einerstelle immer an derselben Stelle steht.

Allerdings stellt Felix sich auch wirklich an.
Man zerlegt nicht die Zahl während der eigentlichen Ausgabe. Die Ausgabe 
(in einer ISR) zeigt vorgefertigte Bitmuster an. Wo immer die auch 
herkommen. Zb. aus einer Funktion, die eine Zahl in die 3 Stellen 
zerlegt und die entsprechend anzuzeigenden Bitmuster in den globalen 
Variablen hinterlässt, auf dass die Anzeige-ISR sie regelmässig an die 
7-Segment ausgibt.

von Michael (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Das ist bei LCD schon 'ein
> Problem', bei 7-Segment Anzeigen will man aber üblicherweise haben, dass
> die Einerstelle immer an derselben Stelle steht.

Dann muss er sprintf nehmen oder programmieren lernen ...

von Karl H. (kbuchegg)


Lesenswert?

Michael schrieb:
> Karl Heinz Buchegger schrieb:
>> Das ist bei LCD schon 'ein
>> Problem', bei 7-Segment Anzeigen will man aber üblicherweise haben, dass
>> die Einerstelle immer an derselben Stelle steht.
>
> Dann muss er sprintf nehmen oder programmieren lernen ...

:-)
Er muss nur durch 10 dividieren lernen und lernen was es mit Modulo auf 
sich hat.

von Axel G. (axelg) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> Er muss nur durch 10 dividieren lernen und lernen was es mit Modulo auf
> sich hat.

*Mathe lernen
*C lernen
*Und Rechtschreibung wären auch noch schön

Da hat er ja noch was zu tun.

von Michael (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Michael schrieb:
>> Karl Heinz Buchegger schrieb:
>>> Das ist bei LCD schon 'ein
>>> Problem', bei 7-Segment Anzeigen will man aber üblicherweise haben, dass
>>> die Einerstelle immer an derselben Stelle steht.
>>
>> Dann muss er sprintf nehmen oder programmieren lernen ...
>
> :-)
> Er muss nur durch 10 dividieren lernen und lernen was es mit Modulo auf
> sich hat.

Das hab ich ihm oben auch schon vorgekaut aber das nimmt er ja auch 
nicht an.

Michael schrieb:
> Also 213 / 100 = 2 = hunderter
> 213 - (2(hunderter)*100) = 13
> 13 / 10 = 1 = zehner
> 13 - (1(zehner)*10) = 3
> 3 = einer

Ich weiß echt nicht was daran so schwer ist. Modulo braucht man da ja 
nicht mal. Und mit ein paar schnellen if-Abfragen kann man sich die 
führenden Nullen oder Vorzeichen spielend holen.

von Karl H. (kbuchegg)


Lesenswert?

Michael schrieb:

> Ich weiß echt nicht was daran so schwer ist.

Na ja..
Er hat sich da in eine dämliche Funktion "Anzeige" verrannt.

Das ist
a) schon mal der grundsätzlich falsche Weg
b) bringt ihn das bei der Zerlegung nicht weiter.
   (Man kann schon so eine Funktion benutzen. Aber eigentlich braucht
    die kein Mensch.)

Erst mal muss er verstehen, dass er eine Zahl als ganzes auf seine 7_Seg 
ausgibt. Dann wird alles ganz einfach. Sein eigentliches Problem ist das 
Multiplexen. Wenn er das richtig ansetzt ist der Rest nur noch Pipifax.

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.