Hi, ich hab noch nicht so viel mit Timern gemacht, deshalb die Frage: Wie macht man sowas am Besten: ich habe 6 Bytes, die ich bitweise in einem genauen (festen) Zeitraster (ca. 20 kHz) ohne Lücke zwischen den Bytes aus einem Portpin schieben will. Was ist die einfachste Variante? Bisherige Überlegungen: RS232 fällt wohl aus, weil da start- und Stopbits generiert werden, und zwischen den Bytes dürfen keine Pausen sein. SPI - kann man die SPI-Clock so genau einstellen? und kann man schnell genug nachladen, so dass keine Lücken zwischen den Bytes entstehen? Also: Timer stellen, in der ISR Timer neu laden und bitweise die 6 Byte rausschieben. Kann man den Timer so einstellen, dass man ihn nicht in der ISR neu laden muss? Also meinetwegen "zähle immer bis 60 und löse dann einen Interrupt aus" ? In den Programmierbeispielen habe ich immer gesehen, dass in der ISR (am Anfang) der Timer-wert neu gesettzt wurde... Also was rauskommen soll: wenn alle Bytes z.B. 55 Hex sind, sollen NUR 24 steigende und fallende Flanken in exakt gleichem Abstand 'rauskommen..
Was spricht denn gegen das neuladen des timers in der ISR. Ich mach das immer so. Eine ISR sollte immer maximal kurz sein. Das Nachladen eines registers ist maximal kurz und unumgaenglich fuer ein genaues timing. Ich wuerd auch in der ISR schieben und ausgeben. Aber nicht mehr.
Naja ich dachte halt es gibt irgendeine Betriebsart, die das automatisch macht, also das Nachladen - sonst muss man ja für das genaue Timing rechnen / berücksichtigen, wie lange das Nachladen in der ISR dauert, und den Nachladewert entspr. verringern, oder?
ticker schrieb: > SPI - kann man die SPI-Clock so genau einstellen? und kann man schnell > genug nachladen, so dass keine Lücken zwischen den Bytes entstehen? Nicht zu alte AVRs können die UART als SPI schalten und dann entsteht keine Lücke, da gepuffert.
Ich glaub der Mega8 ist dann zu alt (ich lese gerade im Datenblatt) - man kann das Frame Format der USART nicht abschalten, und man kann auch nicht "Low when idle" setzen.. schade :-) Aber was die Timer angeht - es scheint einen CTC mode im Timer1 zu geben, der automatisch nachlädt und Interrupt auslösen kann.. funktioniert das Hat jemand das schonmal gemacht ein Stück Beispielcode?
ticker schrieb: > Ich glaub der Mega8 ist dann zu alt Stimmt. Du kannst aber dessen Nachfolger ATmega88 nehmen.
Ach nee, schade, geht doch nicht - ich brauch die UART für die Kommunikation mit einem PC..
ticker schrieb: > Naja ich dachte halt es gibt irgendeine Betriebsart, die das automatisch > macht, also das Nachladen - sonst muss man ja für das genaue Timing > rechnen / berücksichtigen, wie lange das Nachladen in der ISR dauert, > und den Nachladewert entspr. verringern, oder? Na komm. Wir reden hier über Laufzeitunterschiede in der ISR, die sich im einstelligen µs Bereich (also millionstel Sekunden) oder noch weniger abspielen. Frag dich selber: spielt das für dich eine Rolle oder nicht? Für Video-Anwendungen spielt es eine Rolle. Aber in 99% aller anderen Fälle tut es das nicht. 'Genau' ist dann erfüllt, wenn es 'genau genug' ist. FAQ: Timer
Du kannst natürlich komplett jedes einzelne Bit in der ISR aus dem Port wackeln. Dann kannst Du das Timing für jede einzelne Flanke auf den Takt genau bestimmen. Musst halt das jeweils nächste Bit außerhalb der ISR vorbereiten, nicht dass durch Verzweigungen in selbiger noch Laufzeitunterschiede entstehen. Und bloß nirgends die Interrupts blockieren. Und trotzdem alle Zugriffe sauber ordnen. Aber siehe Karl Heinz' Antwort. Brauchst Du das? Wenn ja, hast Du bestimmt auch eine entsprechend genaue Taktquelle, die das rechtfertigt.
Karl Heinz Buchegger schrieb: > Frag dich selber: spielt das für dich eine Rolle oder nicht? Ich weiß nicht, wie genau es das Empfangsgerät braucht. Also wenn es genau geht - mach ich es. Der Punkt ist ja, dass sich dieser Wert bei jedem Interrupt einfügt, also auf alle 6 Bytes betrachtet, mit 1MHz Takt (quarz) und 4 Takte für das Register Nachladen sind das knapp 200uS.. Ok es hängt auch vom Prescaler ab wie genau ich es bekomme.. Malte S. schrieb: > nicht dass durch Verzweigungen in selbiger noch > Laufzeitunterschiede entstehen. Nee, wenn ich das Nachladen am Anfang der ISR mache, ist der Rest egal, solange ich vor dem nächsten Interrupt fertig bin.
Karl Heinz Buchegger schrieb: > FAQ: Timer Ah ja. CTC Modus und Compare match werden wohl zum Ziel führen. danke.
ticker schrieb: > Karl Heinz Buchegger schrieb: >> Frag dich selber: spielt das für dich eine Rolle oder nicht? > > Ich weiß nicht, wie genau es das Empfangsgerät braucht. Also wenn es > genau geht - mach ich es. Der Punkt ist ja, dass sich dieser Wert bei > jedem Interrupt einfügt, also auf alle 6 Bytes betrachtet, mit 1MHz Takt > (quarz) und 4 Takte für das Register Nachladen sind das knapp 200uS.. * Der ISR Aufruf erfolgt auch nicht ganz taktgenau. Je nachdem welcher Befehl gerade ausgeführt wird, wenn der Interrupt kommt gibt es eine kleine Verzögerung, weil dieser Befehl noch fertig abgearbeitet wird. * Timer vorladen ist sowieso meistens unsinnig (dafür gibt es den CTC Modus) * 4 Takte Nachladen sind bei 1Mhz keine 200µs, sondern 4µs * der Fehler akkumuliert sich nicht, denn der Timer zählt für sich alleine und löst den nächsten Interrupt ausschliesslich aufgrund seiner eigenen Zählerei aus * ob dein Quarz genau und exakt 1000000 Schwingungen pro Sekunde macht steht in den Sternen. Tatsächlich wäre es ein enormer Zufall, wenn er es täte.
Du kannst natürlich auch ein 48-Bit-Schieberegister nehmen, das so unregelmäßig die Daten auch auflaufen mögen laden und abschließend quarzofengetaktet hinten abgreifen. SCNR
Erzähl dochmal, wozu das überhaupt dienen soll. Dann findet man viel einfacher eine Lösung. Also nicht, was Du machen willst, sondern warum Du meinst, es ausgerechnet so machen zu müssen. Wenn das z.B. irgendeinen IC ansteuern soll, ist ein Link auf das Datenblatt viel informativer.
Der Ehrgeiz hat mich gepackt - ich will nicht den Timer neu laden, sondern den CTC mode auf dem mega8 in den Griff bekommen, also.. Ich habe mich mal im Datenblatt und in den oben genannten Timer-FAQ belesen und mal ein paar Zeilen im Bascom-Simulator getestet, weil man da so schön sieht, was passiert: TIMSK.OCIE1A = 1 'compare-interrupt ein OCR1AH = 0 'Vergleich mit 96 OCR1AL = 96 TCCR1A.CTC1 = 1 ' ctc-modus 'TCCR1A.WGM12 = 1 'alias, ebenfalls ctc modus TCCR1B.CS10 = 1 'prescaler=1 Wenn ich das Programm schrittweise laufen lasse, funktioniert zunächst alles wie geplant: Der Zähler fängt an, aufwärts bis 60(Hex) zu zählen, und die Interrupt-Routine wird aufgerufen, bei der Rückkehr aus der ISR wird das Interrupt-Flag zurückgesetzt, ABER der Zähler (TCHT1H, TCNT1L) zählt weiter und fängt nicht wieder bei 0 an - ist das ein Verständnisproblem, hab ich was vergessen oder spinnt der Simulator?
Falls jemand mit dem Simulator probieren möchte, hier das ganze "Mini-Testprogramm". Im Simulator "Sim Timers" ankreuzen: $regfile = "m8def.dat" $crystal = 1228800 $baud = 1200 'Ports Config Portd.7 = Output : S_out Alias Portd.7 : S_out = 0 'Var Dim Dummy As Byte Dummy = 0 'Timer einstellen On Oc1a T_isr Nosave Timsk.ocie1a = 1 Ocr1ah = 0 Ocr1al = 96 Tccr1a.ctc1 = 1 'ctc mode 'Tccr1a.wgm12 = 1 'ctc mode Tccr1b.cs10 = 1 'prescaler=1 Enable Interrupts Do Incr Dummy Loop T_isr: Decr Dummy Return End
ticker schrieb: > Tccr1a.ctc1 = 1 'ctc mode > 'Tccr1a.wgm12 = 1 'ctc mode Im TCCR1A sehe ich weder WGM12 noch CTC1 Bit im Datenblatt.
Danke, das war die Lösung (falsches Register A statt B), jetzt spielt alles, wie es soll!
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.