Hallo Ich habe mich wieder an einem Programm versucht. Folgendes bisher habe ich Zeitverzögerungen immer mit hilfe des Timer0 gelöst, das möchte ich auch so beibehalten, da es einfach sehr gut funktioniert. Nun wollte ich noch eine Uhr erweitern, sprich - das wichtigste, den Sekundentakt. Am einfachsten geht das über den Timer1, da 16BIT. Problem ist nur, der Timer1 läuft mit den selben Einstellungen wie Timer0, also, selber Overflow-Schwellwert?!? Habe ich da wieder was durcheinander gebracht? Die eigentliche Funktion, raufzählen etc, Datum mit Sommer/Winterzeit umstellung war eigentlich sehr einfach - Problem ist jetzt nur der Timer, damit ich genau Eine Sekunde hin bekomme. Vielleicht hat noch jemand einen Tipp Danke
Also auf jedenfall hat der 16bit timer Unabhängige Comparematch Werte. Und ich glaube du kannst sogar den 16bit timer von einer Externeen Taktquelle speisen Warum das SInnvol sein kann: --> http://www.mikrocontroller.net/forum/read-1-193043.html
Problem ist nur, der Timer1 läuft mit den selben Einstellungen wie Timer0, also, selber Overflow-Schwellwert?!? --> Obwohl ich verschiedene Einstelle. Wie ich den Sekundentakt theorethisch erzeugen kann, das weiß ich - es funzt nur in der Praxis nicht.
Mahlzeit Hannes! @Thomas: Das einzige, was T0 und T1 verbindet, ist ein gemeinsamer Prescaler und ein gemeinsames Reset-Prescaler-Bit. Trotzdem haben T0 und T1 eigene Clock-Select-Bits welche zum Vergleich mit dem Prescaler dienen und können verschieden schnell laufen. Auch haben T0 und T1 eigene Counter und Output-Compare-Register. Wie berechnest Du den Timer für Deinen Sekundentakt? Wie hoch ist die Grundfrequenz? Ist es eine Sekunde oder sogar im Millisekundentakt? Hast Du einen Abgleich-Algorythmus weil ja z. B. 4MHz oft nicht 4MHz sind? Ach ja: Es ist besser und genauer, den Timer nicht über Timer Overflow zu machen, sondern im CTC-Mode mit Output Compare. Da braucht man sich um das Rücksetzen des Timers nicht zu kümmern. MfG Andi
CTC schaue ich mir heut Abend dann mal an - ist mir bisher unbekannt. Der Timer0 läuft mit 4ms. Timer 1 habe ich versucht mit 20ms, 50ms, und auch 1s. Timer1 läuft allerdings auch mit 4ms - und da hänge ich fest.
Mojje Andi... @Thomas: Wenn du schon ein 4ms-Zeitnormal hast, wozu brauchst du dann einen zweiten Timer für die Sekunde? Erniedrige in der ISR ein Register, setze es bei Unterlauf auf 250 und erhöhe deinen Sekundenzähler. Falls du Timer1 nimmst, Compare-Match im CTC-Mode geht gut. Falls du aber auch noch irgendwann mal Input-Capture nutzen willst, dann ist der CTC-Mode nachteilig. Ein einfaches Beispiel in ASM findest du im Anhang dieses Beitrags: http://www.mikrocontroller.net/forum/read-1-164017.html#164207 Da löst der Timer aber alle 10ms den Interrupt aus, da hat man dann auch noch die hundertstel Sekunden zur Verfügung. ...
Natürlich könnte ich diesen Weg gehen. Ich stehe allerdings nun vor einem Problem, welches ich gern lösen würde - nicht umgehen :) Wenn ich ein anderes mal zwei oder drei Timer benötige, dann stehe ich evtl. wieder vor dem Problem.
Tip am Rande: Die Timer des Mega8 enthalten allerhand Features. Dies macht das Kapitel Timer im Datenblatt etwas unübersichtlich. Schau dir doch mal das Kapitel Timer im Datenblatt eines älteren AVRs an, z.B. AT90S2313 oder AT90S4433. Dort kannst du die Grundfunktionen der Timer verstehen lernen, die beim Mega8 auch nicht viel anders sind. Mit diesem Wissen verstehst du das Datenblatt des Mega8 bedeutend besser. Dein Problem ist lösbar, denn: - jeder Timer hat seinen eigenen Zählerstand, - jeder Timer hat seine eigene Vorteilereinstellung, - jeder Timer hat seine eigenen Interruptvektoren, - jeder Timer-Interrupt hat seine eigenen Freigabeflags (TIMSK)... Allerdings erhöht sich das Risiko, das Interrupts sich gegenseitig behindern, mit der Anzahl der Interrupts im Programm. Es kann bei zwei Timern gelegentlich vorkommen, dass ein Interrupt warten muss, weil der Controller gerade die/eine andere ISR abarbeitet. ...
Hallo In dem Datenblatt des 2313 lese ich schon immer quer. Schaue mr das andere nachher auch noch an. Andere Interrupts sind nicht aktiv, lediglich Timer0 und Timer1 (jeweils overflow). Frage noch. Wie macht ihr das in Assembler? Die Aktivierung der Interrupts? Ich nehm diese unhandliche Liste. ****************** .org 0x0000 rjmp reset reti ;blabla reti ;blabla ... rjmp timer1; rjmp timer0; ... reti ;blabla ****************** Gibt es da noch eine schönere Variante?
Wie ich es mache siehst du in dem oben verlinkten Beispiel. Es gibt aber auch die Möglichkeit, vor jedem IntVektor mittels .ORG die in der Include-Datei definierte Adresse zu definieren. Ich persönlich mag diese Art aber nicht, da dann eine fragmentierte (kein linearer Adressraum) Hexdatei entsteht, die meine (selfmade-) Brennersoft nicht mag. ...
Wie, die Brennersoft mag keine FFFF dazwischen? @Thomas: Es geht auch so, wie Hannes schon meinte: .cseg rjmp Init .org OC1Aaddr rjmp Timer1CmpA ;IRQ on Timer Compare Match a .org OC2addr rjmp Timer2Cmp ;IRQ on Timer 2 Compare Match Nur füllt der AVR-ASM die Lücken mit 0xFFFF auf. Dabei ist die Gefahr, das, wenn man versehntlich einen Interrupt aktiviert den man nicht verwendet, der Programm-Counter (PC) an so ein 0xFFFF springt oder nach der kleineren Liste mitten in den Programmstart. Habe noch keinen Befehl aus 0xFFFF bestehend gefunden, aber wenn der AVR bei nicht dokumentierten Befehlen einfach ein Word weiter geht, dann ist der AVR irgend wann bei dem 2. Interrupt-Vektor der obigen Tabelle oder eben beim Programmstart. Aber wenn man weis was man macht, dann geht das. MfG Andi
Das mit dem 0xFFFF hat mir jetzt irgend wie keine Ruhe gelassen. Habe in einer Zählschleife zur Messung des AVR-Taktes und in einer LCD-Commando-Ausgabe ein ".dw 0xFFFF" dazwischen gesetzt. Die Messung des AVR-Taktes auf einen Takt für das 0xFFFF angepasst, und siehe da, es kommt das selbe raus wie ohne (20.001MHz). Also ist das 0xFFFF im Prinzip wie ein "NOP" und benötigt einen Takt. Auch die LCD-Ausgabe mit dem 0xFFFF dazwischen geht Problemlos. Also kann man eigentlich (fast) gefahrlos die Vektor-Tabelle wie oben machen. MfG Andi
@Andi: Die Hexdatei wird eben nicht mit FF gefüllt sondern einfach nicht definiert. Aus diesem Code: .include"m8def.inc" .cseg rjmp Init .org OC2addr rjmp Timer2Cmp ;IRQ on Timer 2 Compare Match .org OC1Aaddr rjmp Timer1CmpA ;IRQ on Timer Compare Match a .org SPMRaddr+1 ;Adresse hinter den Int-Vektoren Timer1CmpA: ;Code reti Timer2Cmp: ;Code reti Init: rjmp Init wird diese Hexdatei: :020000020000FC :0200000014C02A :0200060010C028 :02000C000CC026 :0600260018951895FFCFAC :00000001FF erstellt. Wie du siehst, ist das kein linearer zusammenhängender Adressraum. Es werden nur die benutzten Speicherzellen definiert. Und als ich die Routine zum Einlesen der Hexdatei schrieb, ging ich von linearem Adressraum aus (wie er ja bei kompetter Vektorliste mit RETI auftritt) und implementierte das Einlesen fragmentierter HEX-Dateien nicht. Und ich baue das nicht mehr um, ich kann damit leben. Dafür bietet mir die ISP-Soft andere Features wie Auto-Calibration, Löschzähler, sinnvolle Darstellung der Fuses usw... Bit- & Bytebruch... ...HanneS...
Ups, sorry! Bin zu stark Pony-Prog gewohnt :-) Habe mir schon ewig keine Hex-Datei mehr angesehen. Das mit dem FF statt 00 macht dann wohl das Pony-Prog vorab beim laden der Hex-Datei. Sinn ist wohl, das der ungenutzte Bereich dann nicht programmiert werden muß da eine 1 "unprogrammet" ist. Ich wünschte, ich wäre auch in der Lage, eine Programmersoft zu schreiben. Hätte nähmlich schon so ein Feature wie externen Clock über das Programmierkabel brauchen können. Die Verschlüsselung der Hex-Dateien wäre kein Problem aber die Steuerung der 3 ISP-Signale und sowieso der Zugriff auf die COM-Ports. MfG Andi
OT... @Andi: Externen Clock habe ich auch nicht drin, war aber ganz zu Beginn fast drauf und dran, das einzubauen. Es ging dann aber auch ohne. Nicht vergessen: Das Programm wurde geschrieben, damit ich AT90S1200 programmieren konnte, denn mit Pony ging nix (heute weiß ich, dass es an der langen Druckerportleitung incl. Umschalter lag). Als ich das Programm (in QB 4.5) schrieb, hatte ich weder Internet noch die Beschreibung des Aufbaus der HEX-Datei. Den Aufbau ermittelte ich durch Vergleichen von Listing und HEX-Datei selbst. Dabei erkannte ich aber nicht alle Merkmale, sondern nur die Codierung des linearen Adressraums. Lade ich damit ein fragmentiertes Hexfile, dann werden die vorhandenen Bytes linear eingelesen, worauf außer dem Reset-Sprung nix mehr stimmt. Böse Falle, aber ich animiere niemanden dazu, das Teil zu verwenden. Der ISP(SPI)-Port war nicht das Problem, das Timing wird ja in den AVR-Datenblättern gut beschrieben, die Serielle unterstützt mein Programmer nicht. Und es ist schließlich nicht das erste QB-Programm, das den Druckerport für andere Zwecke missbraucht. Das ISP-Programm unterstützt auch nicht alle Typen, nur die, mit denen ich bereits hantiert habe. Tiny2313, Tiny13 und Mega48/88/168 werde ich wohl in absehbarer Zeit implementieren müssen. ;-( Ich weiß jetzt auch garnicht, wie das Ding reagiert, wenn man einen nicht unterstützten Typ (oder einen mit defekten Signature-Bytes) anschließt. Falls es dich interessiert kann ich dir gerne mal den Quelltext schicken. Bit- & Bytebruch... ...HanneS...
Interressiert mich schon! Vielleicht hilft es mir das Timing der ISP-Leitungen zu verstehen. Auf jeden Fall, Danke! MfG Andi
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.