Forum: Mikrocontroller und Digitale Elektronik Mega8 und Timer nachladen: Bitfolge ausgeben - wie am besten?


von ticker (Gast)


Lesenswert?

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..

von цомби (Gast)


Lesenswert?

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.

von ticker (Gast)


Lesenswert?

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?

von Peter D. (peda)


Lesenswert?

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.

von ticker (Gast)


Lesenswert?

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?

von Peter D. (peda)


Lesenswert?

ticker schrieb:
> Ich glaub der Mega8 ist dann zu alt

Stimmt. Du kannst aber dessen Nachfolger ATmega88 nehmen.

von ticker (Gast)


Lesenswert?

Ach nee, schade, geht doch nicht - ich brauch die UART für die 
Kommunikation mit einem PC..

von Karl H. (kbuchegg)


Lesenswert?

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

von Malte S. (maltest)


Lesenswert?

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.

von ticker (Gast)


Lesenswert?

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.

von ticker (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> FAQ: Timer

Ah ja. CTC Modus und Compare match werden wohl zum Ziel führen. danke.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Malte S. (maltest)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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.

von ticker (Gast)


Lesenswert?

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?

von ticker (Gast)


Lesenswert?

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

von CTC (Gast)


Lesenswert?

ticker schrieb:
> Tccr1a.ctc1 = 1                                             'ctc mode
> 'Tccr1a.wgm12 = 1                                            'ctc mode

Im TCCR1A sehe ich weder WGM12 noch CTC1 Bit im Datenblatt.

von ticker (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.