Hallo Ihr,
Ich hab an meinem Testboard fünf 7-Segment Anzeigen per Multiplexing und
ner selbergeschrieben Funktion dazu gebracht, dass ich ihr ein
5-Stelliges Wort übergebe, und die Funktion das dann in ner while(1)
schleife brav anzeigt.
Dann hab ich da noch fünf Taster, die ich auch super entprellen kann
wenn ich die öfters Abfrag und dazwischen immer 50-120 ms warte und den
drei mal auslesen lass. Der Tater soll nacher bei einmaligem drücken
eine Variable einfach 1 machen oder wenn diese schon 1 ist wieder 0
machen.
Jetzt komm ich in Konflikt, wnn ih die Variable auf der Anzeige anzeigen
lassen will, hab ich ja immer die Pausen, die meine Entprellung braucht
auch auf der Anzeige, das heißt ich hab ein ziemlich doofes Flackern.
Meine Frage, wie kann ich meine Entprellung so gestalten, dass diese in
weniger als drei bis zehn Millisekunden geschieht, denn das sieht man
der Anzeige noch nicht an, weil das ist ja dann eigentlich ziemlich
blöd.
Ich programmiere in C also für jegliche Hilfe bin ich euch sehr Dankbar.
Hans
Du bist in einer Sackgasse.
Es hilft nichts, Du mußt Dich mit Timerinterrupts befassen.
Hier ein Beispiel fürs Entprellen:
Beitrag "Universelle Tastenabfrage"
Und hier fürs Muxen:
Beitrag "ADC mit Multiplexanzeige"
Die Verkopplung mit dem ADC-Interrupt kann man weglassen, wenn man ihn
nicht braucht.
Mit etwas Überlegung kriegt man beides in einen Timer.
Peter
?? Ich versteh da irgendwie nur Bahnof, kannste mir das vielleicht mal
ewas weniger kompliziert erklären, wie so der Grundablauf vom Prorgramm
ist, weil das Programm ist ja immer nur an einer Stelle im Code, und
irgendwo muss ich ja die Pause für die Taster machen oder? weil wenn
ichs jetzt so lass wie ichs hab, dann dafr ich maximal 3ms drücken, um
die Variable einmal u erhöhen bzw zu ändern, alles andere gibt ein
schnelles blinken :(.
Bin für jede Hilfe offen, und versuchs dann in meinem Code zu ändern.
Danke Hans
Kan mir mein Problem niemand lösen? oder mir vllt mal den Grundcode
erklären Programmieren ist dann das kleinere Problem, bin voll in nem
Gedankenloch :(
Deine ganze Gedankenwelt kreist momentan nur um Wartezeiten und
Schleifen. Wie PeDa schon sagte: Das ist eine Sackgasse! Sieht auf den
ersten Blick gut und einfach aus, aber wenn du am Ende der Strasse bist,
merkst du das du so nicht weiter kommst.
Du musst dich mit Timern und Interrupts beschäftigen!
Kurz gefasst: Ein Timer liefert deinem Programm ein regelmässiges Signal
etwas zu tun. Regelmässig kann alle Millisekunden sein und das was zu
tun ist könnte zb sein die momentan erleuchtete Anzeige abzuschalten und
die nächste einzuschalten oder schnell einen kurzen Durchlauf durch die
Tasten zu machen um zu sehen ob eine gedrückt ist.
Dein eigentliches Programm kriegt davon nichts mit. Interrupts laufen
ascynchron zum Hauptfaden deines Programms. Dein eigentliches Programm
wird nur kurz unterbrochen um zwischendurch mal schnell was anderes zu
machen.
50-120ms is schon mal sehr viel. Ich hab noch keine taste länger als
10ms entprellen müssen. Manchmal reicht auch schon 1ms. Ich würde mal
versuchen die Entprellzeit sukzessive runter zu setzen bis Blödsinn
entsteht.
Wenn das nicht reicht würd ich die Multiplexing-Funktion in einen
Timer-Interrupt packen (Falls deine Tasten an einem Interrupt hängen
muss der Timer Interrupt höhere Priorität haben) der zyklisch dein
Programm (auch die Entprellung, was ggf. nur zu einer höheren
Entprellzeit führt) unterbricht und das Display immer zuerst bedient.
#EDIT# Karl heinz war schneller
Aha okay, danke schonmal, dann les ich mir aus dem AVR GCC Tut die Timer
mal durch, und guck b ich das so versteh, nur noch kurz ne Frage, wenn
ich einen Timer in meinem Programm haben will, dann läuft das alles auf
der Software oder? also ich brauch dafür keine Pins an dem Prozessor
dafür, da im Timer Tut sowas davon steht, und das hab ich nicht ganz
verstanden.
Wenn bei mir Fragen auftauchen dann guck ich mal in der SuFu ob ich was
find ansonsten nehm ich diesen Thread.
Grüße Hans
Ein Timer ist eine unabhängige Hardwareeinheit in deinem Prozessor.
Stell dir als Analogie zb deine Armbanduhr vor.
Die habe eine Weckfunktion, so dass sie zu jeder vollen Minute ein
Signal von sich gibt. Und als braver Benutzer kannst du nicht anders als
bei jedem Signal ins Badezimmer zu gehen und nachzusehen ob die Wanne
voll ist.
Jetzt kannst du in Ruhe ein Buch lesen während deine Wanne sich füllt.
Deine Uhr erinnert dich brav jede Minute daran, kurz nachzusehen ob die
Wanne voll ist. Und da du dich dem Signal nicht entziehen kannst, läufst
du auch nicht Gefahr, dass die Wanne überläuft. Obwohl du eigentlich ein
Buch liest.
Jo das Grundprinzip hab ich auch verstanden, und den Code eigentlich
auch, jetzt gibts da ja den tollen Code für eine Uhr, und da ich ja eine
super 7-Segment Anzeige hab will ich auch ausprobieren, aber leider ist
der Code fehlerhaft und da ich mich nochnicht damit beschäftigt hab weiß
ich au net an was es liegen kann, kann mal vllt einer kurz danach
schauen?
1
/*Hinweis: Der Timer ist für die 1Mhz vom interne Takt des ATMEGAs*/
2
#include<avr/io.h>
3
#include<avr/interrupt.h>
4
5
//Variablen für die Zeit
6
volatileunsignedintmillisekunden=0;
7
volatileunsignedintsekunde=0;
8
volatileunsignedintminute=0;
9
volatileunsignedintstunde=0;
10
main()
11
{
12
13
//Timer 0 konfigurieren
14
15
TCCR0=(1<<WGM01)|(1<<CS01);
16
OCR0=125;
17
18
//Compare Interrupt aktivieren
19
TIMSK|=(1<<OCIE0);
20
//Globale Interrupts aktivieren
21
sei();
22
while(1)
23
{
24
/*Hier kann man die aktuelle Zeit ausgeben werden*/
25
}
26
27
}
28
29
30
//Der Compare Interrupt Handler
31
//Wird aufgerufen wenn TCNT0 = 125
32
{ISR(TIMER0_COMP_vect)//### HIER KOMMT DER FEHLER IM COMPILER
33
{
34
millisekunden++;
35
if(millisekunden==1000)
36
{
37
sekunde++;
38
millisekunden=0;
39
if(sekunde==60)
40
{
41
minute++;
42
sekunde=0;
43
}
44
if(minute==60)
45
{
46
stunde++;
47
minute=0;
48
}
49
}
50
}
../Atmega_Testboard.c:946: error: expected identifier or '(' before '{'
token
Danke schonmal, nur das ich weiter lernen kann ;)
Hans
>{ISR(TIMER0_COMP_vect) //### HIER KOMMT DER FEHLER IM COMPILER
Was soll auch die geschweifte Klammer vor "ISR"?
Und genau den Fehler markert dir der Compiler an.
{ISR(TIMER0_COMP_vect)//### HIER KOMMT DER FEHLER IM COMPILER
4
{
Was soll die { vor ISR?
Eine ISR ist für dich als C-Programmierer eine Funktion wie jede andere
auch. Ledglich der Funktionskopf sieht ein klein wenig anders aus.
So jetz tklappt die Uhr und das Programm an sich hab ich jetzt auch
verstanden, nur sind da noch Sachen, die jetzt nicht beschrieben worden
sind und die mich aus der Bahn werfen:
1
TCCR0|=(1<<CS00)|(1<<CS02);
Das ist mir ja klar, hier wird der Timer mit seinen Bits so gesetzt,
dass er jeden 1024sten Takt nur inkrementiert wird, soweit alles klar!
Später im fertign Programm heißt die Timer-Zuweißung dann:
1
TCCR0=(1<<WGM01)|(1<<CS01);
Hier irritiert mich das WGM01, es ist nicht gesat worden was das ist,
und oben steht ja immer nur CS00 CS01 oder CS02, für die
initialisierung.
Zu guter letzt, steht da noch das:
1
OCR0=125;
Für was genau steht das? Es wird hier ein Wert gesetzt, der dann später
in der Funktion gebraucht wird, um den Zeipunkt der Ausführung zu
setzen, oder wie darf ich das verstehen?
Ich bin sehr wissenshungrig, und will das alles lernen drum frag ich
jetzt euch mal ihr kennt euch da ja richtig aus ;)
Hans
WGM steht für Waveform-Generation-Mode
OCR0 steht für Output-Compare-Register-Timer0
Das sind ein paar Funktionen die ein AVR-Timer noch mit sich bringt.
Antworten darauf findest du mit STRG+F im Datenblatt deines µC
in deinem geposteten Code kann ich TCCR0 |= (1<<CS00)|(1<<CS02);
nirgends entdecken.
Jo die letzte Zeile steht in dem Tutorial, bei der Timerinitialisierung,
und ich hab gedacht das geht dann nacher im Program auch nur mit der
Zeile und nicht mit dem WGM, da ich ja nicht weiß für was das genau
steht, und was das WGM steht.
Danke für den Rest,ist immer besser wenn man weiß für was die Sachen
stehn, dann kann man(n) sich das besser merken ;)
Hab mich jetzt nach einiger Zeit auch bei euch angemeldet, da ich
vermute das ich bei euch bleiben werde ;) macht echt Spaß bei euch und
das große Tut find ich spitze!
Euer Hans_angemeldet
Hab jetzt mal etwas herrumprobiert und hab festgestellt, dass sich die
Taster über nen Interrupt viel besser auswerten lassen, aber ich muss
dazusagen, dass der Timer ja parallel zum Programm läuft, aber der
Zeitpunkt nach dem Overflow wird dann ja im Programm ausgeführt.
Also darf meine Interrupt-Funktion nicht allzu lang sein oder seh ich da
was flasch?
Schöne Pfingsten Noch
Hans
Dennis G. schrieb:
> Hab jetzt mal etwas herrumprobiert und hab festgestellt, dass sich die> Taster über nen Interrupt viel besser auswerten lassen, aber ich muss> dazusagen, dass der Timer ja parallel zum Programm läuft, aber der> Zeitpunkt nach dem Overflow wird dann ja im Programm ausgeführt.> Also darf meine Interrupt-Funktion nicht allzu lang sein oder seh ich da> was flasch?
Das siehst du schon richtig.
Wenn du dir allerdings mal ausrechnest (oder überschlägig abschätzt),
wieviel Rechenzeit prozentual in der ISR draufgeht, dann merkst du: Das
sind wenige Prozente, wenn überhaupt.
Trotzdem sollten ISR kurz gehalten werden. Während eine ISR läuft wird
keine andere ISR abgearbeitet. Immer nur nacheinander. Wenn du also
jeder ISR die Chance geben willst möglichst schnell nach Auftreten des
zugehörigen Ereignisses gestartet zu werden, dann ist die Devise: Fasse
dich kurz.
Kleinere Berechnungen sind in einer ISR ok. Sobald es aber länger wird,
oder gar Ausgaben gemacht werden, dann sieht ein bewährter
Programmaufbau so aus
1
volatileuint8_tupdateDisplay;
2
3
ISR(...)
4
{
5
millisek++;
6
if(millisek==1000){
7
millisek=0;
8
9
sek++;
10
if(sek.....
11
...
12
13
updateDisplay=1;
14
}
15
}
16
17
intmain()
18
{
19
....
20
21
updateDisplay=0;
22
23
while(1){
24
25
....
26
27
if(updateDisplay)
28
{
29
updateDisplay=0;
30
31
// mache die Ausgabe
32
}
33
}
34
}
die ISR 'benachrichtigt' die Hauptschleife in main, dass es am Display
etwas zu tun gibt. Sowas nennt man Jobflags: Ist das Flag gesetzt, gibt
es einen Job abzuarbeiten.
Hallo wieder einmal,
Ich hab jetzt wieder etwas herumprobiert, und hab jetzt meine Taster nur
noch über die auslesen lassen wollen, und dann die Flags setzen, sodass
die while(1)-Schlaufe das dann auswerten kann.
so jetzt zum Code:
1
ISR(TIMER0_COMP_vect)
2
{
3
4
if(!(PINB&(1<<PB0)))
5
{
6
Taster_one=1;//Global angelegt
7
interrupt_wait=500;//Global angelegt
8
}
9
}
10
11
//Main
12
//
13
intmain(void)
14
{
15
16
Init();
17
18
//Timer 0 konfigurieren
19
//
20
TCCR0=(1<<WGM01)|(1<<CS01);
21
OCR0=125;
22
23
//Compare Interrupt aktivieren
24
TIMSK|=(1<<OCIE0);
25
//Globale Interrupts aktivieren
26
sei();
27
28
29
while(1)//Mainloop
30
{
31
32
DisplayText(H,E,L,L,O);//Funktion, die ich geschrieben
33
//hab, wird ordungsgemäs angezeigt ;)
34
35
36
if(Taster_one>0)
37
{
38
GreenLED(ON);
39
RedLED(OFF);
40
}
41
else
42
{
43
RedLED(ON);
44
GreenLED(OFF);
45
}
46
}
47
48
return(0);//wird nie erreicht
49
}
Das Problem liegt einach darin, der Code geht zwar, aber der Taster wird
nicht ausgewertet, also Taster_one wird nicht 1 wenn der Code von ISR in
der Main-Loop stht, dann gehts :(
Quizfrage was ist falsch ;) :D ich kanns net herrausfinde
grüßle Hans