Hallo, die PIC32 MCUs haben 5x 16 Bit Timer. Wie kann ich sehen wieviel Zeit vergehen muss, damit ein Timer um 1 hochgezählt wird? Kann ich zur Laufzeit etwa in einer Init Funktion festlegen, das Timer A nach 10 us und Timer B nach 1 ms um 1 hochzählen soll? Grüße
Tikonteroga schrieb: > Kann ich zur > Laufzeit etwa in einer Init Funktion festlegen, das Timer A nach 10 us > und Timer B nach 1 ms um 1 hochzählen soll? Steht das nicht im Manual? Ja, ich liebe (hasse) das Manual auch, wenn ich die Lösung sofort benötige. ;-) Bei den kleinen PICs 12F675 benutze ich den Predivider, und lade im Interrupt den Timer mit einem präzisen Wert nach. Das geht dort ganz gut. Mit dem Predivider vorne dran ist es auch ganz egal, ob bei der Nachladung mal ein paar mehr oder weniger Taktzyklen vergangen sind. Denn die synchrone Taktzählung ist von der Nachladung unabhängig.
Also im Manual wird das wohl drinn stehen. Aber ich hab im Mcu Bereich nicht so die Erfahrung und kann auch niemand sonst fragen. Mein Gebiet ist eher .Net, JAVA und Win32 C++. Deshalb hab ich den Beitrag erstellt. Meine Aufgabe ist es zur Zeit zu prüfen, ob der PIC32 diverse Anforderungen erfüllt ohne es vorab in der Praxis ausprobieren zu können.
Tikonteroga schrieb: > Aber ich hab im Mcu Bereich > nicht so die Erfahrung und kann auch niemand sonst fragen. Also, normalerweise kann man mit dem MCU-Takt und den Angaben im Manual berechnen, wie lange ein Timertakt braucht. Man braucht da überhaupt gar nichts zu probieren.
Tikonteroga schrieb: > Wie kann ich sehen wieviel Zeit > vergehen muss, damit ein Timer um 1 hochgezählt wird? Die Frage ist, was genau meinst du mit Auflösung? Die Länge des Timerregisters hat nur geringe Bedeutung, denn du kannst den Zähler softwaremässig um beliebig viele Bits erweitern. Wie lange ein einzelner Zählschritt dauert, ist dagegen eine komplexere Frage, die nur aus dem Datenblatt zu klären ist (aus dem speziellen für den Prozessor, nicht allgemein für PIC32). In den meisten Fällen kann der Timer maximal mit einem bestimmten Bruchteil der Quarzfrequenz zählen, z.B. /4, dazu gibt es (oder auch nicht) Vorteiler mit bestimmten Teilerfaktoren, vorzugsweise /2, /4, /8 usw., und es gibt (oder auch nicht) die Kaskadierung von Timern, so dass Timer1 als Vorteiler für Timer2 arbeitet, wobei beide programmierbar sind (das ist nicht das gleiche wie ein doppelt so langes Timerregister). Es gibt wahrscheinlich noch mehr Variationen, die mir gerade nicht einfallen, bei vielen µC ist das Timersystem das Komplexeste am ganzen Controller. Gruss Reinhard
Also wenn ich das Manual so verstehen würde, dass ich das mal kurz berechnen könnte, dann hätte ich nicht gefragt. Ich habe vor ein Modul (Gpt.h + Gpt.c) für die 5 Timer zu entwickeln bzw. entwickeln zu lassen. Es soll u. a. folgende Funktionen geben. void Gpt_Init(); void Gpt_InitTimer(uchar timer, uchar resolution); void Gpt_StartTimer(ushort ticks, bool continue); Ich muss jetzt bewerten, ob das Morden PIC geht.
http://ww1.microchip.com/downloads/en/DeviceDoc/61105F.pdf http://www.microchip.com/forums/m616390.aspx http://www.microchip.com/forums/m641880.aspx http://www.microchip.com/forums/m654548.aspx
Tikonteroga schrieb: > Ich habe vor ein Modul (Gpt.h + Gpt.c) für die 5 Timer zu entwickeln > bzw. entwickeln zu lassen. Das ist schon das erste Missverständnis, die Timer sind keineswegs alle gleich. Tikonteroga schrieb: > void Gpt_InitTimer(uchar timer, uchar resolution); Das ist das 2. Missverständnis - resolution ist nicht frei wählbar. Der Vorteiler kann z.B. durch 2 teilen oder durch 4, aber nicht durch 3 - und bei einer Sorte von Timern gehen alle 3 Faktoren nicht. Du kannst also Resolution nicht vorgeben, sondern musst vorab prüfen, welche denn verfügbar sind, welche davon für dich geeignet, und welchen Timer man dafür benutzen kann. Ich kann schliesslich auch nichts dafür, dass Elektronik kompliziert ist, du kommst entweder damit klar oder nicht, aber ganz bestimmt schnitzt dir niemand Spezialtimer passend zu deinem Verständnislevel. Auch kein anderer Hersteller. Gruss Reinhard
Reinhard Kern schrieb: > Tikonteroga schrieb: >> Ich habe vor ein Modul (Gpt.h + Gpt.c) für die 5 Timer zu entwickeln >> bzw. entwickeln zu lassen. > > Das ist schon das erste Missverständnis, die Timer sind keineswegs alle > gleich. > > Tikonteroga schrieb: >> void Gpt_InitTimer(uchar timer, uchar resolution); > > Das ist das 2. Missverständnis - resolution ist nicht frei wählbar. Der > Vorteiler kann z.B. durch 2 teilen oder durch 4, aber nicht durch 3 - > und bei einer Sorte von Timern gehen alle 3 Faktoren nicht. Du kannst > also Resolution nicht vorgeben, sondern musst vorab prüfen, welche denn > verfügbar sind, welche davon für dich geeignet, und welchen Timer man > dafür benutzen kann. Also mit Resolution ist eine Art Enumeration gemeint. "NS" = 0, "US" = 1, "MS" = 2, "S" = 3 Ich habe gelesen dass ich für bestimmte Timer auch eine externe Clock verwenden kann. Bin ich flexibler, wenn ich eine externe Clock verwende? Es ist auch letztendlich so, dass die Timer eine unterschiedliche Auflösung haben müssen. Also z. B. einer mit "US" pro Tick, einer mit "MS" pro Tick und einer mit "S" pro Tick. Das ich eine NS pro Tick erreichen kann wäre "NICE-TO-HAVE". Ich müsste über einen der Timer (Timer 1 mit Realtime Clock ?) einen Timestamp realisieren. Hier bräuchte ich aber einen 32 bit Timestamp und ich habe aber nur einen 16 bit Timer. Könnte ich hier so vorgehen, dass ich eine zusätzliche 16 Bit Variable anlege. Diese initialisiere ich mit 0 und bei jedem Mal wenn im 16 Bit Timer eine Überlauf entsteht, inkrementiere ich die Variable in der Timer_Overflow ISR um 1. Wenn dann der Timestamp abgefragt wird, gebe ich einen 32 Bit Wert zurück, den ich aus dem Intehalt des Timer (0..15) und der Variable (16..31) zusammenbaue. Kann ich das so machen oder gibt es hier geeignetere übliche Vorgehensweisen?
16-Bit Timer und eine Zählvariable als Erweiterung auf 32 Bit geht natürlich. Alternative: Timerkombination2/3 (oder 4/5 etc.) im 32-Bit-Mode betreiben.
hast du im pdf oben die erste skizze angesehen? offensichtlich nicht. also ein beispiel timer1: der timer1 zählt die variable TMR1 mit einem gewissen takt hoch (lässt sich einstellen), erreicht TMR1 den wert von PR1, gitb's einen interrupt bei dem du irgendetwas machen kannst und gleichzeitig wird TMR1 wider auf 0 gesetzt. der timer zählt im hintergrund deiner applikation von alleine weiter. ich glaube aber, dass wenn du nach genauigkeit fragt und 'NS' bei dir für Nanosekunde steht, dass du einfach seeehr genau die länge eines impulses oder abstand zweier impulse messen willst. das machst du aber nicht über timer; oder nicht direkt.
So wie es sich anhört will er einfach eine Stoppuhr bauen und denkt, er brüchte für us einen Timer, für ms einen zweiten, für Sekunden einen dritten und für Minuten einen vierten. Und weil er es ganz genau haben will, für ns noch einen. Er versteht aber nicht, dass so ein Timer an den Takt des Prozessors, über einen Prescaler, womit man den Takt halbieren, vierteln, ... kann, gebunden ist. Ebenso gibt es noch ein Register das der Timer bei jedem "Geprescaledten"-Takte incrementiert und bei überschreiten eines bestimmten vom User eingestellten Wertes einen Interrupt auslöst und das Register des Timers dann wieder von 0 anfängt hochzuzählen, bis zum Interrupt, wieder 0, ... Durch diese Methode kann man einstellen, dass der Timer alle ms, oder alle us oder wann auch immer einen Interrupt auslöst. Diesen Interrupt verwendet man dann um die eine globale groß dimensionierte (DWORD) Variable, nennen wir sie, Tick, hochzählt. D.h. man kann einstellen, dass der Timer jede 1ms einen Interrupt auslößt. Im Interrupt wird dann Tick incrementiert. Darauß Sekunde, Minute und Stunde zu berechnen geht durch Mathematik und kann bei Bedarf geschehen, da braucht man nicht weitere Variablen oder Timer. Die feinere Auslösung von us oder gar ns bekommt man indem man den Prescaler möglichst deaktiviert und das Timer Register bei Bedarf ausließt und den momentanen Wert in us und ns umrechnet. Hätte er sich die Mühe gemacht und meine Links angeschaut, dann hätte er es auch selbst herausgefunden, denn dort steht alles drin. Das Allgemeine Paper von Microchip zum Timer bei PIC32 und etliche Foreneinträge die zeigen wie man einen Timer initialisiert und benutzt.
Tikonteroga schrieb: > die PIC32 MCUs haben 5x 16 Bit Timer. Wie kann ich sehen wieviel Zeit > vergehen muss, damit ein Timer um 1 hochgezählt wird? Google mal nach pic32 timer calculator
Frank M. schrieb: > So wie es sich anhört will er einfach eine Stoppuhr bauen und denkt, er > brüchte für us einen Timer, für ms einen zweiten, für Sekunden einen > dritten und für Minuten einen vierten. Und weil er es ganz genau haben > will, für ns noch einen. Nein das möchte ich nicht. Ich möchte, dass nach bestimmten Zeiten, die ein User vorgeben kann, zyklisch eine ISR aufgerufen wird, in der etwas bestimmtes gemacht wird. Dabei gibt der User diese Zeit in "NS", "US", "MS" oder "S" zuzüglich eines ganzzahligen Faktors an. Dies ist so vorgegeben, das kommt nicht von mir. > Er versteht aber nicht, dass so ein Timer an den Takt des Prozessors, > über einen Prescaler, womit man den Takt halbieren, vierteln, ... kann, > gebunden ist. > Ebenso gibt es noch ein Register das der Timer bei jedem > "Geprescaledten"-Takte incrementiert und bei überschreiten eines > bestimmten vom User eingestellten Wertes einen Interrupt auslöst und das > Register des Timers dann wieder von 0 anfängt hochzuzählen, bis zum > Interrupt, wieder 0, ... Das mit dem Interrupt ist schon klar. Ich habe jedoch nach Möglichkeiten gesucht, wie ich die vorgegebenen Zeiteinheiten auf die Hardware übertragen kann. Sicherlich kann ich die möglichen Zykluszeiten die der User auswählen darf so einschränken, das es mit dem Takt und den Prescalern passt, aber das entspricht nunmal nicht meinen Anforderungen. Der User sollte hier so flexibel sein wie es geht. Deshalb habe ich hier nachgefragt.
Jens Martin schrieb: > Tikonteroga schrieb: >> die PIC32 MCUs haben 5x 16 Bit Timer. Wie kann ich sehen wieviel Zeit >> vergehen muss, damit ein Timer um 1 hochgezählt wird? > > Google mal nach > > pic32 timer calculator Danke schön. Ich teste damit mal alles durch.
Tikonteroga schrieb: > Sicherlich kann ich die möglichen Zykluszeiten die der > User auswählen darf so einschränken, das es mit dem Takt und den > Prescalern passt, aber das entspricht nunmal nicht meinen Anforderungen. Wenn du mit der lieferbaren Hardware nicht auskommst, musst du dir wohl oder übel deine eigene bauen, so einfach ist das. Aber wenn du nicht einmal die Funktion eines µControllers verstehst, ist das völlig illusorisch. Du kannst es dir und uns auch ersparen, noch ein paarmal zu erklären, dass du mit der Funktion real existierender Prozessoren nicht einverstanden bist, die ändern sich deswegen ja nicht. Gruss Reinhard
Also falls deine Aufgabe so trivial einfach und simpel ist, dann reicht auch wieder ein einziger 32-Bit (oder gar nur 16-Bit Timer und ein bisschen mehr Code). Die Eingabe des Users kann man mit simpler Mathematik in us umrechnen und bspw. in 'Duration' speichern. Also 1 Min, 10 Sek, 40ms, 20us ergibt dann Duration = 70040020 Entweder du stellst den Timer fix auf 1us (was genau machbar ist) ein und incrementierst jedes mal eine globale Variable. In deinem Hauptprogramm vergleichst du diese mit Duration und machst bei Überschreiten des Wertes deine Aktion. Andere Möglichkeit: Angenommen dein PIC32 taktet mit 80MHz und du hast einen Prescaler von 8 drin, dann ist die Auflösung des Timers 100ns. D.h. alle 100ns wird das internet Timer Register incrementiert. Jeweils 10 Einheiten muss er zählen um eine us erreicht zu haben. Das bedeutetm die Duration rechnest du nun um auf den Wert den dein Timer Register haben muss, d.h. 70040020 * 10 = 700400200, schaltest den Interrupt ein und startest den Timer. Nach genau deiner Duration wird ein Interrupt ausgelöst. Falls du nun länger Warten willst, sodass ein 32-Bit Register nicht mehr reichen sollte, dann musst du halt ein paar mal im Interrupt eine zweite Variable hochzählen bis zu umschaltest, oder dein Konzept übderdenken, denn was bringt eine us Auflösung wenn er 1s lang laufen soll, das ist Schwachsinn. Aber wieder, wie so ein Timer funktioniert, und wie man ihn benutzt, naja, les dir halt die Threads durch, da steht doch alles. Und ich verstehe immmer noch nicht wozu du jetzt zig Timer brauchst und einen rießen Aufwand für so eine Kleinigkeit betreibst.
Frank M. schrieb: > Also falls deine Aufgabe so trivial einfach und simpel ist, dann reicht > auch wieder ein einziger 32-Bit (oder gar nur 16-Bit Timer und ein > bisschen mehr Code). > > Die Eingabe des Users kann man mit simpler Mathematik in us umrechnen > und bspw. in 'Duration' speichern. > Also 1 Min, 10 Sek, 40ms, 20us ergibt dann Duration = 70040020 > > Entweder du stellst den Timer fix auf 1us (was genau machbar ist) ein > und incrementierst jedes mal eine globale Variable. In deinem > Hauptprogramm vergleichst du diese mit Duration und machst bei > Überschreiten des Wertes deine Aktion. > > Andere Möglichkeit: > Angenommen dein PIC32 taktet mit 80MHz und du hast einen Prescaler von 8 > drin, dann ist die Auflösung des Timers 100ns. D.h. alle 100ns wird das > internet Timer Register incrementiert. Jeweils 10 Einheiten muss er > zählen um eine us erreicht zu haben. > Das bedeutetm die Duration rechnest du nun um auf den Wert den dein > Timer Register haben muss, d.h. 70040020 * 10 = 700400200, schaltest den > Interrupt ein und startest den Timer. Nach genau deiner Duration wird > ein Interrupt ausgelöst. > Falls du nun länger Warten willst, sodass ein 32-Bit Register nicht mehr > reichen sollte, dann musst du halt ein paar mal im Interrupt eine zweite > Variable hochzählen bis zu umschaltest, oder dein Konzept übderdenken, > denn was bringt eine us Auflösung wenn er 1s lang laufen soll, das ist > Schwachsinn. > > > Aber wieder, wie so ein Timer funktioniert, und wie man ihn benutzt, > naja, les dir halt die Threads durch, da steht doch alles. > Und ich verstehe immmer noch nicht wozu du jetzt zig Timer brauchst und > einen rießen Aufwand für so eine Kleinigkeit betreibst. Ich habe mir jetzt nochmal das Datenblatt durchgelesen und verstehe viele Stellen schon etwas besser. http://ww1.microchip.com/downloads/en/DeviceDoc/61105F.pdf Im Kapitel "14.3.5 16-bit Synchronous External Clock Counter Mode" steht, dass ich an den TxCK pin eine externe Clock anbinden kann. Kann ich hier z. B. jeweils ein zusätzliches Bauteil verbauen, dass dann einen Takt von 1 Hz (Timer 2, 1 Tick/s), 10 Hz (Timer 3, 1 Tick/100 ms), 100 Hz (Timer 4, 1 Tick/10 ms) vorgibt. Ich hätte gerne vermieden, dass die ISR ständig aufgerufen wird und globale Variablen hochzählen muss und nur ganz selten das macht, was sie eigentlich machen soll. Nach meinem Verständnis ist das eine Art "Polling" und das will ich ja gerade nicht. Bei so Stichwörtern wie "Polling" und "globale Variable" erscheint bei mir ein "Achtung !!! oder HALT !!!" im Sinn. Im Idealfall soll die ISR des Timers nur dann aufgerufen werden, wenn es an der Zeit ist, dass der Task ausgeführt wird, der durch das zeitliche Event getriggert wird. Es mag vielleicht sein, dass ich letztendlich nicht drummherum komme, das so zu lösen, aber jetzt in der Konzeptphase würde ich auch gerne ein Konzept ohne Polling und globale Variablen als Alternative ausarbeiten. Die Hardware wird auch nicht von mir gebaut, dass machen Leute mit E-Technik-Studion bzw. anderer Themenbezogener Ausbildung und Erfahrung. Ich mache nur den Projektvorschlag. Den PIC32 habe ich unter anderem deshalb ausgewählt, weil man hier die IDE, den Kompiler, einen Custom USB Treiber + Library, ... aus einer Hand bekommt. Ich habe mir aber auch Arm7, Arm9, Cortex M3/M4 angesehen.
Tikonteroga schrieb: > Ich hätte gerne vermieden, dass die ISR ständig aufgerufen wird und > > globale Variablen hochzählen muss und nur ganz selten das macht, was sie > > eigentlich machen soll. Die ISR wird doch nicht ständig aufgerufen!? Wenn du einen Timer mit 1ms extern Taktest und du möchtest das nach 1234ms ein bestimmtes Ereigniss ausgelöst wird, dann lädst du das Timerregister mit 64302 (2^16 - 1234). Erst beim Überlauf wird der INT ausgelöst.
Du hast das Prinzip des Timers noch nicht ganz verstanden: 1. Takt: Der kann vom Prozessortakt abhängen oder von eine externen geliefert werden. Ein externen wird gerne für eine RTC verwendet, da so der PIC im Stromsparmodus laufen kann, während die RTC im Hintergrund weiter laufen kann. Auch kommt es darauf an wie genau der Timer sein soll. Der PIC hat einen internen RC-Schwingkreis mit mäßiger Genauigkeit. Willst du es genauer, so kannst du den ganzen PIC mit einem externen Quarz noch versorgen, dennoch kann der Timer vom Takt des Prozessors abhängig bleiben. Muss sogar, da du sonst ja auch gar nicht deine us oder gar ns Auflösung hinbekommst. 2. Prescaler: Nun kann dieser Takt halbiert, geviertelt, ... werden um den Timer gröber zu laufen lassen, da nicht immer so ein schneller Timer (im Fall von 80MHz: 12.5ns) von nöten ist. 3. Timerregister: Es ist ein internes Register das bei jedem Timertakt incrementiert wird. Dieser Prozess läuft im Hintergrund in der Hardware, nicht in der Software. Dieses Register kann nun 16-Bit bzw. 32-Bit groß sein. D.h. interner Takt und kein Prescaler: Alle 12.5ns wird das Register incrementiert. 4. Ein zweites Register dient als Vergleich. In dieses Register kannst du einen Wert deiner Wahl eintrage. Erst wenn das Timerregister den Wert des Vergleichregisters übersteigt wird ein Interrupt ausgelößt. Nochmal: Das automatische incrementieren des Timers geschieht im Hintergrund in der Hardware. Mit Hilfe diesem Vergleichregister und einem geeignet gewähltem Prescaler kannst du so ziemlich jede erdenkliche Zeitspanne dir einstellen. Wie ich oben eben gerechnet habe. Schau dir doch auch endlich mal meine verlinkten Threads an. Dort ist ein Code Beispiel, dort steht geschrieben was wie gemacht wird. Vor allem: http://www.microchip.com/forums/m641880.aspx Und da den gelb hervorgehobenen Teil. Im Datenblatt schaue mal die Register: TMR.. und PR.. an. Das eine enthält den aktuellen Wert des Timerregisters, das andere den Vergleichswert bis zu dem er zählen soll bis er einen Interrupt auslöst.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.