Hallo! Ich habe ein Problem, exakt 2 Khz mit dem Timer 0 zu erzeugen. Das Programm erzeugt mir 1,6 Khz schöne symmetrische Rechtecke. (Mit Oszi und Zählfrequenzmesser festgestellt). Aber warum? Ratlos Erwin
Du benutzt den Überlauf-Interrupt mit Nachladewert, um die Zeitbasis zu erzeugen. Bist du dir beim NachladeWert=6 sicher, dass BASCOM das in der Zeit schafft? Ich würde den Timer im CTC-Mode laufen lassen. Dann braucht man sich um nichts mehr zu kümmern. Sogar der dazugehörende Ausgang wird ganz ohne extra Programm-Code umgeschaltet. Das erfodert allerdings einen Blick ins Datenblatt und dem verstehen der dort aufgeführten Informationen...
@Rahul Eben, das ist es. ...dem Verstehen der Informationen im Datenblatt. (Englisch). Wenn ich wüßte, wie man den Timer in den CTC-Modus bekommt, würde ich es mal probieren. Ich kenne nur die Modi Timer oder Counter. :-(( Immer noch ratlos Erwin
Jetzt habe ich mal mit größeren Prescaler-Werten getestet; da stimmen die Frequenzen, die ich berechnet habe. Scheinbar ist die Zeit zu gering, um die Schleife vernünftig auszuführen, wenn der Prescaler auf 1 steht. In dem CTC-Modus könnte ich doch wahrscheinlich doch auch keine 2 KHz aus 4 Mhz erzeugen, bei nur 256 Schritten, die Timer 0 kann?! Ich baue gleich einen 4060 und einen Schwung Teiler dahinter. GRMPF Erwin
Warum nimmst du nicht den Prescaler 8, dann ersparst du dir das teilen danach, obwohl 48 Takte sind auch ziemlich knapp für Interrupt und Timer laden. Timer 0 kann übrigends kein CTC, das kann nur Timer 1 und der ist 16bit. Da müsstest du dann 2000 als Wert eintragen, das sollte dann schon,
@Hubert Ich kann den Timer1 nicht dafür verwenden, weil das Ganze ein Frequenzzähler werden soll und der Timer1 als Impulszähler agieren soll. Der Timer0 sollte mir eigentlich die Meßzeit zur Verfügung stellen. Wenn der 1ms Meßzeit herstellen soll, muß er ja mit 1000Hz "schwingen". ...wenn es Atmel´s mit 2 großen Timern gäbe....?! Tja dann... Ich würde mich trotzdem über ein Stückchen Assembler freuen, was mir mal den CTC-Modus veranschaulicht. Gruß Erwin
Assembler? Guck doch mal bei www.hanneslux.de vorbei. In den Datenblättern neuerer AVR sind meist auch Codebeispiele vorhanden. Sehe ich es richtig, dass du den AT90S2313 verwendest? Der kann CTC beim Timer0 noch nicht... Du kannst aber auch "irgendeine" MEsszeit wählen und den Controller dann etwas rechnen lassen - das machen die gerne...
Ich schätze, das grundsätzliche Problem ist, dass die Interrupt-Routine nie in Nullzeit übernehmen kann. Sprich: ab dem Zeitpunkt, wo der Interrupt kommt, bis zum Neuladen hat der Timer immer schon ein Stück über die 0 hinaus weitergezählt, was in der Zeitrechnung berücksichtig werden muss - oder zu einer Verlängerung der Interrupt-Periode führt. Dazu kommt, dass ein AVR-Timer nach dem Neuladen im laufenden Betrieb stets einen Takt "aussetzt", bevor er weiterzählt. Ein probates Verfahren für einen Nicht-CTC-Timer mit Prescaler 1 ist daher, in der Interrupt-Routine "Timer0 = Timer0+(startwert+1)" statt "Timer0 = (startwert)" zu schreiben. Ansonsten, wenn der Timer0 wirklich nur den Ausgangspin toggeln soll und es auf möglichst hohe Genauigkeit ankommt, würde ich die Umlauf-Geschichte mit in die Interrupt-Routine zu integrieren und schreiben: "Ontimer0: Timer0 = 6+1 Decr Umlauf If Umlauf <=0 Then Umlauf = 8 If Umlauf >=4 Then Portd.1 = 1 Else Portd.1 = 0 End If End If Return" Vorausgesetzt, es wird kein höher priorisierter Interrupt benutzt (INT0/1 oder Timer1-Interrupts), jittert das Ausgangssignal dann nur noch um maximal 3 Taktzyklen. HIH Johannes
> ...wenn es Atmel´s mit 2 großen Timern gäbe....?!
Gibt es doch... ATMega64 z.B. hat zwei 8- und zwei 16-Bit-Timer... Oder
ist Dir das dann schon zu viel des Guten?
Ähm, ich meinte natürlich: "Ontimer0: Timer0 = Timer0+6+1 ..." Verflixtes Copy-n-paste :-)
Noch eins: Was spricht gegen eine Tiny2313 statt AT90S2313? Der hat auch schon CTC auf Timer0. Und ist sowieso zukunftsträchtiger als der eh auslaufende AT90S2313...
Der Einsprung in den Interrupt-Vektor dauert bei AVRs mit bis zu 128KB Flash 4 Taktzyklen. Hinzu kommt noch die Zeit, die benötigt wird, um den zum Zeitpunkt des Auftretens des Interrupt-Ereignisses gerade ausgeführten Befehl zu Ende zu bearbeiten (bis zu 3 Zyklen). Dann kommen 3 Zyklen für den Sprungbefehl in die ISR (bei µCs mit bis zu 8 KB Flash). Dann werden Register gesichert, was auch noch mal 10-15 Zyklen dauern dürfte (Schätzwert, hängt davon ab, welche Register vom Compiler gesichert werden). Dann erst kommt die eigentliche Interrupt-Routine. Am Ende werden die Register wieder geladen (noch mal 10-15 Zyklen) und der Rücksprung dauert noch mal 4 Zyklen. Dann noch mindestens ein Befehl im Hauptprogramm (mindestens ein Zyklus) und erst dann kann der nächste Interrupt bearbeitet werden! Macht insgesamt 30-50 Zyklen... Das nur als Idee, wie lange die Ausführung einer Interrupt-Bearbeitung wirklich dauert und dass das mit Timern ohne Prescaler und mit niedrigen Werten für den Überlauf nicht funktionieren kann.
> als der eh auslaufende AT90S2313...
Wohl eher 'ausgelaufen' als 'auslaufend'. Und der Tiny2313 ist so
preisgünstig, da sollte es keine Frage sein, ob man seine verstaubten
Altlasten noch benutzt...;-)
@johnny.m u.a. Bitte nichts durcheinanderbringen, denn der Timmer zählt, außer in bestimmten PWM-Modi, immer hoch und nicht runter. Von daher bedeuten kleine Startwerte durchaus hohe Taktzahlen bis zum Überlauf. Die Formel für einen 8bit-Timer lautet: Takte bis Überlauf = (256 - Startwert) * Prescaler Nichts für ungut Johannes
@Johannes: Hast natürlich recht! Hatte nicht richtig gesehen, dass er die 6 dirket ins TCNT schreibt. War davon ausgegangen, dass er nur 6 Zyklen warten will. Dass der Timer raufzählt ist mir schon klar... Auch in diesem Fall kann aber die Ausführungszeit der ISR eine Rolle spielen, v.a. dann, wenn innerhalb der ISR mehr Code steht. Ich weiß halt nicht, was BASCOM noch alles an automatischen Aktionen in ISRs durchführt, aber so was sollte man schon bedenken. Und auch 250 Taktzyklen sind u.U. schnell erreicht, wenn man nicht aufpasst....
@Erwin, "Ich kann den Timer1 nicht dafür verwenden, weil das Ganze ein Frequenzzähler werden soll und der Timer1 als Impulszähler agieren soll. Der Timer0 sollte mir eigentlich die Meßzeit zur Verfügung stellen. Wenn der 1ms Meßzeit herstellen soll, muß er ja mit 1000Hz "schwingen"." Wenn das ein Frequenzmesser werden soll, dann ists genau umgekehrt besser, weil Du dann die Capture-Funktion für kleine Frequenzen nutzen kannst (Periodendauermessung über n Perioden). Außerdem keine Angst vor Mathematik, d.h. obs nun genau 1ms sind oder genau was anderes, ist völlig egal. Peter
UFF!! Das Programm ist nur als Test gedacht, später werde ich nur intern eine Variable setzen und damit den anderen Timer starten und stoppen. Ich wollte eben "draußen" etwas messen können. (Oszi) Ihr habt mich jetzt erst mal mit genug Lesestoff versorgt. :-) Ich habe auch noch Attiny2313. Danke für den Rat mit den "großen" Avr´s. (2 16 bit Timer). Bascom unterstützt den CTC-Betrieb nicht :-( Scha....ade! @Peter Ich könnte natürlich die Timer tauschen, aber ich möchte möglichst viele Werte pro Zeiteinheit einlesen, (genauigkeit) und in den kleinen Timer kann ich nur 256 Bit "reintun". Danke erst mal Erwin
> Bascom unterstützt den CTC-Betrieb nicht...
Das kann ich mir so aber nicht vorstellen. Außerdem kannst Du sicher
auch in BASCOM die I/O-Register von Hand konfigurieren, oder etwa
nicht?
Ich kann die Register "von Hand" beeinflussen. Das nützt mir aber wenig, wenn ich den CTC-Modus nicht durchschaue. Ich kann kein Englisch und Übersetzungen der Datenblätter mit Babelfish liefern nur wirres Zeug. Ein Stück kommentierter Assemblercode zu diesem Modus würde mir sehr helfen, zumal man Assembler auch in Bascom "einbauen" kann. Gruß Erwin
P.S. "Config Timer" kann nur Timer als Timer, als Counter oder als PWM einstellen. Das ist ja mein Ärger. Erwin
@Erwin Wenn es um eine Frequenz- bzw. Periodenmessung geht, ist, wie Peter schon angedeutet hat, die Capture-Funktion in Kombination mit dem Overflow des Timer1 in der Lage, ganz ohne Interrupt zwischen ein paar zig und fast 2mal 65536 Taktzyklen auf +/- 1 Taktzyklus genau zu vermessen. Dazu muss das zu messende Signal nur auf den ICP-Pin des AVR geschaltet sein. Die Umrechnung auf die exakte Frequenz erfolgt dann anhand der (immer bekannten) Taktfrequenz und ist normal ziemlich einfach. Und Assembler brauchst Du dafür ebenso normal nicht unbedingt. Bleibt allerdings die Frage, welchen Frequenzbereich Du tatsächlich erfassen willst... Johannes
Ich will bis 100Mhz messen. Dazu muß ich noch einen 10:1 Teiler davorsetzen. Die Prozessoren, die ich habe sind für 20Mhz Takt gedacht. Damit müßte ich bis 10 Mhz messen können. Und dann eben den Wert * 10. Gut, den Capture Interrupt gibt es bei Bascom. Damit habe ich noch nichts gemacht, aber da finde ich mich schon zurecht. Ich gucke jetzt erst mal, wie das mit Capture geht. Vor Jahrzehnten habe ich einen TTL-Zähler mit 26 Schaltkreisen gebaut. Ich glaube, damals bin ich schneller zum Ziel gekommen als heute mit Kontrollern. ;-) Gruß Erwin
"...und in den kleinen Timer kann ich nur 256 Bit "reintun"." Nö ! Im Overflowinterrupt kannst Du beliebig weiter zählen. Genau, wie Du mit nur 10 Ziffern 0..9 auch beliebig hohe Zahlen darstellen kannst. Mit 20MHz kannst Du nur etwa bis 8MHz zuverlässig zählen. Aber kein Problem, nimm einfach nen Vorteiler 1/16. Peter
Oha, ich fürchte, da musst Du schon mindestens 100:1 vorteilen, um mit einem 20MHz AVR noch hinterher zu kommen. Selbst wenn der gar nichts weiter tut, als in "pure Asm" nur auf das ICP-Signal zu warten... Johannes
> ... wenn ich den CTC-Modus nicht durchschaue...
Der CTC-Modus (Clear Timer on Compare match) macht nix anderes als den
Timer bei Auftreten eines Compare-Ereignisses (also genau dann, wenn
das Timer-Counter-Register TCNTx den im entsprechenden Compare-Register
befindlichen Wert erreicht) zurückzusetzen. Das ganze geschieht
hardwaremäßig, d.h. verzögerungsfrei. Es muss nichts nachgeladen
werden, da der Wert im Compare-Register gleich bleibt, wodurch sich
keine Ungenauigkeiten ergeben. Im CTC-Modus kann man (ähnlich wie bei
einer PWM) auch einen bestimmten I/O-Pin bei einem Compare-Ereignis
hardwaremäßig umschalten lassen und so sehr präzise Taktsignale
erzeugen.
Um johnny's post zu ergänzen, kann der CTC-Modus den betreffenden Output, sofern er vorher per DDR auf Ausgang gestellt ist, nur toggeln, d.h. er wird bei Ablauf der Timer-Periode auf den jeweils anderen Pegel gestellt, was wiederum heißt, dass für ein symmetrisches Ausgangssignal das Compare-Register (OCR) mit dem halben Periodenwert geladen werden muss. Hoffentlich ist das nicht schon wieder zu kompliziert :-) Johannes
@Alle Helfer :-) Jetzt habe ich 2 Möglichkeiten, das Programm zu realisieren:Peters Methode (Du hast Recht, das habe ich eben mal probiert, geht gut) und Johnnies Erklärung, da setze ich mich heute Abend mal dran. (Jetzt habe ich den Mechanismus verstanden, danke). So, ich muß mich erst mal neu initialisieren, ich habe in der falschen Schleife gehangen! :-)) Gruß Erwin
Moin Erwin, wenn es etwas extra Hardware sein darf, schau Dir mal den LTC1799 an, der ist programmierbar von 2kHz bis 20 Mhz, kostet bei Fr. Reichelt 3,- . 2Rs und ein C und fertig. mfg Oliver
@Oliver Moin! Danke für den Tip, aber ich will das Problem mit AVR lösen, woll´n mal sehen, wer den stärkeren Willen hat, der MC oder ich. :-)) Gruß Erwin
Der MC wird starrer in seinem Verhalten sein...Der kann einfach nicht anders!
Erwin, lass Dich nicht bangemachen. Mag ein MC noch so starr in seinem Verhalten sein, dem menschlichen Willen ist er doch niemals gewachsen. Ohne angeben zu wollen - ich spreche da aus Erfahrung. Viel Erfolg Johannes
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.