Hallo zusammen,
habe ein kleines Problem:
Ich möchte mit einem ATMega128 einen Timer bekommen welcher mit 10 µS
getaktet ist und einen Overflow interrupt erzeugt. (alle 10µs x 2^16)
Ich benuzte 14,7456 MHz und weis nicht wie ich zu einem solchen
Betriebstakt für einen Timer kommen kann. Ich will aber keine Interrupts
alle 10µs haben weil dann die Systemauslastung zu hoch wird.
danke für eure Hilfe
Muss es unbedingt ein Overflow sein?
Ohne jetzt nachgerechnet zu haben, denke ich
dass du mit einem CTC Interrupt mit dem Timing
besser hinkommen wirst. Vor allen Dingen deshalb
weil du dann bei jedem beliebigen Zählerstand einen
Interrupt auslösen lassen kannst und nicht erst dann
wenn der Timer seinen hardwarebedingten Maximalwert
erreicht hat.
Karl heinz Buchegger wrote:
> Muss es unbedingt ein Overflow sein?> Ohne jetzt nachgerechnet zu haben, denke ich> dass du mit einem CTC Interrupt mit dem Timing> besser hinkommen wirst. Vor allen Dingen deshalb> weil du dann bei jedem beliebigen Zählerstand einen> Interrupt auslösen lassen kannst und nicht erst dann> wenn der Timer seinen hardwarebedingten Maximalwert> erreicht hat.
Schlecht ausgedrückt.
Im CTC Mode zählt der Timer bis zu einer von dir
vorgegebenen Obergrenze, löst den Interrupt aus
und beginnt wieder bei 0
ich benutzte den Timer als Zeitstempel auf 10µSekunden genau eben, aber
ich habe KEINEN 10µs takt, das ist mein Problem, man kann ja nur durch
zweiepotenzen Teilen. Der Timer soll soll jdesmal bei Überlauf einen
aktion auslösen (Zeitstempelüberlauf) sonst dient er nur als
Hardwaregenauer Zeitstempel.
Nochmal,
ich brauche 10µs als Basistakt.
Mit CTC kann ich zwar 10µs erzeugen, ich brauche diese Zeit aber als
Taktquelle. für meinen Zeitstepel welcher Hardwaremäßig vor sich hin
laufen soll. ohne Interrupt alle 10 µs,
wie bekomme ich mit CTC einen TIMER mit taktquelle 10µs , das geht nicht
Bei 14.7456 Mhz hast du eine Zykluszeit
von 1 / 14.745600. Macht 6.78158 E-8 Sekunden
10 µS sind 0.000010 Sekunden.
6.78 E-8 / 0.000010 = 147.456
d.h. der Zähler muss bei einem Vorteiler von 1
abwechwselnd bis 147 bzw. 148 zählen.
Timer1 in CTC Modus, Obergrenze 147 und fertig.
Bei 10µS wird ein CTC Interrupt angezeigt, der
Zähler resettet und der nächste Zählvorgang beginnt.
Jetzt musst du nur noch den externen Pin entsprechend
ein bzw. Ausschalten. Sollte sich mit einer Kombination
aus Compare Match Abfragen und entsprechnder Hardware
Pin-Toggelei erreichen lassen.
Schau doch bitte mal ins Datenblatt deines Prozessors
und lies den Abschnitt über Timer1. Oder programmierst
du in BASCOM?
> Schau doch bitte mal ins Datenblatt deines Prozessors> und lies den Abschnitt über Timer1. Oder programmierst> du in BASCOM?
Der war gemein. Den nehme ich zurück.
Es ist doch eigentlich wurscht, ob der Timer mit 10µs läuft oder
sonstwas.
Willst Du damit ein Delay zählen, dann kann doch der Compiler bequem den
richtigen Zählwert ausrechnen.
Und willst Du ne Zeit messen und für einen Menschen in 10µs-Schritten
anzeigen, dann hast Du alle Zeit der Welt für die Umrechnung, schneller
als ein Lidschlag dauert.
10µs ist nicht besser und schlechter, als jede andere Zahl.
Nimmste eben 4,34µs und gut is.
Peter
Das gibt ein Datenlogger und die Zeitbasis für die Zeitstempel sollte
eben einigermaßen vernünfig sein.
Bei Aufzeichnungen auf 2 Kanälen mit 115KBd habe ich schon alle 50µs
einen Interrupt, das System würde bei nochmaligen interrupt überlasten.
Zu Bascom: NEIN
Verarschen kann ich mich selber.
Das geht,
die 14,7456 durch 32 teilen, also vorteiler 32, dann hat man ca
je alle 2 uS einen increment.
Weiters beim Timestamp teilt man das durch 5, also da der AVR kein
HW-div
hat, macht man eine Multiplication daraus.
((tick-timer * 1422) >> 16 ) + K
K ist eine Korrekturkonstante, die normalerweise (tick-timer >> P)
ist, kann aber auch kombinationen von solchen K´s sein, die dann addiert
oder auch subtrahiert werden, oder das K auch weggezählt wird.
Zur Zahl, 1000/14,7456 = 67,816840277777777777777777777778 nS / Tick
Tick * 32 (prescaler) = 2170,1388888888888888888888888889 nS
= 2,170138888888888888888888888888 uS / Tick
Um nun vom Tick einen 10uS Wert zu erhalten, macht man folgendes:
10 uS / 2,170138888888888888888888888888 uS =
4,6080000000000000000000000000019
256*256 / 4,6080000000000000000000000000019 =
14222,222222222222222222222222219
Also, wenn man den 16bit Timer mit 14222 multipliziert, und das Resultat
um 16 bit nach Rechts shiftet, erhält man die 10uS Interwalle.
Da die Zahl nicht Ganzzahlig ist, muß man das noch korrigieren.
0,222222222222222222222222219 256 256 =
14563,555555555555555555555353284
Dies ist der Fehler, der unter 16bit ist, also sind die 10uS exact.
Da der Timer läuft alle ca 142 mS über.
Dieser Überlauf sollte dann mit dem Breshnam Algorithm gezählt werden,
sowie der Korrekturwert appliziert werden, damit man einen wirklich
exakte Zeit hat.
Also den 32/48/64 bit counter mittels Breshnam Algorithm
alle 142mS incrementieren und heisse ihn mal Tick_10_high.
Um den 10uS Tick zu loggen, sollte man
Tick_10_high + (cast)(( tick * (cast)1422 ) >> 16)
machen. Das geht dann sehr schnell, diese Rechnung.
Du hast recht. Mit dem CTC gehts nicht ohne Interrupt.
Aber mit dem Fast-PWM gehts.
1
#include<avr/io.h>
2
3
intmain()
4
{
5
ICR1=147;
6
OCR1A=14;
7
8
TCCR1A=(1<<WGM11);
9
TCCR1B=(1<<WGM12)|(1<<WGM13);
10
11
TCCR1A|=(1<<COM1A1)|(1<<COM1A0);
12
13
DDRB=(1<<PB5)|(1<<PB6);
14
PORTB=(1<<PB5)|(1<<PB6);
15
TCCR1B|=(1<<CS10);
16
17
while(1)
18
;
19
}
Da der AVR-Simulator im Bereich fast-PWM ziemlich
buggy ist, habe ich versucht das so gut es geht
im Simulator auf einem Mega128 zu simulieren.
Die PWM funktioniert grundsätzlich, der OC-Pin
wird aber im Simulator nicht richtig getoggelt.
Im echten Device sollte das aber nach Datenblatt gehen.
> endlich mal was Produktives (ausgenommen Peter)
Das nächste mal such dir die Modi selbst aus dem
Datenblatt raus, wenn du schon mit der Nase darauf
gestossen wirst. Das wär dann echt produktiv von dir.
@ Debugger
Warum nimmst du nicht einfach einen passenden Quarz?
Der Vorteiler kann mit 1/8/64/256/1024 arbeiten. D.h. bei 10uS Timertakt
brauchst du einen Quarz von 100kHz/800kHz/6.4 MHz, die höheren Teiler
gehen nicht, weil das Quarze über 20 MHz braucht. Alternativ kann man
noch 12,8 MHz nehmen und einfach die Zeitstempel durch 2 teilen (lsr).
MfG
Falk
Vermutlich braucht er die 14,7456 für die serielle Schnittstelle, um
mehr als 9600 Baud sauber einzustellen.
Der Vorschlag mit dem abwechselnden Teilen durch 147 / 148 scheint mir
die einzige Lösung zu sein. Man könnte es verfeinern, (so wie
Schaltjahre alle 4 Jahrhunderte ausfallen) und die 147.456 genauer als
durch 147,500 annähern. Ergebnis ist natürlich ein kleiner Jitter des
Zeitstempels, aber der mittelt sich heraus.
den ganzen "stress" kann man sich sparen, wenn man auf peter dannegger
hoert und die gewuenschte 10µs-aufloesung aus einem beliebigen takt
nachtraeglich ausrechnet.
das mag zwar nicht in das vorher so toll ausgedachte konzept passen,
aber ich finde, es ist die praktikabelste loesung.
2 portpins und 2 timer zu "opfern"(ein timer erzeugt den takt des
anderen) ist allerdings auch ein netter workarround. leider scheint das
ja mit ctc nicht zu klappen(habs grad nicht selber nachgelesen), aber
mit fast-pwm soll es laut Karl heinz Buchegger gehen. ein bisschen
eigeninitiative waere hier vielleicht angebracht.
gruss, alex.
@ Christoph Kessler
Mit 12,8 kann man auch alle Baudraten sehr genau erzeugen. 1%
Frequenzabweichung ist problemlos akzeptabel! Mein Excel sheet sagt für
14,4k bis 115,2k -0.8%. Passt schon.
Das it dem durch 147/148 halte ich für arg aufwendig.
@Alex Trusk
Wieso Stress? 12,8 MHz und gut ist. Klar, Peters Methode wird in den
meisten Fällen auch sehr gut funktionieren, aber wenn es beispielsweise
darum geht, bestimmte Vorgänge mit klar definiertem Zeitraster
aufzuzeignen und darzustellen wirds umschön und ggf aufwändig. Niemand
will ein Oszilloskop, das 4,75 us/ DIV anzeigt.
MfG
Falk
ok, das mit dem stress ist relativ und koennen wir aussen vor lassen.
die 12,8 MHz sind damit die dritte(?) alternative und ein externer
100kHz oszillator waere eine vierte.
ich persoenlich wuerde entweder die ctc-variante waehlen und im int eine
hilfsvariable hochzaehlen, oder falls das wirklich zu viel ressourcen
frisst(was ich nicht glaube), auf peters variante ausweichen.