Forum: Mikrocontroller und Digitale Elektronik Timer mit 10µs Betriebstakt, aber wie??


von Debugger (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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

von Debugger (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

Sag ich doch. Mit dem CTC kannst du auf dein Timing kommen.

CTC - nicht Overflow

Vorausgesetzt es geht sich mit den Vorteilern
vernünftig aus.

von Debugger (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Debugger (Gast)


Lesenswert?

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.

von Francesco N. (franceso-)


Lesenswert?

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.

von Debugger (Gast)


Lesenswert?

Danke Francesco Na

endlich mal was Produktives (ausgenommen Peter)
werd mal darüber schlafen.

von Karl H. (kbuchegg)


Lesenswert?

Du hast recht. Mit dem CTC gehts nicht ohne Interrupt.
Aber mit dem Fast-PWM gehts.
1
#include <avr/io.h>
2
3
int main()
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.


von Falk (Gast)


Lesenswert?

@ 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



von Christoph Kessler (db1uq) (Gast)


Lesenswert?

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.

von Alex Trusk (Gast)


Lesenswert?

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.

von Falk (Gast)


Lesenswert?

@ 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

von Alex Trusk (Gast)


Lesenswert?

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.

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.