Hallo, ich arbeite zum ersten Mal mit einem Mikrocontroller und zum ersten Mal mit AVR. Mein Controller ist ein attiny2313 und ich will eine Binäruhr bauen. Ich habe mir alles so zusammengebaut, dass ich die LEDs (jeweils 6 für Stunde, Minute und Sekunde) einzeln ansteuern kann. Die Idee hinter meinem Programm ist auch soweit fertig, ich weiß nur nicht, wie ich eine Schleife so programmiere, dass sie eine Sekunde lang ausgeführt wird. Ich habe mir schon viel Kram durchgelesen über Timer0 und Timer1 und auch das AVR-Tutorial über Uhren, aber ich werde nicht schlau daraus... Ich muss also möglichst konkret wissen, wie ich eine Schleife so programmiere, dass der Controller sie eine Sekunde lang immer wieder im Loop ausführt und danach mit dem restlichen Code fortfährt. Danke schon mal im Vorraus!
Das hört sich nach einem Designfehler an. An sich ist eine Schleife, die eine Sekunde lang ausgeführt wird in einer solchen Uhr garnicht notwendig. Vielleicht beschreibst Du mal im grösseren Zusammenhang wozu solch eine zeitbegrenzte Schleife Deiner Ansicht nach notwendig ist. Lies mal http://www.mikrocontroller.net/articles/AVR-Tutorial:_Uhr Um Dir weiter zu helfen, müsstest Du schon genau schreiben was Du nicht verstehst, denn eine globale Erklärung, die potentiell alle Deine Verständnismängel, die wir dazu garnicht kennen, behebt, ist garnicht möglich.
Danke für die schnelle Antwort! Das Problem ist, dass ich mit meinem Aufbau nicht ohne Weiteres mehrere LEDs gleichzeitig einschalten kann. Ich brauche die Schleife, damit eine Sekunde lang alle zu dem Zeitpunkt gewollten Lampen abwechselnd an- und aus geschaltet werden.
Diemo G. schrieb: > Das Problem ist, dass ich mit meinem Aufbau nicht ohne Weiteres mehrere > LEDs gleichzeitig einschalten kann. Aha. Wie ist denn Dein Aufbau? Poste mal den Schaltplan. Hört sich nach Multiplexing oder Schieberegister an. > Ich brauche die Schleife, damit eine > Sekunde lang alle zu dem Zeitpunkt gewollten Lampen abwechselnd an- und > aus geschaltet werden. An sich ergibt sich der Zeittakt für eine Änderung des LED-Zustandes (Lampe oder LED?) aus dem der Uhr selbst. Eine besondere Vorkehrung für einen Sekundentakt ist also garnicht notwendig. Also, immer wenn sich die Sekunde ändert, dann muss der LED-Zustand geändert werden. Da Du aber oben schreibst, das Du nicht mehrere LEDs gleichzeitig schalten kannst und damit Multiplexing (oder ein Schieberegister) suggerierst, wird überlicherweise ein noch schnellerer Takt benutzt um innerhalb der Sekunde die LEDs kurz anzuschalten bzw. den aktuellen Zustand in Schieberegister zu schieben. Aber wiegesagt. Dazu sind nähere Erklärungen und ein Schaltplan notwendig.
Dein Ansatz mit der Schleife ist schlecht. Timer ist schon ein gutes Stichwort. Was macht ein Timer? Er zählt. Hört sich jetzt banal an. Aber so ein Timer zählt einfach nur vor sich hin und zwar, und das ist das entscheidende, völlig regelmässig. An deinem µC hast du einen Quarz, der schwingt. Und zwar auch regelmässig. Zb. mit 4Mhz. Wenn du nun den Quarz mit dem Timer koppelst, dann wird dein Timer ebenfalls regelmässig zählen. Und zwar auch mit 4Mhz. Oder in anderen Worten: Wenn man den Timer einfach vor sich hinzählen lassen würde, dann würde er in 1 Sekunde genau bis 4 Millionen kommen. Nun gehts das aber nicht. Der Timer kann nicht bis 4 Millionen zählen. Nehmen wir den Timer 1. Das ist ein 16 Bit Timer. Der kann daher nur bis 65535 zählen. Hat er 65536 erreicht, dann beginnt er wieder bei 0. Das ist technologisch bedingt, weil der Timer nun mal nicht mehr als 16 Bit hat. Stört uns aber nicht weiter. Rechnen wir doch mal in die andere Richtung. Wenn der Timer in 1 Sekunde bis 4 Millionen zählen würde, es aber nicht kann, weil er bei 65535 (also nach jeweils 65536 Zählvorgängen) wieder bei 0 anfangen muss, wie lange dauert es dann, bis er einmal bis 65535 kommt. 1 Sekunde ............... 4000000 x ............... 65536 -------------------------------------- 1 * 65536 x = ------------- = 0.016384 Sekunden 4000000 Wenn du deine Uhr daher nicht auf Sekunden als Basiseinheit, sondern auf diesen 0.016384 Sekunden aufbaust, dann gibt dir der Timer einen schön regelmässigen Takt vor. Du musst dann nur noch mitzählen, wie oft dieses Ereignis (Zähler ist übergelaufen) auftritt. Wie kann man so etwas machen? Nun. Ein Timer der nur vor sich hinzählt ist eher nutzlos. Interessant wird die Geschichte nur dadurch, dass du den Timer dazu bringen kannst, bei bestimmten Zählerständen irgendwelche Dinge auszulösen. Ein solcher Zählerstand, ein Ereignis, ist zb genau dieser Overflow, wenn der Timer von 65535 zurück auf 0 springt. Man kann sich dann die Dinge so einrichten, dass bei diesem Ereignis eine ganz bestimmte Funktion automatisch aufgerufen wird, eine sogenannte ISR (Interrupt Service Routine). In diesem Fall ist es die ISR die für den Timer Overflow zuständig ist. Jetzt können wir uns fragen: Na, wie oft wird denn die ISR in 1 Sekunde aufgerufen? Und die Antwort ist einfach. Wie wissen, dass der Overflow alle 0.016384 Sekunden kommt, die ISR wird daher in 1 Sekunde 61.035 mal aufgerufen. Leider ist das keine ganze Zahl (aber das sei jetzt erst einmal nebensächlich). Wenn man also in der ISR eine globale Variable als Zähler hat, die bei jedem Aufruf ganz einfach um 1 hochgezählt wird und danach überprüft ob die Variable 61 geworden ist, dann weiss man, dass dieser Fall eintritt, wenn ~1 Sekunde vergangen ist. Hat man das festgestellt, dann erhöht man die Uhr um 1 Sekunde, setzt die Zählvariable wieder auf 0. Beim nächsten ISR Aufruf zählt die wieder um 1 hoch (1), beim nächsten wieder (2), usw. usw. bis nach 1 Sekunde wieder ein Stand von 61 erreicht ist und man darauf reagiert. Und jetzt geb ich dich ab ans AVR-GCC-Tutorial bzw. das AVR-Tutorial. All das findest du nämlich dort auch wieder. Timer, Interrupts und was es rundherum noch so alles zu sagen und zu erzählen gibt.
Diemo G. schrieb: > Danke für die schnelle Antwort! > Das Problem ist, dass ich mit meinem Aufbau nicht ohne Weiteres mehrere > LEDs gleichzeitig einschalten kann. Ich brauche die Schleife, damit eine > Sekunde lang alle zu dem Zeitpunkt gewollten Lampen abwechselnd an- und > aus geschaltet werden. Ui. Du hast dir Multiplexing ausgesucht. Dann hast du dir einen großen Brocken vorgenommen. Übelicherweise kommt man mit Multiplexing nicht vor 4 Wochen Erfahrung sammeln in der µC-Programmierung in Berührung. Und das ist auch gut so. Lerne zuerst zu gehen, ehe du laufen willst. Fang klein an, so wie alle anderen auch.
Ja, das ist Multiplexing und ich habe keinen Schaltplan, würde mich aber über ein geeignetes Programm freuen, um einen zu machen. Der Timer, den ich möchte, soll den Sekundentakt überhaupt erst bestimmen. Ich habe bisher erst geschrieben, dass immer nach der Schleife, für die ich noch keine Abbruchbedingung habe, die eine Sekunde lang gehen soll, die Sekundenzahl um 1 erhöht wird und ggf. die Minuten usw. Dann wird noch übersetzt, welche LEDs beim nächsten Durchlauf leuchten müssen, damit z.B. bei Sekunde 9 die LEDs 1 und 8 für Sekunden leuchten. Danach soll wieder die Schleife ausgeführt werden, die eine Sekunde lang die beiden LEDs an- und ausschaltet.
Karl heinz Buchegger schrieb: > Diemo G. schrieb: >> Danke für die schnelle Antwort! >> Das Problem ist, dass ich mit meinem Aufbau nicht ohne Weiteres mehrere >> LEDs gleichzeitig einschalten kann. Ich brauche die Schleife, damit eine >> Sekunde lang alle zu dem Zeitpunkt gewollten Lampen abwechselnd an- und >> aus geschaltet werden. > > Ui. > Du hast dir Multiplexing ausgesucht. > Dann hast du dir einen großen Brocken vorgenommen. Übelicherweise kommt > man mit Multiplexing nicht vor 4 Wochen Erfahrung sammeln in der > µC-Programmierung in Berührung. Und das ist auch gut so. > > Lerne zuerst zu gehen, ehe du laufen willst. > Fang klein an, so wie alle anderen auch. Das ist sehr traurig für mich, aber der Timer ist halt die letzte Hürde, vor der ich stehe. Kann der wirklich so viele Probleme machen?
Diemo G. schrieb: > Ja, das ist Multiplexing und ich habe keinen Schaltplan, würde mich aber > über ein geeignetes Programm freuen, um einen zu machen. > Der Timer, den ich möchte, soll den Sekundentakt überhaupt erst > bestimmen. Ich habe bisher erst geschrieben, dass immer nach der > Schleife, für die ich noch keine Abbruchbedingung habe, die eine Sekunde > lang gehen soll Nochmal Das ist der falsche Ansatz. So wird das nichts. Überhaupt dann nicht, wenn da aich noch Multiplexing mit im Spiel ist. Du kannst es drehen und wenden wie du willst: Du wirst die Grundlagen lernen müssen! Und eine der Grundlagen für Multiplexing und Uhr ist nun mal das man einen Timer einigermassen sicher benutzen kann.
Diemo G. schrieb: > Ja, das ist Multiplexing und ich habe keinen Schaltplan, würde mich aber > über ein geeignetes Programm freuen, um einen zu machen. Eagle, Ascii-Circuit, für die Leute mit künstlerischer Veranlagung auch Paint, Photoshop... Oder ganz oldschool: Ein Blatt Papier, dann einen Stift(Blei-),malen und einscannen/abfotografieren. :-) Und neben dem Schalplan zeigste uns dann auch mal dein Programm, dann kann man dir gezielt helfen. :-)
Versuch hier mal in den Tutorien, die einfachen Timeraufgaben zu realisieren. Dann siehst Du schon wie es läuft. Für Deine Uhr: Du musst gedanklich immer von dem schnellsten Takt in Deiner Uhr ausgehen. In diesem Takt musst Du die am häufigsten auftretende Aktion ausführen. Das ist der Takt mit dem die LEDs gemultiplext werden. Stell Dir vor, Du hättest Die Aufgabe eine Uhr von Hand zu bedienen, also den Sekundenzeiger, den Minutenzeiger selbst vorzurücken. Dazu hast Du ein Metronom, das alle Sekunde klackt. Du würdest also bei jedem Klack, den Sekundenzeiger um einen Strich weiterrücken und wenn Du ihn auf Null vorgerückt hast, sofort den Minutenzeiger um eins vorrücken. Genauso läuft es mit dem Multiplexing, nur ein wenig schneller. Du musst z.B. alle 10ms jeweils die LEDs einschalten, die leuchten sollen, was gerade von der aktuellen Uhrzeit abhängt. Aber während Du das tust, ändert sich die Uhrzeit nicht. Wenn Du das 100 Mal getan hast, ist genau eine Sekunde vergangen.
Danke an alle, ich werde mich nun intensiver damit beschäftigen, aber eine Frage habe ich noch zu dem >Zitat von Grrrr: >Aber während Du das tust, ändert sich die Uhrzeit nicht." Kann ich nicht herausfinden, wie lange er für die Berechnung der LEDs braucht und in Abhängigkeit davon einen Abbruchbedingung machen? Das wäre ja dann indirekt auch ein Timer.
NEIN. Nimm einfach 2 Timer Den ersten stellst du auf 1sekunde, in dessen Interrupt Routine wird einfach die Sekunden nach den Regeln der Uhr erhöht. Den zweiten stellst du z.b. auf 1kHz und mit dem machst du das Multiplexing. Fertig.
Diemo G. schrieb: > Das ist sehr traurig für mich, aber der Timer ist halt die letzte Hürde, > vor der ich stehe. Kann der wirklich so viele Probleme machen? Der Timer nicht. Aber du musst jetzt 2 Dinge gleichzeitig unter 1 Hut bringen. Wenns nicht funktioniert, woher weißt du welcher Teil nicht funktioniert?
Diemo G. schrieb: > Kann ich nicht herausfinden, wie lange er für die Berechnung der LEDs > braucht und in Abhängigkeit davon einen Abbruchbedingung machen? Das > wäre ja dann indirekt auch ein Timer. Theoretisch ja. Soweit ist Deine Überlegung folgerichtig und sie würde funktionieren. Das würde man allenfalls in einem Multimilliarden-Dollar-Projekt machen, wenn alle Platinen soweit fertig sind und morgen der Abgabetermin ist und eben irgendwie verpennt wurde, das "richtig" zu machen und ein uC ohne Timer gewählt wurde. In der "Praxis" würde man das nie so machen. Falls Du das erste und letzte Mal in Deinem Leben einen uC programmierst, dann mach es so, weil es dann keine Rolle spielt. Aber Du lernst eben nichts praktisch relevantes dabei. Vergiss das mit der Schleife und der Abbruchbedingung. Du scheinst irgendwie darauf fixiert zu sein, die Sekunden mit einer Schleife abzumessen. Aber nimm einmal an, Du müsstest in einem späteren Projekt noch einen Alarm einbauen oder willst eine Maus auf dem Display tanzen lassen, ein MP3 abspielen etcpp. Jede Änderung an dem Zeitablauf würde ein neues bestimmen der Verzögerungszeit bedeuten. Und, noch viel schwerwiegender, falls Du Bedingungen in dem Code hast, wäre die Laufzeit evtl. nicht konstant, bzw. Du müsstest aufwendige Maßnahmen treffen um die Laufzeit konstant zu kriegen. Deine Idee funktioniert ungefähr so gut, wie der Versuch ein Auto an einer Mauer anzuhalten. Es geht, aber es ist absolut nicht empfehlenswert. ;-)
Diemo G. schrieb: > Kann ich nicht herausfinden, wie lange er für die Berechnung der LEDs > braucht und in Abhängigkeit davon einen Abbruchbedingung machen? Das > wäre ja dann indirekt auch ein Timer. Glaub es. Deine Idee mit der Messung der Ausführungszeit ist zwar in der Theorie machbar, in der Paxis aber völlig untauglich. Dazu musst du alle Pfade, die dein Programm nehmen kann berücksichtigen und von jeder Anweisung die Taktzyklen zählen und die aneinander angleichen. Und bei der geringsten Programmänderung geht alles wieder von vorne los. Ja schon die nächste Compilerversion kann dir alles durcheinanderwerfen. Du brauchst einen Taktgeber, der unabhängig von deinem Programm einen reproduzierbar exakten Basistakt zur Verfügung stellt. Ein Timer ist so eine Komponente, sie wurde extra dafür gebaut. Eine Schleife ist das nicht. Selbst dann, wenn du einen Timer benutzt, wird deine Uhr nicht auf Anhieb angemessen genau gehen, selbst wenn du dich mittels Timer an jede einzelne Quarzschwingung klemmst. Denn, Überraschung: Dein (Hausnummer) 4Mhz Quarz macht keine 4000000 Schwingungen in der Sekunde. Der macht vielleicht ein paar 100 Hz mehr oder weniger. Zu allem Überdruss auch noch abhängig von der Temperatur. Wir reden hier von einer Uhr! Selbst kleinste Abweichungen im µSekunden Bereich summieren sich bei Laufzeiten von Wochen und Monaten zu beträchtlichen Minuten und Stundenzahlen auf!
Stefan schrieb: > NEIN. > > Nimm einfach 2 Timer > > Den ersten stellst du auf 1sekunde, in dessen Interrupt Routine wird > einfach die Sekunden nach den Regeln der Uhr erhöht. > > Den zweiten stellst du z.b. auf 1kHz und mit dem machst du das > Multiplexing. Für ihn ist das eine gute Strategie, auch wenn sich mir die Haare ein wenig sträuben, 2 Timer zu benutzen, wo's 1 auch tut. Aber, wie heißt es so schön: Für nicht benutzte Komponenten bekommt man von Atmel kein Geld zurück. Wenn der µC einen oder mehrere Timer hat, kann man die auch ruhig benutzen.
Grrrr schrieb: > Siehst Du! Sogar Karl-Heinz sagt so. ;-) Kunststück :-) Das ist so klar wie Klossbrühe, das das mit einer Schleife nichts werden kann. Er sträubt sich doch nur gegen Timer, weil das schon wieder etwas Neues ist und er sich das Ganze eigentlich viel einfacher vorgestellt hat. Was er noch nicht weiß: Bei Timern geht es hauptsächlich um Konzepte und Verständnis. Hat man das erst einmal, ist die Implementierung ein Kinderspiel. Viel einfacher als Schleifen.
Takte deinen Controller mit einem Uhrenquartz 32768 Hz. Teile die 32768 durch 256, ergibt 128. Also setze eine geschachtelte Schleife ein, die heruntrer zählt: Start: loop1: ld r8,128 loop2: dec r7 jnz loop2 dec r8 jnz loop1 ;; wenn hier angekommen, mach das, was alle sec gemacht werden soll. Das Beispiel geht davon aus, dass alle Befehle in einem Microzyklus ausgeführt werden. Mangels Datasheet kann es hier Abweichungen geben. Das muss dann in die Startwerte von r7 einfliessen. Gruss Robert
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.