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
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.
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.
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ß
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
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.
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?
Nee, dann machst du es noch nicht richtig und die 9 wird gelegentlich auf der falschen Stelle ausgegeben.
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.
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.
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.
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 !!
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!
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.
@Telco : Danke , genau das hab ich mir gedacht nachdem ich den Code hochgeladen habe. @Dirk: Werde es mal versuchen und sehen was dabei rauskommt.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.