PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Periodendauermessung Overlayvariable Verständnisproblem



gesamtplan
22.10.2009, 21:31
Hallo,

ich habe da ein kleines Verständnisproblem was den Overlayvariable machen. Ich habe eine sehr schönes Worddokument im WWW entdeckt wo einige Beispiele zum Bascom programmieren drin sind. Allerdings checke ich den Code nicht so ganz. (Was macht der Programmierer da?).

Das Grundprinzip ist der Periodendauermessung ist mir klar.
Warten bis Eingang = 0: definierter Beginn
Warten bis Eingang = 1
Zähler starten
Warten bis Eingang = 0
Warten bis Eingang = 1
Zähler stop
Zähler auslesen und Wert ggf. umrechnen



'Testprogramm für T-Messung über Timer0/Int0
'Messwerte:
'Tsoll Tmess /us
'10 keine Reaktion (Int nicht schnell genug)
'100 98
'1000 998/999
'10000 10010
'100000 100041
'1000000 1000424


'---------------------------------------------------
$regfile = "2313def.dat"
$crystal = 8000000
$baud = 2400


'Periodendauermessung benutzt Int0 und Timer0
Config Pind.2 = Input
On Int0 Int0serv
Config Int0 = Rising
Enable Int0

'Timer0 für Periodendauermessung
Config Timer0 = Timer , Prescale = 8 'Timer-CLK = 8MHz -> TCLK = 1us
Enable Timer0 'Overflow alle 256us
On Timer0 Timer0overflow

Enable Interrupts
'-----------------------------------------------------

'Variablen Periodendauermessung
Dim T As Long At &H60 'Periodendauer
Dim Tvaluel As byte At &H60 Overlay 'Periodendauer low byte
Dim Tvalueh As word At &H61 Overlay 'Periodendauer high word
Dim T0overflowctr As Word 'Zähler für Timer1Overflow

T = 0

'--------------------------------------------------------------------
Do

Print "T=";
print T;
print "us"

waitms 1000

Loop
'---------------------------------------------------------------------

Int0serv: 'Impulsflanke Lichtschranke
'Periodendauermessung
'Werte der alten Periodendauermessung übernehmen:
Stop Timer0
Tvaluel = Timer0 'Low word von T
Tvalueh = T0overflowctr 'High word von T

'neue Periode messen:
Timer0 = 0
Start Timer0
T0overflowctr = 0

Return

'-----------------------------------

Timer0overflow:
Incr T0Overflowctr 'wieder auf 1.Flanke warten
return
'-------------------------------------------




Allerdings kapier ich nicht, wie und vor allem warum die T-Variable aus zwei Overlayvariablen zusammengesetzt, die man sich aus den zwei Subroutinen holt, und wie dabei das Ergebnis stimmen kann? Kann mir das vielleicht jemand erklären?

Viele Grüße

R.

for_ro
22.10.2009, 23:00
Timer0 ist ein 8-bit Timer, d.h., wenn du ihn ohne Startwert laufen lässt, dann erreicht er nach 256 Schritten einen Overflow. Dies ist der Moment wo die ISR "Timer0overflow". Timer0 selber ist jetzt 0.
In der Variable T0Overflowctr zählst du nun die Anzahl der Aufrufe, also die Anzahl der Overflows.
Wenn du die Zeitnahme nun zu irgendeinem Zeitpunkt anhälst, ergibt sich die Zeitdauer aus der Anzahl der Overflows * 256 + den aktuellen Wert von Timer0. Also

T = T0Overflowctr* 256 + Timer0

Die Overlay Technik erlaubt dir nun, in T das Ergebnis zu bekommen, ohne es tatsächlich auszurechnen. Anstelle der Multiplikation mit 256 könntest du auch so etwas machen:
T = T0Overflowctr
shift T, left, 8
Du verschiebst also die Bits von T0Overflowctr in T an höherwertige Stellen. Mit dem Overlay schreibst du praktisch direkt auf diese höherwertigen Stellen.
T reicht im Speicher von Zelle &H60 bis &H63, da T ein Long-Typ ist. Das niegriedwertigste Byte (LSB) steht in &H60, in &H61 das nächst höherwertige. Und genau da wird T0Overflowctr (über Tvalueh) hingeschrieben. Timer0 wird dann noch (über Tvaluel) auf das LSB geschrieben.

Besserwessi
22.10.2009, 23:02
Die sache mit dem Overlay wird gemacht, um schnell den 8 Bit wert aus dem Timer 0 und den 16 Bit Wert von den gezählten Überläufen zusammenzustzen zu einer Zeit mit 24 Bit Auflösung, die dann in einer 32 Bit langen variable Steckt. Das wird gemacht statt so etwas zu schreiben wie: zeit = timer + 256 * ZahlDerÜberläufe
Die Multiplication ist ja einfach ein Verschieben um 1 Byte.

Im Prinzip kann das so funktionieren, allerdings nicht immer:
Wenn man Pech hat, gibt es gerade an Anfang in der Interruptroutine, noch vor dem Timer0 Stop einen Überlauf von Timer0. Da man sich noch in der ISR befindet wird dieÜberlauf ISR aber nicht mehr ausgeführt und der Überlaufzähler ist folglich um einen zu klein. So wie es aussieht ist das bei dem Beispielwert für 1s passiert, sonst wäre der Fehler nicht so groß. Wenn man will könnte man den Fall noch abfangen, indem man das Interruptflag abfragt.

Für eine wirklich genaue Messung sollte man aber lieber Timer1 und die ICP-Funktion nutzen.

gesamtplan
22.10.2009, 23:49
Danke für die Antworten. Aber ich glaube ich stecke nicht so tief im programmieren drin wie Ihr. Im Klartext ich verstehe nur spanische Dörfer. Ich freu mich ja quasi schon wenn eine Lampe blinkt. ;-)

Aber nun Spass bei Seite.
Das die Overlayroutinen die höheren Bits verschieben ist mir klar. Soweit konnte ich noch folgen.

Ich zähle also mit T0overflowctr die Überlaufe und nehme das zum schalten des 2^8 Bits in der Longvariable T, da sich ja bei jedem Überlauf den der Timer0 erfasst das "2^8 Bit" um 1 erhöht und somit Dezimalzahl 256 zu meinem Longwert T dazuaddiert wird. Verstehe ich das richtig?

Das Ergebnis ist schließlich die Periodendauer in µs.

Was ist die ICP-Funktion mit Timer1 wieso ist die Messung da genauer?

Besserwessi
23.10.2009, 00:37
Das mit dem Overlay scheint ja schon richtig verstanden. Das Zählen der Overflows gibt einfach weitere höherwertige Bits zu den 8 von der Timer Hardware.

Man kreigt nur dann die Zeiten in µs wenn der Timer mit 1 MHz läuft.

Die ICP Funktion von Timer1 ist genau dazu da genaue Zeitmessungen zu machen. Wenn die gewählte Flanke auftritt, wird in Hardware der Zählerstand in extra Register kopiert und ggf. ein Interrupt ausgelöst. Man kann da die Zeit bis auf 1 Taktzyklus genau messen, denn die eigentliche Messung (= kopieren des Zählerstandes) macht die Hardware.

Mit den Interrupt so wie im Beispiel oben, hat man immer noch eine nicht ganz konstante Verzögerung bis der Interrupt auslöst. Meistens sind es nur +-2 Zyklen, aber wenn mal Interrupts gesperrt werden, oder wenn gerade ein Overflow kommt, kann es deutlich länger werden.

Bei Timer1 hat man außerdem gleich 16 Bits in Hardware. Für Einige Anwendungen kann das reichen. Damit wird dann auch die Programmierung einfacher, vor allem wenn man das Zählen der Überläufe richtig machen will.

gesamtplan
23.10.2009, 00:51
Dann hab ich wieder was gelernt. Ein guter Tag quasi.

Wenn ich also den Timer1 benutze um in der Interruptroutine den Stand zu zählen, wie kann ich dann Wert den das ICP erhält dann auslesen? Da gibts doch sicher ne Varibale die mir den Zugriff aufs ICP ermöglicht bzw. den Interrupt ausslöst? Wie programmiere ich denn sowas?

Besserwessi
23.10.2009, 11:03
Wenn die Zeiten nicht so groß sind, oder die Auflösung nicht so hoch sein muß, kommt man eventuell auch mit den 16 Bit aus, und muß gar nicht von Hand die Auflösung erweitern.
Wie weit die ICP direkt von BASCOM unterstützt wird, weiss ich nicht. Eventuell wird man das mit direktem Zugriff auf die Registsr machen müssen, so wie in C. Ein Beispiel in C ist hier :
http://www.rn-wissen.de/index.php/Timer/Counter_(Avr)#Input_Capture
Nicht erschrecken wegen der Länge, etwa die Hälfte ist die Ausgabe und hat mit dem Timer nicht viel zu tun.