Hallo ich bin dabei mir eine Impulszählerschaltung zu bauen. Hardware ATtiny 2313 4 7-Segment Anzeigen 2x 4543 4x BC 328 zum Ansteuern der 7 segment paar Widerstände und C sowie Festspannungsregler an pin 4,5 und pin 7,8 hab ich die Transistoren für die 7 Segement Anzeige gelötet. Jetzt möchte ich erstmal ein Grundprogramm schreiben welches auf pin 4,5,7,8 low Pegel ausgibt. Allerdings sind bis jetzt alle Versuche gescheitert es liegen immer 5V an egal wie ich mein Programm verändere. Hier mal mein Code. Thx for help Grüße Simon #define MCU attiny2313 #include <avr/io.h> // Namen der IO Register #include <util/delay.h> // Funktionen zum warten int main(void){ DDRA = 0b00000111; //alle A als Ausgang 0-2 DDRB = 0b11111111; //alle B als Ausgang 0-7 DDRD = 0b01111111; //alle D als Ausgang 0-6 PORTA = 0b00000011; //A0,A1 = Pin 4,5 am uC -> Transistor PORTB = 0b11111111; //alles high auch für 7 seg PORTD = 0b00110000; //D4,D5 = Pin 8,9 am uC -> Transistor while(1) { // (5a) /* "leere" Schleife*/ // (5b) } // (5c) /* wird nie erreicht */ return 0; } Selbst wenn ich jetzt die Transitor Pins auf 0 schalte liegen - gemessen mim Multimeter - immernoch 5 V an den Pins an. Danke!
>Allerdings sind bis jetzt alle Versuche gescheitert es liegen immer 5V >an egal wie ich mein Programm verändere. Ein Schaltplan könnte ganz hilfreich sein;)
Guten Morgen anbei der gewünschte Schaltplan. Ich glaube auch den Fehler gefunden zu haben. Ich muss statt des PNP Transistors einen NPN einbauen - ?!? oder? Gestern habe ich noch den uc ausgebaut und dann lagen an den pins für TR-1 bis TR-4 5V an. Somit war es immer egal welche pins ich im code auf high gezogen habe... P.S. Wäre die Schaltung so dann i.o. an Pin1 des uc hängt ein öffner welchen ich zum resetten des impulszählers verwenden möchte (also anzeige auf 0000 bzw ganz aus)
pnp? npn? Ich sehe keinen Transistor. Der Öffner an Pin 1 ist also normalerweise geschlossen? Dann resettest Du den Controller ständig. Außerdem würde ich unbedingt einen Widerstand 10 kOhm von Pin 1 (Reset) an Vcc (5V) empfehlen. Und muss der Reset nicht auch am Programmierstecker liegen? Nachtrag: Erst jetzt habe ich gesehen, dass die PDF zwei Seiten hat, und jetzt habe ich auch die Transistoren gesehen. Die PNP sind schon in Ordnung (und besser als NPN an dieser Stelle), aber die Ausgänge TR1 bis TR4 müssen normalerweise auf HIGH (also auf 5V) liegen, nur wenn die entsprechende Ziffer eingeschaltet werden soll, wird der einzelne Ausgang auf LOW (GND) geschaltet. Zweiter Nachtrag: Beim HEF4543 musst Du PH (Pin 6) auf Vcc legen, wenn Du 7-Segment-LEDs mit gemeinsamer Anode hast.
Hi Edi R. Danke für die Info, ich habe 7 Segment mit gemeinsamer Kathode. Zu dem Transistor: Ich hab das Problem dass wenn ich Betriebsspannung anlege am Emitter 5V anliegen -soll ja auch so sein- Allerdings kommen über die Basis 4,3V an den uC was mir ja nix bringt - desshalb der Gedanke mit einem NPN Transistor nur genau anders herum eingebaut. Folgendes muss ich ncoh ändern : -Richtig? - an pin 1 häng ich jetzt nen öffner - zwischen pin 1 und vcc noch 10kOhm Widerstand - Wo muss ich den Reset am Programmierstecker anbringen? Danke Grüße Simon
Simon schrieb: > ich habe 7 Segment mit gemeinsamer Kathode. Bist Du sicher? Im Schaltplan steht auch: "CA", was ich als "Common Anode" verstehe. Aber wenn die Displays gemeinsame Kathoden haben, dann passt der Schaltplan nicht. > Zu dem Transistor: > Ich hab das Problem dass wenn ich Betriebsspannung anlege am Emitter 5V > anliegen -soll ja auch so sein- > Allerdings kommen über die Basis 4,3V an den uC was mir ja nix bringt - > desshalb der Gedanke mit einem NPN Transistor nur genau anders herum > eingebaut. Zuerst sollten wir klären, ob die Displays wirklich gemeinsame Kathoden haben, und wenn ja, den ganzen Schaltplan umstellen. > - an pin 1 häng ich jetzt nen öffner Ich dachte, da ist jetzt schon ein Öffner? Es sollte ein Schließer zwischen Pin 1 und GND hinkommen. Der ATtiny macht einen Reset, wenn der Pin 1 auf LOW gezogen wird. > - zwischen pin 1 und vcc noch 10kOhm Widerstand Richtig. Mit diesem Widerstand wird der Pin 1 sicher auf HIGH gezogen. Es ist zwar ein Pull-Up-Widerstand eingebaut, aber nach meinen Erfahrungen ist der zu hochohmig. Atmel empfiehlt diesen externen Widerstand übrigens auch. > - Wo muss ich den Reset am Programmierstecker anbringen? Wenn Du den 10-poligen ISP-Stecker verwendest: An Pin 5. Und ich sehe gerade, dass dort auch schon der 10-kOhm-Widerstand ist. Es fehlt also nur noch die Verbindung zu Pin 1, dann hat sich die Sache mit dem zusätzlichen Pull-Up-Widerstand auch erledigt.
Hallo again, jetzt auch mit Anmeldung. also ich hab nachgeschaut. - Das sind die 7 Segment - und doch mit gemeinsamer Anode. http://www.reichelt.de/?;ACTION=3;LA=444;GROUP=A51;GROUPID=3002;ARTICLE=6916;START=0;SORT=artnr;OFFSET=16;SID=31TQHyr38AAAIAADAKATY732e878fb025c20a23a09b38664a00bd - Pin 1 bekommt natürlich einen schließer - sorry for that. - anbei mal der neue schaltplan. zusätzlich habe ich auch den pin 6 vom 4543 geändert. Was mich eben stört ist die Tatsache, dass der Transistor eben die 4,3V an den uC Transistor Pin schaltet. Um auf 0V zu kommen bräuche ich ja ne negative Spannung am uC - oder? Thx for help Edit: Sorry fals es jetzt nichts mehr mit Programmierung zu tun hat und somit im falschen Forum ist
Simon S. schrieb: > - Das sind die 7 Segment - und doch mit gemeinsamer Anode. Dann passt der Schaltplan, dann passen auch die PNP-Transistoren. Ob die Basisvorwiderstände mit 1 kOhm nicht zu hochohmig sind, muss sich noch herausstellen. Möglicherweise reicht das aber auch. > zusätzlich habe ich auch den pin 6 vom 4543 geändert. Was die Hardware betrifft, müsste es so klappen. Obwohl ich ein paar Sachen ändern würde, aber das geht momentan schon zu weit. > Was mich eben stört ist die Tatsache, dass der Transistor eben die 4,3V > an den uC Transistor Pin schaltet. Um auf 0V zu kommen bräuche ich ja ne > negative Spannung am uC - oder? Der Transistor schaltet über die Basis überhaupt nichts, und Du brauchst auch keine negative Spannung am µC. Die 4,3 V misst Du wahrscheinlich direkt am Transistor, nicht am Portpin, oder? Dazwischen ist ja noch der Widerstand. Wenn Du direkt am Portpin 4,3 V misst, dann ist er nicht als Ausgang geschaltet. Oder die Basisvorwiderstände fehlen (bzw. sind kurzgeschlossen). Ich weiß ja nicht, mit welcher Entwicklungsumgebung Du arbeitest, aber probier mal, ob dieses Programm übersetzt wird und läuft:
1 | #include <avr/io.h> // Namen der IO Register |
2 | #include <util/delay.h> // Funktionen zum warten |
3 | |
4 | int main(void){ |
5 | DDRA = 0b00000111; //alle A als Ausgang 0-2 |
6 | DDRB = 0b11111111; //alle B als Ausgang 0-7 |
7 | DDRD = 0b01111111; //alle D als Ausgang 0-6 |
8 | |
9 | PORTA = 0b00000011; |
10 | PORTB = 0b00000000; |
11 | PORTD = 0b00110000; |
12 | |
13 | while(1) { |
14 | PORTA &= (1<<0); |
15 | _delay_ms(250); |
16 | PORTA |= (1<<0); |
17 | |
18 | PORTA &= (1<<1); |
19 | _delay_ms(250); |
20 | PORTA |= (1<<1); |
21 | |
22 | PORTD &= (1<<4); |
23 | _delay_ms(250); |
24 | PORTD |= (1<<4); |
25 | |
26 | PORTD &= (1<<5); |
27 | _delay_ms(250); |
28 | PORTD |= (1<<5); |
29 | }
|
30 | }
|
Damit müssten der Reihe nach auf den vier Digits "0" erscheinen.
Edi R. schrieb: > Der Transistor schaltet über die Basis überhaupt nichts, und Du brauchst > auch keine negative Spannung am µC. Die 4,3 V misst Du wahrscheinlich > direkt am Transistor, nicht am Portpin, oder? Dazwischen ist ja noch der > Widerstand. Wenn Du direkt am Portpin 4,3 V misst, dann ist er nicht als > Ausgang geschaltet. Oder die Basisvorwiderstände fehlen (bzw. sind > kurzgeschlossen). Also ich hab den uC ausgebaut und messe am uC Sockel die 4,3V und das Wundert mich eben. Vorwiderstände lt. Schaltplan 1k und nicht kurzgeschlossen. > > Ich weiß ja nicht, mit welcher Entwicklungsumgebung Du arbeitest, aber > probier mal, ob dieses Programm übersetzt wird und läuft: > Ich arbeite mit AVR STudio und WinAVR müsste also klappen. Leider kann ich erst am Sonntag abend bescheid geben ob es funktionert hat da ich übers we weg bin. thx bis sonntag bzw montag
Nabend. also es funktioniert so weit. Jetzt hab ich ne frage zum code :-) Ich habe dein Beispiel etwas angepasst. Es sollen die Zeichen 1-4 auf der Anzeige ausgegeben werden. Segment 1 = 1 Segment 2 = 2 Segment 3 = 3 Segment 4 = 4 Problem ist, das 1-3 geht bei 4 kommt ne 6 raus und beim nächsten durchlauf geht es 1636 1636 usw hier mal der code. thx for help
1 | #define MCU attiny2313
|
2 | |
3 | |
4 | #include <avr/io.h> // Namen der IO Register |
5 | #include <util/delay.h> // Funktionen zum warten |
6 | |
7 | int main(void){ |
8 | |
9 | DDRA = 0b00000111; //alle A als Ausgang 0-2 |
10 | DDRB = 0b11111111; //alle B als Ausgang 0-7 |
11 | DDRD = 0b01111111; //alle D als Ausgang 0-6 |
12 | |
13 | PORTA = 0b00000011; |
14 | PORTB = 0b00000000; |
15 | PORTD = 0b00110000; |
16 | |
17 | while(1) { |
18 | |
19 | PORTB |= (1<<PB1) ; //Einschalten Ziffer 1 |
20 | PORTB &= ~(1<<PB2) | (1<<PB3) | (1<<PB5); // Einschalten Ziffer 1 |
21 | PORTD &= ~(1<<PD5); //AUsschalten pos 1 |
22 | _delay_ms(250); |
23 | PORTD |= (1<<PD5); //Einschalten |
24 | |
25 | PORTD |= (1<<PD1) ; //Einschalten Ziffer 2 |
26 | PORTD &= ~(1<<PD0) | (1<<PD2)| (1<<PD3); // Einschalten Ziffer 2 |
27 | PORTD &= ~(1<<PD4); //Ausschalten pos 2 |
28 | _delay_ms(250); |
29 | PORTD |= (1<<PD4); //Einschalten |
30 | |
31 | PORTB |= (1<<PB1) | (1<<PB2) ; //Einschalten Ziffer 3 |
32 | PORTB &= ~(1<<PB3) | (1<<PB5); // Einschalten Ziffer 3 |
33 | PORTA &= ~(1<<PA0); //AUsschalten pos 3 |
34 | _delay_ms(250); |
35 | PORTA |= (1<<PA0); //Einschalten |
36 | |
37 | |
38 | PORTD |= (1<<PD2) ; //Einschalten Ziffer 4 |
39 | PORTD &= ~(1<<PD0) | (1<<PD1)| (1<<PD3); // Einschalten Ziffer 4 |
40 | PORTA &= ~(1<<PA1); //AUsschalten pos 4 |
41 | _delay_ms(250); |
42 | PORTA |= (1<<PA1); //Einschalten |
43 | |
44 | |
45 | |
46 | }
|
47 | }
|
Hallo nochmal ich hab es geschafft der Impulszähler funktioniert. Allerdings hab ich noch etwas Probleme mit meinem Code. Die Profis unter euch werden sich bestimmt die Hände über dem Kopf zusammschlagen. Anbei ist ein Bild von der 7 Segment. Es ist deutlich zu erkennen, dass z.b. bei der 7 immer noch die 0 schwach durchleuchtet. Wie kann ich das umgehen. Ich hab auch schon im AVR Tutorial nachgelesen zwecks Geisterleuchten, komm aber gerade nicht weiter. Hier zusätzlich mein Code. vielen Dank
1 | #include <avr/io.h> // Namen der IO Register |
2 | #include <util/delay.h> // Funktionen zum warten |
3 | |
4 | |
5 | void Display(int num) |
6 | {
|
7 | switch (num) |
8 | {
|
9 | case 0: |
10 | PORTB &= ~(1<<PB1)| (1<<PB2)| (1<<PB3)| (1<<PB4); |
11 | PORTD &= ~(1<<PD0)| (1<<PD1)| (1<<PD2)| (1<<PD3);break; |
12 | case 1: |
13 | PORTB |= (1<<PB1); |
14 | PORTB &= ~(1<<PB2)| (1<<PB3)| (1<<PB4); |
15 | PORTD |= (1<<PD0); |
16 | PORTD &= ~(1<<PD1)| (1<<PD2)| (1<<PD3);break; |
17 | case 2: |
18 | PORTB |= (1<<PB2); |
19 | PORTB &= ~(1<<PB1)| (1<<PB3)| (1<<PB4); |
20 | PORTD |= (1<<PD1); |
21 | PORTD &= ~(1<<PD0)| (1<<PD2)| (1<<PD3);break; |
22 | case 3: |
23 | PORTB |= (1<<PB1) | (1<<PB2); |
24 | PORTB &= ~(1<<PB3)| (1<<PB4); |
25 | PORTD |= (1<<PD0) | (1<<PD1); |
26 | PORTD &= ~(1<<PD2)| (1<<PD3);break; |
27 | case 4: |
28 | PORTB |= (1<<PB3); |
29 | PORTB &= ~(1<<PB1)| (1<<PB2)| (1<<PB4); |
30 | PORTD |= (1<<PD2); |
31 | PORTD &= ~(1<<PD0)| (1<<PD1)| (1<<PD3);break; |
32 | case 5: |
33 | PORTB |= (1<<PB1) | (1<<PB3); |
34 | PORTB &= ~(1<<PB2)| (1<<PB4); |
35 | PORTD |= (1<<PD0) | (1<<PD2); |
36 | PORTD &= ~(1<<PD1)| (1<<PD3);break; |
37 | case 6: |
38 | PORTB |= (1<<PB2) | (1<<PB3); |
39 | PORTB &= ~(1<<PB1)| (1<<PB4); |
40 | PORTD |= (1<<PD1) | (1<<PD2); |
41 | PORTD &= ~(1<<PD0)| (1<<PD3);break; |
42 | case 7: |
43 | PORTB |= (1<<PB1) | (1<<PB2) | (1<<PB3); |
44 | PORTB &= ~(1<<PB4); |
45 | PORTD |= (1<<PD0) | (1<<PD1) | (1<<PD2); |
46 | PORTD &= ~(1<<PD3);break; |
47 | case 8: |
48 | PORTB |= (1<<PB4); |
49 | PORTB &= ~(1<<PB1)| (1<<PB2)| (1<<PB3); |
50 | PORTD |= (1<<PD3); |
51 | PORTD &= ~(1<<PD0)| (1<<PD1)| (1<<PD2);break; |
52 | case 9: |
53 | PORTB |= (1<<PB1) | (1<<PB4); |
54 | PORTB &= ~(1<<PB2)| (1<<PB3); |
55 | PORTD |= (1<<PD0) | (1<<PD3); |
56 | PORTD &= ~(1<<PD1)| (1<<PD2);break; |
57 | default:
|
58 | PORTB &= ~(1<<PB1)| (1<<PB2)| (1<<PB3)| (1<<PB4); |
59 | PORTD &= ~(1<<PD0)| (1<<PD1)| (1<<PD2)| (1<<PD3);break; |
60 | }
|
61 | }
|
62 | |
63 | void SegmentNummer(int tausender, int hunderter, int zehner, int einer) |
64 | {
|
65 | |
66 | // gebe einer aus
|
67 | Display(einer); |
68 | PORTD &= ~(1<<PD5); //Transistor Seg 1 aus -> Seg = ein |
69 | PORTD |= (1<<PD4); //Transistor Seg 2 an -> Seg = aus |
70 | PORTA |= (1<<PA0); //Transistor Seg 3 an -> Seg = aus |
71 | PORTA |= (1<<PA1); //Transistor Seg 4 an -> Seg = aus |
72 | _delay_ms(2); |
73 | PORTA = 0b00000000; |
74 | PORTB = 0b00000000; |
75 | PORTD = 0b00000000; |
76 | |
77 | // gebe zehner aus
|
78 | Display(zehner); |
79 | PORTD |= (1<<PD5); //Transistor Seg 1 an -> Seg = aus |
80 | PORTD &= ~(1<<PD4); //Transistor Seg 2 aus -> Seg = ein |
81 | PORTA |= (1<<PA0); //Transistor Seg 3 an -> Seg = aus |
82 | PORTA |= (1<<PA1); //Transistor Seg 4 an -> Seg = aus |
83 | _delay_ms(2); |
84 | PORTA = 0b00000000; |
85 | PORTB = 0b00000000; |
86 | PORTD = 0b00000000; |
87 | |
88 | // gebe hunderter aus
|
89 | Display(hunderter); |
90 | PORTD |= (1<<PD5); //Transistor Seg 1 an -> Seg = aus |
91 | PORTD |= (1<<PD4); //Transistor Seg 2 an -> Seg = aus |
92 | PORTA &= ~(1<<PA0); //Transistor Seg 3 aus -> Seg = ein |
93 | PORTA |= (1<<PA1); //Transistor Seg 4 an -> Seg = aus |
94 | _delay_ms(2); |
95 | PORTA = 0b00000000; |
96 | PORTB = 0b00000000; |
97 | PORTD = 0b00000000; |
98 | |
99 | // gebe tausender aus
|
100 | Display(tausender); |
101 | PORTD |= (1<<PD5); //Transistor Seg 1 an -> Seg = aus |
102 | PORTD |= (1<<PD4); //Transistor Seg 2 an -> Seg = aus |
103 | PORTA |= (1<<PA0); //Transistor Seg 3 an -> Seg = aus |
104 | PORTA &= ~(1<<PA1); //Transistor Seg 4 aus -> Seg = ein |
105 | _delay_ms(2); |
106 | PORTA = 0b00000000; |
107 | PORTB = 0b00000000; |
108 | PORTD = 0b00000000; |
109 | |
110 | |
111 | }
|
112 | |
113 | |
114 | // Modification for active high push button
|
115 | |
116 | #define debounce( port, pin ) \
|
117 | ({ \
|
118 | static uint8_t flag = 0; /* new variable on every macro usage */ \ |
119 | uint8_t i = 0; \
|
120 | \
|
121 | if( flag ){ /* check for key release: */ \ |
122 | for(;;){ /* loop... */ \ |
123 | if( (port & 1<<pin) ){ /* ... until key pressed or ... */ \ |
124 | i = 0; /* 0 = bounce */ \ |
125 | break; \
|
126 | } \
|
127 | _delay_us( 98 ); /* * 256 = 25ms */ \ |
128 | if( --i == 0 ){ /* ... until key >25ms released */ \ |
129 | flag = 0; /* clear press flag */ \ |
130 | i = 0; /* 0 = key release debounced */ \ |
131 | break; \
|
132 | } \
|
133 | } \
|
134 | }else{ /* else check for key press: */ \ |
135 | for(;;){ /* loop ... */ \ |
136 | if( !(port & 1<<pin) ){ /* ... until key released or ... */ \ |
137 | i = 0; /* 0 = bounce */ \ |
138 | break; \
|
139 | } \
|
140 | _delay_us( 98 ); /* * 256 = 25ms */ \ |
141 | if( --i == 0 ){ /* ... until key >25ms pressed */ \ |
142 | flag = 1; /* set press flag */ \ |
143 | i = 1; /* 1 = key press debounced */ \ |
144 | break; \
|
145 | } \
|
146 | } \
|
147 | } \
|
148 | i; /* return value of Macro */ \ |
149 | }) |
150 | |
151 | |
152 | |
153 | |
154 | int main(void){ |
155 | |
156 | DDRA = 0b00000111; //alle A als Ausgang 0-2 |
157 | DDRB = 0b11111110; //alle B als Ausgang 0-7 |
158 | DDRD = 0b01111111; //alle D als Ausgang 0-6 |
159 | |
160 | PORTA = 0b00000011; |
161 | PORTB = 0b00000000; |
162 | PORTD = 0b00011000; |
163 | |
164 | int zahl = 0; |
165 | |
166 | while(1) { |
167 | |
168 | if (zahl >9999) |
169 | {
|
170 | zahl=0; |
171 | }
|
172 | |
173 | int tausender = zahl/1000; |
174 | int hunderter = (zahl-(tausender*1000))/100; |
175 | int zehner = (zahl-(tausender*1000) - (hunderter*100))/10; |
176 | int einer = (zahl-(tausender*1000) - (hunderter*100) - (zehner*10)); |
177 | |
178 | |
179 | SegmentNummer(tausender, hunderter, zehner, einer); |
180 | |
181 | |
182 | if( debounce( PINB, PB0 ) ) |
183 | zahl++; |
184 | |
185 | |
186 | |
187 | |
188 | }
|
189 | }
|
Simon S. schrieb: > Es sollen die Zeichen 1-4 auf der Anzeige ausgegeben werden. > Segment 1 = 1 > Segment 2 = 2 > Segment 3 = 3 > Segment 4 = 4 Das hat mich erst ein wenig verwirrt, denn als Segment bezeichnet man die einzelnen Striche des Displays ("7-Segment-Anzeige"). Was Du meinst, sind Stellen oder Digits. Simon S. schrieb: > Es ist deutlich zu erkennen, dass z.b. bei der 7 immer noch die 0 > schwach durchleuchtet. > Wie kann ich das umgehen. Du musst alle Digits erst mal abschalten, bevor Du die Segmente umstellst. Außerdem kann es sein, dass Du nach dem Abschalten noch kurz warten musst, weil die Transistoren nicht sofort abschalten können ("Sperrverzugszeit"). Da reichen aber wenige Mikrosekunden. Zum Beispiel so:
1 | > Display(einer); |
2 | > PORTD &= ~(1<<PD5); //Transistor Seg 1 aus -> Seg = ein |
3 | > PORTD |= (1<<PD4); //Transistor Seg 2 an -> Seg = aus |
4 | > PORTA |= (1<<PA0); //Transistor Seg 3 an -> Seg = aus |
5 | > PORTA |= (1<<PA1); //Transistor Seg 4 an -> Seg = aus |
6 | > _delay_ms(2); |
7 | |
8 | PORTD |= (1<<PD5); // alles aus |
9 | PORTD |= (1<<PD4); |
10 | PORTA |= (1<<PA0); |
11 | PORTA |= (1<<PA1); |
12 | _delay_us(2); |
13 | |
14 | > PORTA = 0b00000000; |
15 | > PORTB = 0b00000000; |
16 | > PORTD = 0b00000000; |
Damit sollte es funktionieren. Noch ein Tipp: Simon S. schrieb: > void Display(int num) > { > switch (num) > { > case 0: > PORTB &= ~(1<<PB1)| (1<<PB2)| (1<<PB3)| (1<<PB4); > PORTD &= ~(1<<PD0)| (1<<PD1)| (1<<PD2)| (1<<PD3);break; > case 1: > PORTB |= (1<<PB1); > PORTB &= ~(1<<PB2)| (1<<PB3)| (1<<PB4); > PORTD |= (1<<PD0); > PORTD &= ~(1<<PD1)| (1<<PD2)| (1<<PD3);break; > case 2: Diese Funktion könnte man deutlich einfacher machen. Statt jedes Segment einzeln zu setzen, kann man das "num" direkt ausgeben, weil Du praktischerweise die Portpins schon passend gewählt hast:
1 | void Display(unsigned char num) |
2 | {
|
3 | PORTB = (PORTB & 0b00001111) | (num & 0b11110000); |
4 | PORTD = (PORTD & 0b00001111) | (num & 0b11110000); |
5 | }
|
Außerdem reicht auch ein "unsigned char" für die Ziffern 0 bis 9. Noch was: Es wird Dir vielleicht auffallen, dass die Tausender-Stelle ein wenig heller ist als die anderen Stellen, oder dass die Stellen kurz flackern, wenn Du die Taste drückst. Das kommt vom Makro "debounce", das immer wieder mal eine Millisekunde wartet. In dieser Zeit wird die Anzeige nicht angesteuert. Deshalb macht man das Multiplexen lieber über Timer-Interrupts. Aber lass es vorerst ruhig mal so, wie es ist, das ist schon ok. Und noch was: Nachdem Du zwei 4543 eingebaut hast, könntest Du zwei Stellen gleichzeitig anzeigen, nämlich die Tausender und die Zehner gleichzeitig, oder die Hunderter und die Einer. Das würde die Helligkeit der Anzeige noch ein wenig erhöhen, weil jede Stelle doppelt so lange eingeschaltet wäre. Ich denke, Dein Ziel hast Du bereits erreicht :-)
hi danke es funktioniert :D jetzt geht es ans fein tuning :D kann man es so einstellen, dass beim impuls die anzeige solange 8888 anzeigt bis der taster wieder losgelassen wird? thx grüße simon
natürlich kann man.
Allerdings: so wie du es jetzt hast, wirst du bald anstehen.
Du musst jetzt den Schritt in Richtung Timer und Timerintererrupt gehen
und das Multiplexing dorthinein verlagern. Die Anzeige muss eigenständig
und ohne weiteres Zutun der Hauptschleife ständig upgedated werden. Auch
die ganzen delays, die du im Multiplexing hast, fallen dann raus.
Bei jedem Aufruf der ISR wird immer nur das nächste Digit eingeschaltet
(Tausender, Hunderter, Zehner, Einer, Tausender, Hunderter, ...) und das
reihum. Jedes Digit leuchtet solange, bis die ISR das nächste mal vom
Timer aufgerufen wird.
Was anzuzeigen ist, holt sich die ISR von globalen Variablen.
Und egal welche Ziffern du dann in diese globalen Variablen
reinschreibst, die ISR zeigt sie an.
Deine Zwischenanzeige ist dann nichts anderes als der Aufruf der
Ausgabefunktion, die die einzelnen Variablen für die ISR befüllt. Mehr
steckt dann nicht mehr dahinter und du kannst zu jedem beliebigen
Zeitpunkt jewde Zahl zur Anzeige bringen.
> jetzt geht es ans fein tuning :D
Noch nicht. Was du hast, ist eine Machbarkeitsstudie, die zeigt dass man
auf deiner Hardware etwas anzeigen kann. Der nächste SChritt ist es
jetzt, aus diesem Hardwaretest etwas Brauchbares und Vernünftiges zu
entwickeln.
Simon S. schrieb: > // Modification for active high push button > > #define debounce( port, pin ) \ > ({ \ > static uint8_t flag = 0; /* new variable on every macro usage */ \ > uint8_t i = 0; \ > \ > if( flag ){ /* check for key release: */ \ > for(;;){ /* loop... */ \ > if( (port & 1<<pin) ){ /* ... until key pressed or ... */ \ > i = 0; /* 0 = bounce */ \ > break; \ > } \ > _delay_us( 98 ); /* * 256 = 25ms */ \ > if( --i == 0 ){ /* ... until key >25ms released */ \ > flag = 0; /* clear press flag */ \ > i = 0; /* 0 = key release debounced */ \ > break; \ > } \ > } \ > }else{ /* else check for key press: */ \ > for(;;){ /* loop ... */ \ > if( !(port & 1<<pin) ){ /* ... until key released or ... */ \ > i = 0; /* 0 = bounce */ \ > break; \ > } \ > _delay_us( 98 ); /* * 256 = 25ms */ \ > if( --i == 0 ){ /* ... until key >25ms pressed */ \ > flag = 1; /* set press flag */ \ > i = 1; /* 1 = key press debounced */ \ > break; \ > } \ > } \ > } \ > i; /* return value of Macro */ \ > }) Das mit dem flackern hab ich wegbekommen indem ich die _delay_us( 98 ) auf _delay_us (1) geändert hab. Es funktioniert -allerdings hab ich die Befürchtung dass es wieder grob fahrlässig war und jetzt irgendwas schieflaufen könnte. >> jetzt geht es ans fein tuning :D >Noch nicht. Was du hast, ist eine Machbarkeitsstudie, die zeigt dass man >auf deiner Hardware etwas anzeigen kann. Der nächste SChritt ist es >jetzt, aus diesem Hardwaretest etwas Brauchbares und Vernünftiges zu >entwickeln. Was verstehst du unter brauchbar bzw vernünftig? Das was es können sollte geht ja schonmal - brauchbar also ja oder?
Simon S. schrieb: > Das mit dem flackern hab ich wegbekommen indem ich die > _delay_us( 98 ) auf > _delay_us (1) geändert hab. > Es funktioniert -allerdings hab ich die Befürchtung dass es wieder grob > fahrlässig war und jetzt irgendwas schieflaufen könnte. Damit hast du leider die gesamte Debounce-Funktion nichtig gemacht. > Was verstehst du unter brauchbar bzw vernünftig? > Das was es können sollte geht ja schonmal - brauchbar also ja oder? Dass es funktioniert, heißt nicht, dass es brauchbar ist. Da du noch in der Hauptfunktion multiplext, kannst du mit dem Controller praktisch nichts Anderes anfangen. Verlagerst du das Multiplexing wie vorgeschlagen in eine ISR, hat dein Controller plötzlich massig Kapazität für weitere Spielereien, u. A. auch, dass während des Tastendrucks 8888 angezeigt wird. Nico
Nico22 schrieb: > Simon S. schrieb: >> Das mit dem flackern hab ich wegbekommen indem ich die >> _delay_us( 98 ) auf >> _delay_us (1) geändert hab. >> Es funktioniert -allerdings hab ich die Befürchtung dass es wieder grob >> fahrlässig war und jetzt irgendwas schieflaufen könnte. > > Damit hast du leider die gesamte Debounce-Funktion nichtig gemacht. > > >> Was verstehst du unter brauchbar bzw vernünftig? >> Das was es können sollte geht ja schonmal - brauchbar also ja oder? > > Dass es funktioniert, heißt nicht, dass es brauchbar ist. Da du noch in > der Hauptfunktion multiplext, kannst du mit dem Controller praktisch > nichts Anderes anfangen. Verlagerst du das Multiplexing wie > vorgeschlagen in eine ISR, hat dein Controller plötzlich massig > Kapazität für weitere Spielereien, u. A. auch, dass während des > Tastendrucks 8888 angezeigt wird. > > Nico Ok das 1. war mir schon fast klar -wäre ja zu schön gewesen. - kannst du mir erklären warum ich es zunichte gemacht hab? - immerhin flackert jetzt ja nichts mehr und bei jedem tastendruck ob kurz oder lang zählt er eins nach oben Dann werd ich mich wohl nochmal in die Sache mit dem ISR einlesen müssen. Ist wie gesagt mein 1. Projekt mit uC und C Programmierung. Vielen Dank schonmal bis hier hat mich schon sehr viel weiter gebracht als ich zu beginn des Freds war.
Simon S. schrieb: > Ok das 1. war mir schon fast klar -wäre ja zu schön gewesen. > - kannst du mir erklären warum ich es zunichte gemacht hab? Weil du damit das debouncing ausgehebelt hast. Das Prinzip des Debouncen ist: Da Taster prellen, muss man sich einen Weg überlegen, wie man einen prellenden Taster von mehreren Tastendrücken unterscheiden kann. Die einfachste und einzigste Möglichkeit ist es, das über die Zeit zu machen. Verändert ein Taster in 1 Millisekunde seinen Wert mehrfach, dann wird das wohl kein Tastendruck vom Benutzer gewesen sein, sondern unerwünschtes Tastenprellen. So schnell kann kein Mensch drücken und loslassen. Verändert ein Taster aber nach einer halben Sekunde seinen Zustand, dann ist das kein Tastenprellen mehr sondern da wird wohl der Benutzer die Taste sehr schnell losgelassen haben. Die Unterscheidung zwischen Prellen und Benutzeraktion erfolgt also durch den Beobachtungszeitraum. Alle Wechsel des Zustands innerhalb dieses Beobachtungszeitraums werden als Prellen gewertet, alle die länger sind, als Benutzeraktion. Machst du den Beobachtunszeitraum aber zu kurz, dann wird plötzlich Prellen als Benutzeraktion gewertet. Und das war ja eigentlich Sinn der Übung, das genau das nicht passiert. > - immerhin flackert jetzt ja nichts mehr und bei jedem tastendruck ob > kurz oder lang zählt er eins nach oben Aber du kannst dein Programm nicht mehr erweitern ohne ständig auf die Anzeige Rücksicht nehmen zu müssen! Eine Holzplatte mit 4 Holzrädern auf Schrauben an den 4 Ecken ist auch eine Plattform die rollen kann und auf der man etwas transportieren kann (solange es nicht zu schwer ist). Aber von dort weg, bis zu einem vernünftigen Transportmittel ist es noch ein weiter Weg. Du hast momentan die Grundplatte mit den 4 Rädern drann. Jetzt geht es darum, daraus eine richtige Transportplattform zu bauen. Und dazu gehört, dass der Benutzer nicht mehr ständig einen Schraubenzieher mit haben muss um die Schrauben neu festzuziehen, sondern dass die Räder auf vernünftige Achsen gesetzt und gelagert werden. Solange dein Programm nicht regelmässig die Werte ausgibt, wird auch die Anzeige nicht aufgebaut. Du hast jetzt 2 Möglichkeiten: Entweder du spickst dein Programm an allen Ecken und Enden mit Aufrufen deiner Ausgabefunktion, oder du baust einen Automatismus, der in regelmässigen Abständen ganz von alleine dein Programm unterbricht und für die Anzeige sorgt. Was wohl wird dir lieber sein? (Hinweis: In der Programmierung ist man gerne 'faul'. Faul in dem Sinne, dass man sich beim Arbeiten an möglichst wenige Dinge erinnern und berücksichtigen muss. Ein geforderter regelmässig Aufruf, den ich selber Programmieren muss, ist etwas an das ich mich erinnern muss) Was du hast, um ein anderes Beispiel zu gebrauchen, ist ein Wecker der zwar morgens um halb 7 klingeln kann und dessen Zeiger sich auch richtig bewegen. Aber du musst händisch das Uhrwerk jede Sekunde betätigen, damit die Uhr auch tickt. Was du brauchst ist ein Uhrwerk, welches das Ticken von alleine macht. > Dann werd ich mich wohl nochmal in die Sache mit dem ISR einlesen > müssen. Darauf läuft es hinaus. Und so schwer ist das nicht.
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.