Forum: Mikrocontroller und Digitale Elektronik 16 Bit Timer für Funkuhr


von Nineteen and Redmouth (Gast)


Lesenswert?

Servus,

also wir haben folgendes Problem. Wir wollen eine Funkuhr bauen. Die
Antenne und alles läuft schon. Bei der Dekodierung des Signals stoßen
wir jedoch auf ein Problem. Wie bringen wir unserem Timer bei, dass er
jede Millisekunde einmal auslöst und eine Variable incrementiert. An
unserem Oszi haben wir nie die richtige Zeit.

Hier der Code:

.include "m16def.inc"
.def ms=r17

.org 0x0000
rjmp main
.org 0x10
rjmp timer1_o

main:

ldi r16, LOW(RAMEND)
out SPL, r16
ldi r16, HIGH(RAMEND)
out SPH, r16

ldi r16, 0b00001000
out DDRD, r16
ldi r16, 0b10001000
out PORTD, r16

ldi r16, 0b00000000     ;Kontrollregister, Prescaler = clk/64
out TCCR1A, r16
ldi r16, 0b00000011
out TCCR1B, r16

ldi r16, 0b00000100     ;Overflow Interrupt...
out TIMSK, r16

ldi r16, LOW(0xFD7F)    ;Wert vorbelegen
out TCNT1L, r16
ldi r16, HIGH(0xFD7F)
out TCNT1H, r16
sei

loop:
rjmp loop

timer1_o:

cbi PORTD, 3 ;für das Oszi...
rcall wait   ;sonst kommt der Pin nicht HIGH bzw. LOW
sbi PORTD, 3 ;und wieder weg...

ldi r16, 0xFD     ;den Wert neu laden...
out TCNT1H, r16
ldi r16, 0x7F
out TCNT1L, r16

reti

wait:                               ;kurze Pause, sehr kurze...
  ldi r20,1
  delay1:
  ldi r21,5
  delay2:
  dec r21
  cpi r21,0
  brne delay2

  dec r20
  cpi r20,0
  brne delay1
ret

soo, wir wären froh über jede Hilfe aber bitte nicht in C... Wir
könnens nicht mehr sehen.

Gruß Nineteen und Redmouth

von Santa Klaus (Gast)


Lesenswert?

Von dem Setzen der Register TCNT1H:TCNT1L im Interrupt-Handler ist
abzuraten, weil der Timer ja munter weiterläuft, bis der µC zur
Ausführung der entsprechenden Befehle kommt (man müßte also die Anzahl
der Systemclocks für die Ausführung dieser Befehle abzählen und den
Setzwert von TCNT1H:TCNT1L um diese Anzahl verringern).

Die Standardlösung des Problems "Erzeugung von Interrupts mit einem
Takt von genau x Millisekunden" ist, den Timer T/C1 im CTC-Mode zu
betreiben ("CTC" = clear on compare match").  Der Timer bekommt
einen Compare-Wert vorgegeben (Register OCR1AH:OCR1AL), und wenn sein
Zählwert diesen erreicht ist, wird er von der Timer-Logik automatisch
auf Null gesetzt, sowie ein Compare-Match-Interrupt ausgelöst.

Hard- und softwaremäßige Details siehe Datasheet.

PS: Und nicht die Sicherung des SREG im Interrupt-Handler vergessen!

von Nineteen and Redmouth (Gast)


Lesenswert?

Hallo,

also danke erst mal für die Antwort. Ich habs bisher auch so versucht,
bis ich im Internet die andere Möglichkeit entdeckt habe. Habs jetzt
wieder geändert. Frage: Ich arbeite mit dem STK500 und dem ATMega16
also mit einem CPU-Takt von 3,69Mhz. Wie groß muss OCR1AH/L sein wenn
ich eine ms haben will. Ich hatte mir E6A also 3690 ausgerechnet.
Stimmt das? Mein Oszi sagt NEIN!

Danke
Nineteen...

von Nineteen and Redmouth (Gast)


Lesenswert?

servus,

also ich hab jetzt noch mal ne zwischenfrage. Komm mir selber ein
bisschen dumm vor. Wenn ich die Taktfrequenz im AVR-Studio ändere.
Ändert sich absolut nichts. Wie ist also diese berühmte überall
genannte clk/IO Frequenz. Welchen Zahlenwert hat die?

von Thomas Forster (Gast)


Lesenswert?

Servus,

Clk ist der hardwaremässige Systemtakt. Bei dir 3690000Hz.
Dein Prescaler ist 64. Also
3690000/64=57656.25 counts/sec.
Für 1ms also ca. 57.7 counts/msec.

OCR1AL= 58
OCR1AH= 00

von Santa Klaus (Gast)


Lesenswert?

>Frage: Ich arbeite mit dem STK500 und dem ATMega16
>also mit einem CPU-Takt von 3,69Mhz. Wie groß muss OCR1AH/L sein wenn
>ich eine ms haben will. Ich hatte mir E6A also 3690 ausgerechnet.
>Stimmt das? Mein Oszi sagt NEIN!

3690, also 0xE6A, stimmt natürlich (wenn Du T/C1 ohne Prescaler
betreibst, d. h. T/C1 mit vollem Systemtakt läuft).  Was sagt denn das
Oszi?

Beim Laden der 3690 in das Output-Compare-A-Register-Paar OCR1AH:OCR1AL
muß unbedingt die Reihenfolge beachtet werden: Zuerst das High-Byte und
dann das L-Byte; nicht andersrum. Das High-Byte wird zuerst intern in
einem Extraregister gepuffert; die 3690 gelangen erst mit dem Setzen
des Low-Bytes als komplettes Wort (!) in OCR1AH:OCR1AL

Also so:

ldi   t, High(3690-1)
out   OCR1AH, t
ldi   t, Low(3690-1)
out   OCR1AL, t

Die "-1" ist notwendig, wenn kein Prescaler verwendet wird.

Hast Du berücksichtigt, daß Du jetzt nicht mehr den T/C1-Overflow-,
sondern den T/C1-Output-Compare-Match-A-Interrupt verwenden mußt?

>Wenn ich die Taktfrequenz im AVR-Studio ändere.
>Ändert sich absolut nichts. Wie ist also diese berühmte überall
>genannte clk/IO Frequenz. Welchen Zahlenwert hat die?

Die Taktfrequenz auf dem STK500 wird durch den eingesteckten Quarz
bestimmt. Für Zeitmessungen im Simulator ist es sinnvoll, die Frequenz
dieses Quarzes in den Optionen im AVRStudio (Hauptmenü:
"Debug/Simulator Options") einzustellen.

von Nineteen and Redmouth (Gast)


Lesenswert?

Servus,

mann mann mann mann mann aua aua aua...

Also ich glaub echt ich spinn. Mindestens tausend Beiträge hab ich
durchforstet und überall wurde mir gesagt das dieser verschickte
Prozessor auf diesem noch verschickterem STK 500 mit 3,69 Mhz getaktet
ist. Erst nach durchforsten des Datenblattes dann die Erlösung. Er
läuft mit 1Mhz standardmäßig. Für alle, die dies einmal über google
oder direkt im Forum suchen sollten:

DER ATMEGA16 HAT EINEN TAKT VON 1,000000000 MHZ !!!!!!!!!!!!!!!!!!!!!

Trotzdem danke für jegliche Hilfe...
Gruß nineteen und redmouth

von Peter D. (peda)


Lesenswert?

Das ist weder die Schuld des STK noch des M16, sondern einzig und allein
Deine !

Ich käme garnicht erst auf die Idee einen MC zu programmieren ohne das
Datenblatt griffbereit zu haben.

Alle AVRs mit der Option "interner Takt" haben diesen im
Auslieferungszustand aktiviert.

Der Sinn dahinter ist, es sollen ja auch Schaltungen ohne externen Takt
laufen. Abschalten läßt sich der interne Takt ja immer, auch ohne
Quarz.


Peter

von Peter D. (peda)


Lesenswert?

Du weißt schon, daß die kürzeste Pulsbreite beim DCF-77 min 100ms ist ?

Da reichen 20ms Abtastrate dicke aus, 1ms ist völlig übertrieben.


Peter

von Redmouth (Gast)


Lesenswert?

Das ist uns schon alles klar. Das Datenblatt hatten wir ja auch. Nur wir
gingen davon aus, dass mit "CLK" im Datenblatt die Taktfrequenz des
Controllers gemeint ist und nicht die Frequenz der Timer Clock
Source!!!
Jetzt funktioniert es jedenfalls!
Das mit den 10ms machen wir schon noch. Die eine ms war nur mal so ein
Test!!!
Gruß Redmouth

von Nineteen and Redmouth (Gast)


Lesenswert?

Also Leute, ich kann mich Redmouth nur anschließen.

1.) Sind wir Anfänger
2.) Haben wir bisher immer nur den AT90S8535 genommen. Bei dem gibt's
keinen internet Takt, oder? Deswegen sind wir halt durcheinander
gekommen.
3.) Zum Thema 20,10 oder 1 ms. Also wir werden dann schon 10 ms nehmen
ist ja klar aber um die Genauigkeit unserer Berechnung zu testen gilt
ja wohl: um so kleiner desto besser.

Jetzt noch eine Praxis-Frage... Wie würdet ihr die Antenne anschließen.
Mein Vorschlag wäre das Signal an die Int0 und Int1 Pins zu hängen. Beim
int0 auf eine LOW-Flanke zu reagieren um den Sekunden-Takt zu bekommen
und die gezählten Millisekunden auf 0 zu setzen. Beim int1 Pin auf eine
HIGH-Flanke zu reagieren und die gezählten Millisekunden auszuwerten.
Also bei 100 ne 0 und bei 200 ne 1 abzuspeichern. Würdet ihr das auch
etwa so machen oder ist das zu umständlich oder ungenau oder was auch
immer?...

Vielen Dank für die Hilfe aus dem Forum.
Gruß nineteen

von Peter D. (peda)


Lesenswert?

Die Idee mit dem Timerinterrupt ist schon o.k.
Ein externer Interrupt fängt nur unnötig Störungen mit ein.

Externe Interupts sollte man nur für wirklich schnelle Sachen nehmen
(z.B. Frequenzmesser, Ethernet-Interface), wo es auf µs ankommt.


In der Codesammlung ist ein Beispiel von mir.


Peter

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.