Forum: Mikrocontroller und Digitale Elektronik 2 Stellige 7 Segment Anzeige


von Robert I. (robert_i39)


Lesenswert?

Hallo,

Ich würde gerne eine 2 stellige Anzeige mit 2 7 Segment Anzeigen 
programmien.

Sie soll von 00 - 99 hochzählen. Die Schaltung läuft im 
Multiplexbetrieb.

Wie kann ich die 100 Zahlen auf die codierung der Anzeige bringen ohne 
für jede einzelne zahl eine eigene Funktion zu schreiben ?

Programmiert wird auf einem MSP430G2553.


Danke euch schon mal

von Mike (Gast)


Lesenswert?

Robert I. schrieb:
> Wie kann ich die 100 Zahlen auf die codierung der Anzeige bringen ohne
> für jede einzelne zahl eine eigene Funktion zu schreiben ?

Mach dir eine Tabelle für die Ziffern 0..9 und die liest du dann zwei 
mal, einmal für die Zehner und einmal für die Einer.

von MaWin (Gast)


Lesenswert?

In dem du die 2 Ziffern einzeln behandelst.

char ziffer[]={0x7D,0x30,0x6D,0x79,0x33,0x5D,0x5F,0x70,0x7B,0x7B};

void main(void)
{
   DDRB=DDRD=0xFF;
   while(1) for(n=0;n<100;n++)
  {
    PORTB=ziffer[n%10];
    PORTD=ziffer[n/10];
    _delay_ms(1000);
  }
}

Ist also nicht wirklich schwer, aber der Lernweg bis dahin noch weit.

von Robert I. (robert_i39)


Lesenswert?

Danke euch schon mal.

Hab das auch soweit erreicht, nur stehe ich vor dem Problem es Sinnvoll 
auf die Anzeige zu übertragen.

Wenn ich von 0-9 hochzähle , möchte ich dass auf der Zehnerstelle immer 
eine 0 steht , also 00, 01, 02,03, usw. Ich schaffe es nur nicht dass 
die Zehnerstelle, also die 0 steht und nur die Einerstelle aktualisiert 
wird.
Bei mir läuft es total schnell durch und man kann auch erkennen dass die 
Zahlen immer kurz ausgehen.

Also bleibt noch die Frage wie ich es umsetzen kann dass zb 9 Sekunden 
hoch gezählt werden ohne dass eine der Beiden stellen immer aus ist.


Gruß

von Easylife (Gast)


Lesenswert?

Wenn du a mit 1 initialisierst funktionierts.

Show code.

von Max H. (hartl192)


Lesenswert?

Robert I. schrieb:
> Bei mir läuft es total schnell durch und man kann auch erkennen dass die
> Zahlen immer kurz ausgehen.
Zeig mal den Code. Kann es sein, dass du mit irgendwelchen Delays das 
Multiplexen unterbrichst?

> Also bleibt noch die Frage wie ich es umsetzen kann dass zb 9 Sekunden
> hoch gezählt werden ohne dass eine der Beiden stellen immer aus ist.
1
PORTB=ziffer[n%10];
2
if(ziffer>9)
3
  PORTD=ziffer[n/10];
4
else
5
  PORTD=0x00;

: Bearbeitet durch User
von Dirk K. (dekoepi)


Lesenswert?

Für ein 4-stelliges 7-Segment sieht es als Code für AVR so aus:
1
// cathode pins for digit selection
2
volatile static uint8_t digit[4]={
3
    0b00000100,
4
    0b00001000,
5
    0b00010000,
6
    0b00100000 };
7
8
// 'databse' of digits
9
volatile static uint8_t lightup[10]={
10
    0b00111111,  // 0
11
    0b00000110,  // 1
12
    0b01011011,  // 2
13
    0b01001111,  // 3
14
    0b01100110,  // 4
15
    0b01101101,  // 5
16
    0b01111101,  // 6
17
    0b00000111,  // 7
18
    0b01111111,  // 8
19
    0b01101111 };  // 9
20
21
  int tempdigit;  // dissect and show the number
22
  for (int8_t count=3; count>=0; count--) {
23
    tempdigit=temp % 10;
24
       PORTD &= ~(digit[count]);  // select digit
25
       PORTC |= (lightup[tempdigit] & numbitmaska);
26
       PORTD |= (lightup[tempdigit] & numbitmaskd);
27
       if (!(showyear) & !(showdate) & !(showvcc) & !(showtemp) & (count==1) & toggle) PORTD |= 0x80;  // set dot
28
       if (showdate & ((count==1)|(count==3))) PORTD |= 0x80;  // set dot
29
       if (showvcc & (count==0)) PORTD |= 0x80;  // set dot
30
       if (showtemp & (count==1)) PORTD |= 0x80;  // set dot
31
       temp /= 10;
32
    PORTC &= ~(numbitmaska);  // Set all pins A0-A5 HIGH
33
    PORTD &= ~(numbitmaskd);  // Set D2-D5 and D6+D7 HIGH
34
    PORTD |= digbitmask;  // deselect digit
35
  }

Die Schleife musst du auf zwei Durchläufe reduzieren, die if-Bedingungen 
zur Aktivierung des Dezimalpunkts kannst du löschen. Die Funktion unter 
den Arrays läuft bei mir im Timer-Interrupt, einmal pro Millisekunde.

von Robert I. (robert_i39)


Lesenswert?

Bei mir funktionierts es jetzt.

Hab es geschafft dass die Anzeige von 00 bis 99 zählt. Vllt nicht sehr 
elegalnt und effektiv gelöst aber es geht.

Ist es normal dass ich immer einen leichten Schatten habe? Also wenn ich 
Zb die Zahl 19 ausgebe habe ich in der Anzeige für den 1er einen 
leichten Schatten vom 9er drinnen?

von Dirk K. (dekoepi)


Lesenswert?

Nee, dann machst du es noch nicht richtig und die 9 wird gelegentlich 
auf der falschen Stelle ausgegeben.

von Robert I. (robert_i39)


Angehängte Dateien:

Lesenswert?

Ja das denke ich mir selber auch , nur ich wollte keinen Code aus dem 
Internet nehmen und den nur einfügen, ich will solche sachen selber 
lösen.

Ich weiss halt nicht ob man es auf dem Foto erkennen kann, da sollte 
eigentlich 16 stehen, mit dem Auge erkennt man es zwar besser aber ihr 
könnt euch sicher denken um was es geht.

von Dirk K. (dekoepi)


Lesenswert?

Ohne deinen Code zu sehen, können wir nur noch mehr rätseln als du 
selber. Da scheinen die LEDs zwischendrin alle angeschaltet zu werden.

Also, Code posten, dann können andere helfen. So bleibt es ein 
"tu-du-was-ich-denke", also Mission Impossible.

von Peter D. (peda)


Lesenswert?

Robert I. schrieb:
> Die Schaltung läuft im
> Multiplexbetrieb.

Multiplex benötigt zwingend einen Timerinterrupt, alles andere ist 
Quatsch.

Nur wenige Uneinsichtige versuchen es mit einem Delay im Main zu 
erzwingen, was nur doppelte Arbeit bedeutet.
Auch als Anfänger muß niemand in die Sackgasse hineinfahren, er darf 
auch gleich den richtigen Weg nehmen.

von Robert I. (robert_i39)


Lesenswert?

Ja gut ich habs ohne Interrupt gemacht da ich da noch nicht so 
durchblicke.

Sieht so bei mir aus :
1
#include <msp430.h> 
2
/*
3
 * Developer : XXXXXXXXXXXXXX
4
 * Software : 2 Digit on 7 Segment Displays counting from 00 to 99
5
 * Version : v2
6
 * Date : 04.May.2014
7
 *
8
 */
9
10
11
12
#define Display  P1OUT
13
#define NULL  0x3F
14
#define ONE    0x0C
15
#define TWO    0x5B
16
#define THREE  0x5E
17
#define FOUR  0x6C
18
#define FIVE  0x76
19
#define SIX    0x77
20
#define SEVEN  0x1C
21
#define EIGHT  0xFF
22
#define NINE  0xFE
23
24
#define Digit1  P2OUT = 0x01
25
#define Digit2  P2OUT = 0x02
26
27
28
29
30
int InputNumber = 0;
31
int FirstNumber = 0;  //Unit Position
32
int SecondNumber = 0;  //Tens
33
int DelayCounter = 0;
34
int Digit1AcitveNumber = 0;
35
int Digit2AcitveNumber = 0;
36
37
38
39
int main(void)
40
{
41
    WDTCTL = WDTPW | WDTHOLD;  // Stop watchdog timer
42
  
43
    P1DIR = 0xFF;  //P1 --> Output
44
    P2DIR = 0x03;  //P2.0 + P2.1 --> Output
45
    P2OUT = 0;
46
47
    while(1)
48
    {
49
    for(InputNumber=InputNumber;InputNumber<100;InputNumber++)
50
    {
51
      FirstNumber = InputNumber % 10;
52
      SecondNumber = InputNumber / 10;
53
      switch(FirstNumber)
54
      {
55
        case 0:  Digit1AcitveNumber = NULL;
56
        break;
57
        case 1:  Digit1AcitveNumber = ONE;
58
        break;
59
        case 2:  Digit1AcitveNumber = TWO;
60
        break;
61
        case 3:  Digit1AcitveNumber = THREE;
62
        break;
63
        case 4:  Digit1AcitveNumber = FOUR;
64
        break;
65
        case 5:  Digit1AcitveNumber = FIVE;
66
        break;
67
        case 6:  Digit1AcitveNumber = SIX;
68
        break;
69
        case 7:  Digit1AcitveNumber = SEVEN;
70
        break;
71
        case 8:  Digit1AcitveNumber = EIGHT;
72
        break;
73
        case 9:  Digit1AcitveNumber = NINE;
74
        break;
75
      }
76
      switch(SecondNumber)
77
      {
78
        case 0:  Digit2AcitveNumber = NULL;
79
        break;
80
        case 1:  Digit2AcitveNumber = ONE;
81
        break;
82
        case 2:  Digit2AcitveNumber = TWO;
83
        break;
84
        case 3:  Digit2AcitveNumber = THREE;
85
        break;
86
        case 4:  Digit2AcitveNumber = FOUR;
87
        break;
88
        case 5:  Digit2AcitveNumber = FIVE;
89
        break;
90
        case 6:  Digit2AcitveNumber = SIX;
91
        break;
92
        case 7:  Digit2AcitveNumber = SEVEN;
93
        break;
94
        case 8:  Digit2AcitveNumber = EIGHT;
95
        break;
96
        case 9:  Digit2AcitveNumber = NINE;
97
        break;
98
      }
99
      DelayCounter = 0;
100
      while(DelayCounter<500)
101
      {
102
        Display = Digit1AcitveNumber;
103
        Digit1;
104
        _delay_cycles(1000);
105
        Display = Digit2AcitveNumber;
106
        Digit2;
107
        _delay_cycles(1000);
108
        DelayCounter++;
109
      }
110
    }
111
    int i = 0;
112
    for(i=0;i<1000;i++)
113
    {
114
      P2OUT = 0x03;
115
      P1OUT = 0xFF;
116
117
    }
118
    InputNumber = 0;
119
120
121
    }
122
}


Vllt kann mir ja mal jemand zeigen wie es effektiver und kürzer mithilfe 
von Interrupts wird.

Danke euch !!

von Telco (Gast)


Lesenswert?

Robert I. schrieb:
> #define NULL  0x3F

So was macht man nicht! NULL ist in den C-Headern schon definiert!
Wenn, dann nimm den Namen ZERO oder was anderes passendes, aber nicht 
NULL!

von Dirk K. (dekoepi)


Lesenswert?

Ui, echter Einsteiger-Code, schön :)

Du solltest vor dem Wechsel der Stellen Digit1 / Digit2 auch wieder 
ausmachen. So schreibt er den Wert der anderen Digit in die grad aktive 
und schaltet anschließend um. Dadurch hast du ein Glimmen der jeweils 
anderen Nummer.

von Robert I. (robert_i39)


Lesenswert?

@Telco : Danke , genau das hab ich mir gedacht nachdem ich den Code 
hochgeladen habe.

@Dirk: Werde es mal versuchen und sehen was dabei rauskommt.

von Easylife (Gast)


Lesenswert?

Robert I. schrieb:
> Vllt kann mir ja mal jemand zeigen wie es effektiver und kürzer mithilfe
> von Interrupts wird.

Der code wird auch deutlich kürzer, wenn du ein array statt der case 
structure für die digits nehmen würdest...

Ausserdem fände ich es logischer die Zehnerstelle "Digit1" und die 
Einerstelle "Digit2" zu nennen...

1
const unsigned char digit_port_data[10] = { 
2
  0x3F, // 0
3
  0x0C, // 1
4
  0x5B, // 2
5
  0x5E, // 3
6
  0x6C, // 4
7
  0x76, // 5
8
  0x77, // 6
9
  0x1C, // 7
10
  0xFF, // 8
11
  0xFE  // 9
12
};
13
14
15
()
16
17
Digit1AcitveNumber = digit_port_data[InputNumber / 10];
18
Digit2AcitveNumber = digit_port_data[InputNumber % 10];

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.