Hallo, ich habe folgendes Problem: Von der Main-While-Schleife wird immer eine Funktion aufgerufen welche Ports steuert und dabei immer wieder einen Taster-Zustand abfragt. Wenn der Taster gedrückt ist zählt eine Vatiable hoch (statisch). Beim ersten "Impuls" (Variable von 0 auf 1) wird ein Delay von 100ms ausgeführt um eine Fehlinterpretation vom Prellen zu unterbinden. Beim loslassen des Tasters wird ebenfalls ein Delay von 100ms ausgeführt. ...schon klar, 100ms sind viel, aber diese Funktion ist nicht zeitkritisch. Bei einem lange Druck der Taste (z.B. 2 Sekunden) soll eine andere Aktion ausgeführt werden (deswegen die hochzählende Variable). Wie kann ich nun ausrechnen, nach wievielen Funktionsaufrufen die Zeit erreicht ist? Ich kenne die Frequenz, aber wieviele Takte nötig sind um die Funktion abzuarbeiten weiß ich nicht. Wie kann man sowas errechnen?
sowas lässt sich mit delays nicht vernünftig lösen. Nutze Timer, dann hst du keine Probleme mit deinen Funktionen.
Vielen Dank, ich habe gerade mal das mit den Timern überflogen. Das scheint perfekt für meine Anwendung zu sein. Auch vielen Dank für die Tastenentprellung, aber ich schau erst mal ob das mit den 100ms ausreichend ist, dann spare ich eine Menge Code (so üppig ist der Speicher des ATtiny2313 ja nicht). Sollte das nicht klappen komme ich darauf zurück. Da ich das für eine Projektarbeit brauche würde ich gerne so viel wie möglich selber schreiben, ansonsten habe ich ein Mords-Quellenangabe-Verzeichnis, was nicht unbedingt gut ankommt. Ob ich einen Code selber geschrieben habe, oder ob der von jemand anderes stammt wird ein erfahrener Prüfer sofort sehen (Programmier-Stil). Ich werde meinen Code sicher nicht so perfekt hin bekommen, wie er hier verfügbar ist, aber wenn er funktioniert (und ich am Ende alles auf den ATtiny bekomme) sollte das ganz gut ankommen. Die Timer scheinen auch von der Performance her gut zu sein, weil das ja parallel Hardware-Seitig mitläuft. Code spart man damit allemal. Vielen Dank :-)
- Zustandsautomat - Handling mit Flag-Variablen - je nach dem wie ausgelastet dein AVR ist kann man sonst auch auf eine millis() Funktion wie beim Arduino zurückgreifen (basierend auf einem Timer): https://github.com/zkemble/millis
Christian R. schrieb: > Wie kann ich nun ausrechnen, nach wievielen Funktionsaufrufen die Zeit > erreicht ist? Einen Zahler hochzählen wenn die Taste gedrückt wird Selbigen auf 0 stellen wenn Sie losgelassen wurde Den delay an das Ende der Schleife legen Dann kannst du die unterschiedlichsten Aktionen je nach Zählerstand ausführen Der Delay kann auch beleibig klein werden (dann werden halt der Zählerwerte größer)
Christian R. schrieb: > Auch vielen Dank für die Tastenentprellung, aber ich schau erst mal ob > das mit den 100ms ausreichend ist, dann spare ich eine Menge Code Da habe ich so meine Zweifel. Ich optimiere meinen Code recht gut.
Peter D. schrieb: > Ich optimiere meinen Code recht gut. Das würde ich für den konkreten Fall der Tastenentprellung bedenkenlos unterschreiben. Da ist alles optimiert, was man unter C optimieren kann. Aber ganz sicher würde das nicht für den allgemeinen Fall deiner Codes unterschreiben...
Irgendwie komme ich nicht weiter. Ich habe eine Funktion welche immer wieder aufgerufen wird und einen übermittelten Wert auf 2 7-Segment-Anzeigen anzeigt. Nun habe ich zum Testen, ob das mit dem Timer klappt einfach mal folgendes versucht:
1 | // Interrups
|
2 | TCCR1A = ((1<<CS00) | (1<<CS02)); // Counter aktivieren mit einem Prescaler von 1024 |
3 | |
4 | while (1) |
5 | {
|
6 | if (TCNT1 > 21600) zeigeZeichen(22); |
7 | else zeigeZeichen(11); |
8 | }
|
9 | return; |
Da der Timer 16 Bit hat und ich mit einer Frequenz von 11.059200 MHz takte sollten doch eigentlich 2 Sekunden lang eine "11" angezeuigt werden, danach für ca. 4 Sekunden eine "22" und dann wieder von vorne beginnend mit der "11" (sofern der Counter wieder bei 0 anfägt). Es wird aber lediglich die 11 angezeigt und die 22 erscheint niemals. Was mache ich da falsch? Ich möchte eigentlich nur den Timer lesen (und ggf. auf 0 setzen) können, ohne dass ein Interrupt ausgelöst wird. Alle Pins sind anderweitig belegt und ein Interrupt wäre da störend. Was mache ich falsch?
> TCCR1A = ((1<<CS00) | (1<<CS02));
Fehler: Die Bits CS00 und CS02 befinden sich im Register TCCR1B!
JAAAAAA :-) Genau das war es, nun kappt´s wie es soll. Vielen Dank :-)
Peter D. schrieb: > Christian R. schrieb: >> Auch vielen Dank für die Tastenentprellung, aber ich schau erst mal ob >> das mit den 100ms ausreichend ist, dann spare ich eine Menge Code > > Da habe ich so meine Zweifel. Ich optimiere meinen Code recht gut. Du hast zu Recht gezweifelt. Die 100ms merkte man doch stark, indem die 7-Segment-Anzeige verzögert ein-/ausgeschaltet wurde. Das wäre eigentlich nicht so tragisch, aber da die beiden Anzeigen abwechselnd angesteuert werden sah es schon merkwürdig aus, wenn erst eine ausgeht und 0,1s später die andere. Wenn ich mit der Zeit runter gegangen bin wurde der optische Aspekt besser, aber dafür kam es zu Fehler (prellen). Nun habe ich eine ganz simple Lösung gefunden. Das geht zum einen so schnell, dass man optisch keine Verzögerung in den Anzeigen mehr sehen kann und zum anderen ist es auch noch zuverlässiger. Ich habe einfach sowohl beim Betätigen, wie auch beim Loslassen des Tasters eine Schleife laufen lassen, welche so lange läuft bis 250 Zyklen der gleiche Wert stehen bleibt. Wenn ein Taster nun also lange prellt läuft die Schleife etwas länger, wenn ein Taster gar nicht prellt läuft die Schleife 250 durchläufe, was bei 11,059200 MHz ungefähr 23ms sind. Hier ist meine "Not-Lösung", welche jedoch erstaunlich gut funktioniert.
1 | for (uint8_t i=250; i; i--) { |
2 | if (PIND & 0x08) i = 250; |
3 | }
|
Beim Loslassen habe ich halt
1 | if (!(PIND & 0x08)) |
benutzt (das ! davor). Ich habe den Taster (Billist-Ware aus China) nun bestimmt 50x betätigt, dabei hatte ich kein einzigen Tastenpreller :-)
Christian R. schrieb: > wenn ein Taster gar nicht prellt läuft die Schleife 250 durchläufe, was > bei 11,059200 MHz ungefähr 23ms sind. Sicher? Das wären ja ca. 1000 Takte pro Schleifendurchlauf - kann ich mir bei so einer simplen Schleife irgendwie nicht vorstellen.
Habe ich falsch gerechnet? 11.059200 MHz / 1024 (Teiler) = 10800 Takte pro Sekunde 250 Durchläufe / 10800 = 0,02315 --> 23 ms
Oh, da ist ja der Fehler... Ich hatte kurz vorher noch mit dem Timer gerechnet, deshalb war ich immer noch bei dem Prescaler von 1024. Das ist hier aber eine "normale" Schleife, und somit: 11059200 Takte / Sekunde (und nicht 10800) Somit: 250 / 11059200 = 22,6 µs Nun bin ich doch sehr verwundert, dass die Tastenentprellung so überhaupt funktioniert. ...egal es funktioniert und das sogar "Sau schnell" ;-) Wenn ich mal einen Taster habe der vielleicht länger prellt, dann müsste ich auf einen 16 Bit Integer ausweichen und ein paar µs dazu geben.
Christian R. schrieb: > Die 100ms merkte man doch stark, indem die 7-Segment-Anzeige verzögert > ein-/ausgeschaltet wurde. Nun, das Multiplexen von Anzeigen macht man ja auch nicht in der Mainloop, sondern im Timerinterrupt. Da kann man dann auch gleich das Entprellen mit aufrufen.
Peter D. schrieb: > Nun, das Multiplexen von Anzeigen macht man ja auch nicht in der > Mainloop, sondern im Timerinterrupt. Normalerweise mache ich so viel wie möglich in der Main-Loop. Interrupts sollen im Idealfall nur Ereignisse zählen, Flags setzen oder Buffer übertragen. Bei gemultiplexten Anzeigen stimme ich Dir jedoch zu, die flackern sonst nämlich sichtbar und das sieht einfach sch*** aus.
Christian R. schrieb: > 11059200 Takte / Sekunde (und nicht 10800) > Somit: > 250 / 11059200 = 22,6 µs Diese Rechnung stimmt aber auch nicht, denn der Controller braucht sicher mehr, als nur einen Takt pro Schleifendurchlauf! Wie hast Du denn festgestellt, daß die Entprellung funktioniert? Wenn Deine Anzeige bei gedrückter Taste etwas anderes anzeigt, als bei losgelassener Taste, heißt das ja noch lange nicht, daß sie ggf. beim Umschalten nicht ein paar mal hin- und her gesprungen ist. Das Auge ist ja recht träge...
:
Bearbeitet durch User
Stefanus F. schrieb: > Bei gemultiplexten Anzeigen stimme ich Dir jedoch zu, die flackern sonst > nämlich sichtbar und das sieht einfach sch*** aus. Ich habe das Multiplexen in einer Funktion, welche ich aus der Main heraus aufrufe. Da ist keiene Spur von Flackern zu sehen, alles sehr homogen. Thomas E. schrieb: > Christian R. schrieb: >> 11059200 Takte / Sekunde (und nicht 10800) >> Somit: >> 250 / 11059200 = 22,6 µs > > Diese Rechnung stimmt aber auch nicht, denn der Controller braucht > sicher mehr, als nur einen Takt pro Schleifendurchlauf! > > Wie hast Du denn festgestellt, daß die Entprellung funktioniert? Wenn > Deine Anzeige bei gedrückter Taste etwas anderes anzeigt, als bei > losgelassener Taste, heißt das ja noch lange nicht, daß sie ggf. beim > Umschalten nicht ein paar mal hin- und her gesprungen ist. Das Auge ist > ja recht träge... Stimmt, die Schleife braucht auch etwas. Mit dem Tastendruck habe ich die Anzeige aus-/eingeschaltet. Vorher (mit prellen) flackerte diese beim drücken öfters uns blieb dann an oder aus. Die hat halt nich einmal aus- oder eingeschaltet, sondern x mal und ist dann irgendwo stehen geblieben (an oder aus). Nun habe ich den Taster ca. 50 mal betätigt und ich hatte weder Flackern, noch einen Fehlerhaften wechsel (an <--> aus). Ich bin noch ein blutiger Anfänger, was die Programmierung von µC betrifft, somit bin ich für jeden Tipp (und auch konstruktive Kritik) dankbar.
:
Bearbeitet durch User
Christian R. schrieb: > Ich habe das Multiplexen in einer Funktion, welche ich aus der Main > heraus aufrufe. > Da ist keiene Spur von Flackern zu sehen, alles sehr homogen. Dann hast du wahrscheinlich das Glück, dass jeder Durchlauf der Hauptschleife ungefähr gleich lange dauert.
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.