Forum: Compiler & IDEs Timer mit Startwert verwenden (AVR)


von Christian W. (clupus)


Lesenswert?

Hallo,

wenn man den Timer mit einem Startwert verwenden möchte, muss man ja
mit inline asm das Timer-Register laden, einen gewissen Wert
hinzuaddieren (Startwert+Verstrichene Zyklen zwischen Laden und
Schreiben des Timers; deshalb auch ASM, da ist die Anzahl an Zyklen
bekannt).
Wenn nun aber der Timer von einem Benutzerdefinierten Wert hochzählen
soll (im C eingegeben oder gar berechnet), wie kann ich das dann
machen, dass der ASM weiß, mit was er addieren soll?
Sprich: Ist es sinnvoll ein Register (bekannt) als Variable definieren
und auf dieses Register via asm zuzugreifen? Wie geht das (in C)?
Oder ist es sinnvoller ein normaler Speicherbereich im RAM zu
verwenden, damit das Register für den GCC nicht dauerhaft "belegt"
ist? Wie gebe ich dann dem asm die Adresse? Wird ja schließlich zur
Compile-Zeit festgelegt.

MfG
Christian

von Karl H. (kbuchegg)


Lesenswert?

> deshalb auch ASM, da ist die Anzahl an Zyklen bekannt

Wenn jeder Zyklus wichtig ist, bleibt dir nichts
anderes übrig als auf Assembler zu gehen. Die meisten
C-Compiler haben einen inline-Assembler. Da kann man
dann Assembler Instruktionen in den C-Quellcode einbetten.

Meist ist das aber nicht notwendig.

von Christian Wolf (Gast)


Lesenswert?

Es geht um eine saubere Zeitbasis. Deshalb komme ich um inline asm nicht
herum. Das ist klar!

Mein Problem: Wie kann ich einen Wert zwischen C und inline asm
austauschen? Sprich: Wie kann ich dem inline asm eine Konstante z.B.
aus dem SPI oder ähnliches übergeben? Wie kann ich also ein Register in
C ansprechen? Wie kann ich es wieder freigeben, damit C es wieder
verwendet?

MfG
Christian

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Es geht um eine saubere Zeitbasis.

Dann nimm bitte nichts, wo du von der Code-Laufzeit abhängig bist.
Die Timer der aktuellen AVRs haben hier genug Möglichkeiten, dass
man das nicht mehr braucht (Stichwort: CTC mode, clear timer on
compare match).

von Christian W. (clupus)


Lesenswert?

Das hat aber einen deutlichen Nachteil: Ich bekomme nicht die
Genauigkeit, die ich will:

ICh will eine Quarz-Uhr bauen (hab es schon getan) und nun weiß ich,
dass normale Quarze nur eine Genauigkeit von einigen 10-25 ppm haben.
Mal von einer Quarzfrequenz von 2^22 Hz=4,194304 MHz aufgegangen,
bedeutet das, dass das Quarz in der Sekunde um bis zu 105 Takte von der
Nennzahl 4194304 abweicht (natürlich ist der Fehler konstant).
Nun möchte ich nach einiger Zeit der Uhr eine 2. Zeit einprogrammieren,
dei als Synchronisation fungiert: Er weiß, wieviel Takte in der
Zwischenzeit vergangen sind und jetzt weiß er noch vieviele es sein
müssten (der Benutzer kann ja etwa bis auf eine halbe Sec. genau
eingeben; da dürfte ein Monat Sync-Zeit schon ganz gut sein). Jetzt
kann er einen Korrekturfaktor errechnen.

Wenn ich aber hingehe und ihn diesen Korrekturfaktor via CTC einrechnen
lasse (prinzipiell ja möglich), erhalte ich 2 Probleme:
1.) Ich kann die Uhr nur schneller machen (Take übergehen); langsamer
machen kann ich nicht, da ich den Timer nicht erweitern kann.
(Planungsfehler, ok, aber damit muss ich nun leben)
2.) Die Genauigkeit ist miserabel. Egal, ob ich einen Presacler
einsetze oder ihn ohne Prescaler laufen lasse und anschließend manuell
eine Variable hochzähle die als "Postscaler" dient (mein Favorit, da
ich den Prescalor 1 für den anderen Timer brauche ;-)) in jedem Fall
kann ich nur um ganze Schritte im Timer korrigieren. Das bedeutet, dass
der 16-Bit Timer noch mit einem 6-Bit Pre/Post-Scalor ausgestattet
werden müssen. Damit wird aber eine Änderung von einem Takt am Ende zu
einer konkreten Änderung von 64 Takten. Damit könnte ich allenfalls die
Fehler einigermaßen in's Lot bringen; richtig weg bekomme ich die damit
nicht.

Ich sehe da einen besseren Weg:
Mit dem regelmäßigen Timer Overflow wird eine Subroutine ausgeführt,
die die Korrektur folgendermaßen vornimmt:
Ich gehe davon aus, dass bereits Korrektur-Daten vorliegen, die via C
aus dem EEPROM geholt werden. Nun wird bei jedem Overflow der Timer
(inline asm!!!!!!) in ein Register geholt, mit einem fixen Wert
(Korrektur für asm-Befehle) und dem Korrekturwert (ggf. subtrahieren)
addiert. Nun wird zurückgeschrieben.

Soweit hätte ich die selbe Auflösung wie bei CTC, nur könnte ich, da
der Timer schon weitergelaufen ist, auch noch Takte "anhängen.

Das gleiche wird nun aber auch bei jeder vollen Sekunde separaat
gemacht. Damit kann ich nun eine Sekunde mit nur einem Takt Fehler als
Basis erzeugen! Wende ich die Methode noch auf die Minuten an, dürfte
es nicht mehr merklich von der Sollzeit abweichen (da kommt die
Umstellung Sommer-/Winterzeit vorher ;-)). Ich kann es auch noch für
Stunden durchziehen, dann ist das Ding "doch recht genau".

Und jetz nicht sagen: Wie willst du die Korrektur-Daten so genau
eingeben? Ganz einfach: Der Controller zählt die Tage mit. So kann er
sich selbst im Laufe der Zeit synchronisieren, wenn der Benutzer ihm
regelmäßig die neue Zeit einstellt. (bei Sommer-/Witerzeit muss die
Sync-Funktion natürlich deaktiviert sein).

So, jetzt hoff ich ihr wisst, warum ich mit asm auf Werte aus C
zugreifen möchte und das nicht unbedingt über CTC lösen kann. Trotzdem
danke für die Idee.
Christian

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Du musst dir eigentlich nur ausrechnen, aller wie vielen Sekunden
du den Zielwert vom CTC einmalig entweder um 1 größer oder um 1
kleiner machen musst.  Nach diesem einen Zyklus schaltest du
wieder auf den Standardwert zurück.  Zum Umschalten des OCRs hast
du dann einen vollen CTC-Umlauf Zeit, das dürfte ja unkritisch
genug sein, oder?

von Christian W. (clupus)


Lesenswert?

Nein, da ich die Zeit nicht dehen kann. Ich hab das Quarz so gewählt,
dass ich mit einem 22-Bit-Teiler gerade auf 1 Sekunde komme. Ich kann
den CTC also entweder auf 2^16-1 (MAX) oder MAX-1 legen. MAX+1 wäre
aber nötig, um zu dehnen.

Zudem sehe ich keine Probleme das Ding mit ASM zu machen; entweder
inline oder externe Funktion. Find ich persönlich die bessere
Möglichkeit, insbesondere, da hier die Genauigkeit im Endeffekt höher
sein wird: Selbst wenn ich jeden Timer-Overflow eine neue Schranke TOP
festlegen würde, wäre das noch deutlich ungenauer.

Ich weiß nur nicht, wie ich
a) Eine Variable in GCC und in ASM verwende?
b) Eine ASM-Funktion von C aus aufrufe?
c) ob ich eine ASM-Datei ganz normal einbinden kann (#include
"Datei.S)?

MfG
Christian

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Nein, da ich die Zeit nicht dehen kann. Ich hab das Quarz so
> gewählt, dass ich mit einem 22-Bit-Teiler gerade auf 1 Sekunde
> komme. Ich kann den CTC also entweder auf 2^16-1 (MAX) oder MAX-1
> legen. MAX+1 wäre aber nötig, um zu dehnen.

Nun, erstens hättest du wohl mit meinem Vorschlag genauso gut einen
08/15 4,000-MHz-Quarz nehmen können, zweitens kannst du ja statt dem
1:64-Vorteiler einen 1:256-Vorteiler nehmen, dann ist der OCR-Wert
bei MAX/4.

> Zudem sehe ich keine Probleme das Ding mit ASM zu machen; entweder
> inline oder externe Funktion. Find ich persönlich die bessere
> Möglichkeit, insbesondere, da hier die Genauigkeit im Endeffekt
> höher sein wird:

Nur, wenn du keinerlei andere Interruptquelle hast.  Ansonsten hast du
ein Jitter.

> Ich weiß nur nicht, wie ich
> a) Eine Variable in GCC und in ASM verwende?

Eine externe?  Die kennt einfach der Linker, du kannst das Symbol also
im Assembler direkt benutzen.  Wenn du kommentieren willst, dass der
Linker das kennt, kannst du ja noch .extern SYMBOL schreiben, aber das
ist praktisch eine Null-Operation: sowie du SYMBOL benutzt und der
Assembler sonst keine Anweisung hat, woher er das nehmen soll, wird es
automatisch `undefined extern'.

> b) Eine ASM-Funktion von C aus aufrufe?

Genauso, wie du eine C-Funktion von C aus aufrufst.  Wenn du Parameter
übergeben willst, musst du dich an das ABI halten.  Steht in der
avr-libc-FAQ.

> c) ob ich eine ASM-Datei ganz normal einbinden kann (#include
> "Datei.S)?

Natürlich nicht: #include zieht die entsprechende Datei ja 1:1 in die
`current compilation unit' rein, d. h. der C-Compiler würde dann
deinen Assemblercode sehen.  Findet er sicher nicht so toll.  Du musst
sie separat assemblieren.

Vielleicht fängst du ja erst einmal mit der avr-libc-Doku selbst an?
Da steht schon einiges dazu drin...  OK, mixed C and assembly gibt's
erst in der nächsten Version, kannst du dir aber im CVS schon mal
ansehen:

http://cvs.savannah.nongnu.org/viewcvs/avr-libc/doc/examples/asmdemo/?root=avr-libc

von Christian W. (clupus)


Lesenswert?

Wie bekomme ich den "Mist" (sorry, ich hasse cvs, da ich nie verstehe,
wie das funkt.)? Ich kanns entweder manuell runterladen oder irgend
einen fertigen Befehl eintippen. Wie ich das sonst bekomme weiß icht
nicht.

MfG
Christian

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ja, wie du schon schreibst: entweder manuell runterladen (dafür
habe ich dir ja die ViewCVS-Links gegeben, die drei oder vier
Dateien sollten ja einigermaßen schnell gehen), oder mit einem
cvs checkout -- wie das geht, steht cut&paste-fähig hier:

https://savannah.nongnu.org/cvs/?group=avr-libc

> (sorry, ich hasse cvs, da ich nie verstehe,
> wie das funkt.)

Da frage ich mich nur, wie du deine Versionsverwaltung
organisierst...  CVS ist sicher nicht der Stein der Weisen, aber
ganz ohne eine Versionsverwaltung möchte ich auch meine privaten
Projekte nicht betreiben.

von Christian W. (clupus)


Lesenswert?

Hier wird aber, wenn ich das richtig interpretiere (nur kurz
drübergegagen), die .S-Datei auch an den avr-gcc übergeben, oder? Mit
welchem genauen Befehl (kenne mich in der Makefile noch nicht wirklich
aus ;-))? Wie wird dann dem Compiler beim Hauptprogramm eine Funktion
in der .S-Datei zugänglich gemacht? Unter welchem Namen ist eine solche
Funktion dann zu finden?

MfG
Christian

von Branko Golubovic (Gast)


Lesenswert?

@Christian

Die Lösung für dein Problem mit genaue Sekunde:
http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC

von Peter D. (peda)


Lesenswert?

@Christian

"Zudem sehe ich keine Probleme das Ding mit ASM zu machen; entweder
inline oder externe Funktion. Find ich persönlich die bessere
Möglichkeit, insbesondere, da hier die Genauigkeit im Endeffekt höher
sein wird: Selbst wenn ich jeden Timer-Overflow eine neue Schranke TOP
festlegen würde, wäre das noch deutlich ungenauer."


Das ist Quatsch mit Soße.

Die Genauigkeit ist exakt die gleiche, ob Du nun den Timer direkt
änderst oder den Comparewert.

Der einzige Unterschied liegt darin, daß Du Dir mit der Änderung des
Comparewertes bis zum nächsten Interrupt Zeit lassen kannst.


Schau Dir mal den Link von Branko an.


Peter

von kanal-service (Gast)


Lesenswert?

[color=indigo]Ïðîäàþ íîóòáóê Dell Latitude D600 - Pentium-M
1,4Ghz[/color]

[b]http://www.kanal-service.ru[/b]

[b]Îòêà÷êà æèäêèõ ñðåä[/b]
[b]Îêàçàíèå óñëóã ïî ïðîìûâêå, ïðî÷èñòêå, óäàëåíèþ çàñîðîâ[/b]
[b]Ãèäðîäèíàìè÷åñêàÿ ïðî÷èñòêà çàñîðîâ.[/b]
[b]Ìåõàíè÷åñêàÿ ïðî÷èñòêà êàíàëèçàöèîííûõ òðóá[/b]
[b]Ðó÷íàÿ ïðî÷èñòêà êàíàëèçàöèîííûõ òðóá[/b]
[b]Ïðî÷èñòêà è îáñëóæèâàíèå èíæåíåðíûõ ñåòåé[/b]
[b]Îòêà÷êà æèäêèõ ñðåä, òðàíñïîðòèðîâêà è óòèëèçàöèÿ îòõîäîâ ïîñëå
ïðî÷èñòêè[/b]
[b]ÒÅËÅÈÍÑÏÅÊÖÈß â êàíàëèçàöèîííûõ ñåòÿõ[/b]
[b]Ïðîêëàäêà, ðåìîíò è ïåðåêëàäêà èíæåíåðíûõ ñåòåé[/b]


Êîíòàêò: (812)+7(812)380-4140
http://www.kanal-service.ru

von r (Gast)


Lesenswert?


  

von Rolf Magnus (Gast)


Lesenswert?

Hmm, wo sind eigentlich die "Artikel melden"-Links hingekommen?

von ine56rty (Gast)


Lesenswert?


  

von Magnus Müller (Gast)


Lesenswert?

Rolf Magnus wrote:
> Hmm, wo sind eigentlich die "Artikel melden"-Links hingekommen?

Stimmt... jetzt, da du es erwähnst, fällt es mir auch auf...

von QWdastyWER (Gast)


Lesenswert?

Добрый день
Вы ищете РАБОТУ?
У Вас есть свой САЙТ  Вы хотите его  РАСКРУТИТЬ?
Мечтаете о СОБСТВЕННОМ перспективном БИЗНЕСЕ?
Мы НАУЧИМ как ЗАРАБОТАТЬ и  получать СТАБИЛЬНУЮ ПРИБЫЛЬ!
Ждем Вас на WWW.BYOPT.NET
вопросы сюда: byopt.net@list.ru


Будем рады оказаться вам полезными

von dschedsche (Gast)


Lesenswert?

lol

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.