16Bit Compiler Frage
-
BorisDieKlinge schrieb:
das programm in der schleife bleibt, die timer haben ein 1:1 prescale, d.h. dertimer wird jeden zykus erhöht, d.h. a und b werden imm unterschiedlich sein, weil dazwischen imemr inkrementiert ist ... seh ich das richt?
ja, wenn der timer jeden clockimpuls zählt dann ist jedes programm zu langsam dafür. aber wie pc() schon sagte, guck mal in die doku. da ist bestimmt ein latch zwischengeschaltet.
-
naja ich möchte frequenen von 0-30KHz messen, d.h. bei ner zyklus zeit von ~67nano sekunden, dauert eine periode biw 30KHz 497 timer inkremationen, würde ich den prescaler auf 1:16 htte ich zyklen zeit um die werte zu lesen, allerding wäre dann die frequenzmessung etwas ungeauer..
-
ahh.. dann hat sich meine "was ist ein latch" frage auch erledigt, d.h. im latch ist immer der wert des letzen timer zyklus gespeichert?
-
BorisDieKlinge schrieb:
... , die timer haben ein 1:1 prescale, d.h. dertimer wird jeden zykus erhöht, d.h. a und b werden imm unterschiedlich sein, weil dazwischen imemr inkrementiert ist ... seh ich das richt?
Siehst Du richtig, aber die Frage ist, ob Du den Timer erfindungsgemäß verwendest.
Wenn der mit einem Nanosekundenzyklus dahinrast, läßt man ihn üblicherweise beim Unterlauf einen Interrupt auslösen und zählt dann z.B. einen anderen Zähler weiter oder macht das, was (zumeist zyklisch) nach einer definierten Zeit getan werden muß.Als Uhr zum "zwischendurch Draufschauen" sind die Dinger nicht gedacht. Mit unkompensiertem Stoppen und Wiederstarten würdest Du Deine riesige Auflösung ja auch zerstören.
Wozu brauchst Du das eigentlich so genau?
-
BorisDieKlinge schrieb:
ahh.. dann hat sich meine "was ist ein latch" frage auch erledigt, d.h. im latch ist immer der wert des letzen timer zyklus gespeichert?
Nicht ganz. Ist ein getriggertes Register, mal salopp gesagt. Und der Trigger ist das Auslesen des Lo- oder Hi- Teil des Timers, daß der andere mitgespeichert wird.
-
BorisDieKlinge schrieb:
naja ich möchte frequenen von 0-30KHz messen, d.h. bei ner zyklus zeit von ~67nano sekunden, dauert eine periode biw 30KHz 497 timer inkremationen, würde ich den prescaler auf 1:16 htte ich zyklen zeit um die werte zu lesen, allerding wäre dann die frequenzmessung etwas ungeauer..
Je nachdem, wie oft Du ein Meßergebnis brauchst, empfehlen sich u.U. spezielle Timer- Modi:
- Meist haben Timer auch die Möglichkeit, "gated" zu arbeiten, behelfsweise kann man sich ein Gate auch aus 'nem normalen Interruptpin schnitzen.
- Eventuell kommt auch ein Event Counter Modus in Frage, dessen Stand Du gegen einen internes Zeitnormal vergleichst.
- Oft können sie von sich aus Pulsweiten messen.Echt, hilft nur eins ->> Doku lesen!!
-
hey pointer.. ja ich hab mal bischen gelesen;) da gibts Input Capture Timer modi, welcher den timerwert bei steigender flanke und/oder wieder bei fallender flanke in einem interrupt zurück gibt o.ä. ! Gated accumulation mode stoppt und startet den timer ..
das ist ja schon mal wunderbar, aber ich würde gern ein 32bit timer haben, mein PIC 30F4011 kann aus zwei 16bit timer ein 32bit timer (emulieren) leider funktioniert die kombination 32bit timer und "input capture" bzw. "gated accumukation" nicht.
-
BorisDieKlinge schrieb:
... aber ich würde gern ein 32bit timer haben, mein PIC 30F4011 kann aus zwei 16bit timer ein 32bit timer (emulieren) leider funktioniert die kombination 32bit timer und "input capture" bzw. "gated accumukation" nicht.
Kommt drauf an, was Du brauchst. Bei 67 ns Zyklus kommst Du mit 16 Bit auf so 230 Hz runter (1/(65536 * 67,5 ns), bevor er in den Unterlauf kommt.
Wenn Du weiter runter willst: Guck' mal nach, ob er auch bei Unterlauf einen Interrupt generiert. Mittels dieses Interrupts kannst Du Dir einen Merkzähler generieren.
Beim Flankeninterrupt (gated) sollte der Timer stehen bleiben, Du kannst einfach das, was im Zähler steht plus Merkzähler * 65536 als Gesamtticks annehmen. Vorteil: Du kriegst ohne Frickelei genaue Ergebnisse
Achtung:Aufpassen, wie Du Dein Gate einstellst, Standard ist einmal fallend = los geht's, einmal steigend = Stop. Das ist eine Pulsweitenmessung und bei unsymmetrischen Signalen mißt Du dann natürlich Käse. Besser über die volle Periode messen, das wäre z.B. zweimal fallend, wenn das geht.
Wenn Du partout auf den 32 Bit- Betrieb nicht verzichten magst, legst Du Dein Meßsignal auf einen normalen externen Interruptpin, der flankengetriggert betrieben Dein Gate darstellt. Beim ersten Auslösen resettest und startest Du den Timer, beim zweiten stoppst Du ihn wieder. Hat einen Nachteil: Das resetten und Starten sowie das Stoppen stellen einen Zeitoffset dar, der im oberen Frequenzbereich relevant wird und kompensiert werden sollte. Vorteil: Du mißt definitiv über eine volle Periode des Meßsignals.
Aber wie gesagt, es müssen nicht immer 32 Bit sein
-
genau, hab mir auch schon überlegt ob ich bei 16Bit bleibe, und bei jedem überlauf interrupt eine merker hochszähle. dann "Merker* 0xFFFF + TimerWert". die Variante ist ja rel. einfach.. aber ist sie auch sauber? ich weis das beim differenzbildung zweiter timerwerte bzw. rücksetzen des timers zeit verloren geht, aber die geht ja (wenn ich ne periode messe) bei beiden flanken gleichviel verloren, d.h. es gibt ne verschiebung, welche aber dennoch stimmt oder?
ich will so 10hz -30khz messen. ich kann den pic auch noch hochtackten dann hab ich ne zykluszeit von ~37,5nanosekunden. Würd ich den Merker auf auf ein byte beschränken könnte ich max. (0xFF*0xFFFF) + 0xFFFF) == 16776960*37,5 == 639,136ms == ~1,56Hz runter und max. wenn ich die oprationen bei jedem interrupt brücksichte dich vll. 2mircosekunde gehen ca. 50 operationen + 1mircosekunden reserver == 3 mricosekunden kürzeste periodendauer zwischen zwei flankeninterrupte =333Khz d.h. wenn ich bi s30kz messen will wird die messung ziemlich genau sein?
seh ich dar richtig... kostet es mehr zeit den timer zurückzusetzen bei jeder periodenmessung, oder den timer durchlaufen zu lassen und immer differenz bilden?
grüße
EDIT: Zuweisung eines wertes an eien variable dauer 2 zyklen oder?
1. Wert in in accu setzen
2. accu des registers zuweisen?Zurückstzen eines Variable dauer ein zyklus oder CLR?
1. CLR befehl auf register
differenzbildung (16bit) 4 zyklen?
1. Wert A in accu1
2. Wert B in accu2
3. Werte subrtrahieren in accu1
4. Accu1 zurückscreiben in wert?P.S.: hab mich sehr wenig mit assambler beschäftig bzw. ist schon lange her.. die anzahl er zyklen ist hier mal spekulation;)
Muss ich den timer anhalten bevor ich ihn zurücksetze?
-
BorisDieKlinge schrieb:
genau, hab mir auch schon überlegt ob ich bei 16Bit bleibe...
wenn du was 32 bittiges suchst, dann empfehle ich 'nen LPC2xxx von NXP. ARM7-basiert und so. sehr zuverlässige teile. für deine anwendung vielleicht etwas überdimensioniert, aber kosten auch nicht die welt (10€ etwa).
-
BorisDieKlinge schrieb:
genau, hab mir auch schon überlegt ob ich bei 16Bit bleibe, und bei jedem überlauf interrupt eine merker hochszähle. dann "Merker* 0xFFFF + TimerWert". die Variante ist ja rel. einfach.. aber ist sie auch sauber?
Sie ist es, wenn der Timer nicht stehenbleibt, sondern bis zum Periodenende weiterläuft. Es ist die präzisetste Methode, wenn der Timer zwei gleiche Flanken als Start und Stop triggern kann, dann kriegst Du eine Periode.
BorisDieKlinge schrieb:
ich weis das beim differenzbildung zweiter timerwerte bzw. rücksetzen des timers zeit verloren geht, aber die geht ja (wenn ich ne periode messe) bei beiden flanken gleichviel verloren, d.h. es gibt ne verschiebung, welche aber dennoch stimmt oder?
Kannst Du nicht so pauschal behaupten. Vor allem: Welche Differenzen willst Du bilden, eine Periode ergibt einen Meßwert. Da Du eh nur jede zweite Periode messen kannst, hast Du alle Zeit der Welt, alles Mögliche zu berechnen und die Hardware für die nächste Messung klarzumachen.
BorisDieKlinge schrieb:
... wenn ich bi s30kz messen will wird die messung ziemlich genau sein?
Ja, ziemlich.
BorisDieKlinge schrieb:
seh ich dar richtig... kostet es mehr zeit den timer zurückzusetzen bei jeder periodenmessung, oder den timer durchlaufen zu lassen und immer differenz bilden?
Schau, richtig ohne Gemurkse messen kannst Du nur jede zweite Periode, entweder Dein Timer beherrscht das Gate über die Periode oder Du setzt einen Frequenzteiler davor.
Alternative: Du bastelst das mit einem Interruptpin und startest/stoppst den Timer per Software, dann kannst Du auch guten Gewissens den 32 Bit- Modus hernehmen.
Differenzen aus Snapshots zu bilden, haut bei Dir nicht sinnvoll hin.BorisDieKlinge schrieb:
Muss ich den timer anhalten bevor ich ihn zurücksetze?
Ich habe die PICs Mitte der 90er ganz weit aus dem Fenster geworfen und nie wieder angeschaut ==> Manual lesen
-
pointercrash() schrieb:
richtig ohne Gemurkse messen kannst Du nur jede zweite Periode...
wieso das? von einer flanke bis zur nächsten mit der selben steigung ist's genau eine ganze periode.
-
hehe, ja das DEMOBOARD von Mircochip mit nem PIC lag vor meinen augen.. hätte auch lieber nen Atmel Atmega gecoded... naja aber ich kann jetzt messen 1hz bis 30khz.. muss aber noch rumprobieren..
P.S.: Schau mal ins Assambler Forum da hab ich noch ne Aufgabe für dich;)
-
rechteck-freak schrieb:
wieso das? von einer flanke bis zur nächsten mit der selben steigung ist's genau eine ganze periode.
Ja, und diese zweite Flanke ist ja schon der Beginn der nächsten Messung. Sauber kriegst Du damit nur jede zweite Periode. Weil wir schon so lange keine Zeile C mehr hatten, hab' ich mal ein Softgate für den M16C zusammengetippelt (not debugged), damit klar ist, wie so eine Messung ablaufen könnte:
static unsigned long int cycles = 0; // our result static unsigned char reminder = 0; void TimerInit(void) { tb0mr = 0x40; // Timer Mode %0100 0000 normal Timer tb0= 65535; // full range tb0ic = 0x05; // Timer Underflow Interrupt enable int0ic = 0x06; // int0pin = Gate falling edge } #pragma INTERRUPT Gate // Vector int0 void Gate(void) { const unsigned long int compensation = 117; // Timer cycles of constant delay if (tb0s) // Timer running ? { tb0s = 0; // Timer stop cycles = compensation + (unsigned long int)(65535 - tb0) + ((unsigned long int) reminder) * 65536; tb0 = 65535; // reset timer reminder = 0; // reset underflow } else tb0s = 1; // start timer } #pragma INTERRUPT Underflow // Vector tb0 void Underflow(void) { reminder++; }
Alles klar?
EDIT: Mir ist jetzt auch wieder eingefallen, was das Problem mit der Messung aller Perioden war, nicht die Genauigkeit beim Timer, sondern daß der Kiste zuwenig Verschnaufpause zum Herumrechnen bleibt, wenn's mal wirklich flott zugeht, da war mir die Gefahr zu groß, daß durch Interruptverlust die Ergebnisse verderben:
Aber probieren geht manchmal über Studieren. Müßte man nur so ändern
#pragma INTERRUPT Gate // Vector int0 void Gate(void) { static unsigned long int timer; // static => faster static unsigned long int rem; const unsigned long int compensation = 93; // Timer cycles of constant delay tb0s = 0; // Timer stop timer = tb0; // rescue the ... rem = reminder; // datas! tb0 = 65535; // reset timer reminder = 0; // reset underflow tb0s = 1; // restart timer cycles = compensation + (unsigned long int)(65535 - timer) + rem * 65536; }
Daß man sich den Underflow sparen könnte, wenn der Timer in 32 Bit läuft, muß ich nicht extra erwähnen, oder?