Hallo zusammen, ich habe eine generelle Frage zur Verwendung des MSP430 Timers: Kann man den Timer zuverlässig auch ohne Interrupt per Polling und ohne Verwendung der CCRx-Units verwenden? Anwendung: Wenn ich bei meinem Mega AVR128 bisher keinen Interrupt benutzen wollte, dann habe ich das Zählregister mit einem Wert geladen, den Timer gestartet und das Interruptflag gepollt und bei Überlauf gestoppt! Dies funktioniert zuverlässig. Der Timer generiert eine 100us Zeitbasis, von der ich per Funktion dann auch Vielfache generieren kann -alles kein Problem, funktioniert wie gesagt. Ich wollte dies nun auch beim MSP430x169/1611 umsetzen. Beispiele zur Verwendung der CCR0-2 gibt es ja genug und diese funktionieren auch bei mir. Die TI-Beispiele bzw. die Ports für den MSPGCC zeigen aber eine gemeinsame Eigenschaft: sie nutzen alle ausschliesslich die CCR-Units und starten diese einmal, wobei die Interrupts vorwiegend genutzt werden, kein Polling. Ich habe mein o.g. Beispiel nun mit der CCR0 umgesetzt, habe aber immer wieder Probleme mit der Erzeugung des exakten Zeitintervalls. Im Unterschied zu den Beispielen starte und stoppe ich den Timer jedoch. Ist dies beim MSP430 ein Problem? Kann man das Interrupt-Flag zuverlässig auch im Polling-Betrieb abfragen? Weiterhin habe ich in einem weiteren Versuch die CCR0 ganz weggelassen und den Interrupt des TAR direkt genutzt. Auch hier lade ich das Register vor, starte den Timer und warte auf ein Setzen des Flags. Zur genauen Erzeugung der 100us-Basis habe ich die Latenzzeiten berücksichtigt. Nachdem ich nicht sicher war, ob das Interruptflag im Pollingbetrieb richtig gesetzt wird, habe ich das ganze mit Interrupt umgesetzt. Ich zähle in der ISR eine Variable herunter, um Vielfache der Einsprungzeit zu erzeugen. Unter Berücksichtigung der Latenzzeiten lief der Timer bei Vielfachen ungenau. Mir ist klar, dass hier der Code fehlt, es ist sehr spät und ich habe ihn momentan nicht zur Hand. Bitte dies zu entschuldigen. Mir geht es auch vielmehr darum zu erfahren, ob das Unterbrechen eines Timers speziell beim MSP430 zu Synchronisationsproblemen führt, wenn ich diesen immer wieder starte, beim AVR ist das kein Problem. Verwundert hat mich, dass in allen TI-Beispielen, die ich bisher gesehen habe, immer Zeiten mit der CCRx erzeugt werden, nie mit dem TAR direkt, obwohl ich dies bei durchlaufendem Timer mit Interrupt erfolgreich umsezten konnte. Bitte um Nachsicht, dass meine Erläuterung zu dem Thema etwas lang geworden ist, wäre aber sehr dankbar für jede Erfahrung von eurer Seite und vielleicht hilfreiche Tips, wo ich mehr erfahren kann. Habe nun drei Tage probiert. In den App.Notes konnte ich dazu nichts finden (?) Danke für's reinschauen, Gruss Gunb
@ Gunb (Gast) >Kann man den Timer zuverlässig auch ohne Interrupt per Polling und ohne >Verwendung der CCRx-Units verwenden? Verwenden ja, zuverlässig naja, klingt aber eher nach Unsinn. >benutzen wollte, dann habe ich das Zählregister mit einem Wert geladen, >den Timer gestartet und das Interruptflag gepollt und bei Überlauf >gestoppt! Dies funktioniert zuverlässig. Was soll der Quark? Du hast das Prinzip des Timers und Interrupts noch nciht verstanden. Nochmal drüber nachdenken. AVR-Tutorial: Timer [AVR-Tutorial: Interrupts]] >und starten diese einmal, wobei die Interrupts vorwiegend genutzt >werden, kein Polling. Was auch sinnvoll ist um a) die CPULast zu minimieren b) eine GENAUE Zeitbasis zu erzeugen, ohne sprodisch verschluckte Takte >Ist dies beim MSP430 ein Problem? Nein, DU hast ein VErständnisproblem. Der Rest der Welt nutzt Timer mit Interrupt ohne Probleme. >Kann man das Interrupt-Flag zuverlässig auch im Polling-Betrieb >abfragen? Nein. Das wird prinzipbedingt ungenau. >zähle in der ISR eine Variable herunter, um Vielfache der Einsprungzeit >zu erzeugen. Genau so muss es sein. > Unter Berücksichtigung der Latenzzeiten Welche Latenzzeiten? > lief der Timer bei Vielfachen ungenau. Dann hast du ihn falsch initialisiert oder sonstwo einen Programmierfehler drin. Poste mal etwas Sourcecode, als Anhang. >Mir geht es auch vielmehr darum zu erfahren, ob das Unterbrechen eines >Timers speziell beim MSP430 zu Synchronisationsproblemen führt, wenn ich >diesen immer wieder starte, beim AVR ist das kein Problem. Dort ist das auch ein Problem, du hast es nur nicht gesehen, warum auch immer. >habe, immer Zeiten mit der CCRx erzeugt werden, nie mit dem TAR direkt, Logisch, weil das das Timeregister ist, welches nur durchläuft. Das braucht man direkt beim AVR auch eher selten. MfG Falk
Hallo Falk, danke für deine Antwort. Eines mal vorweg: Es ist mir durchaus bewusst, dass Polling eine unprofessionelle "Lösung" darstellt, sie stammt auch nicht von mir, sondern war auf Atmel-Code bereits vorhanden. Messungen mit Scope haben jedoch gezeigt, dass diese für einfache Zwecke ausreichend war. Ich wollte sie nur probeweise auf den MSP portieren und testen, ob's hier genauso klappt. Keine Frage, programmiere für genaues Timing immer mit Interrupt, seit eh und je. ICH habe also kein Problem mit dem MSP430. Inzwischen habe ich den Fehler auch gefunden, es lag am Interruptflag des TAR-Überlaufs, das ich fälschlicherweise noch von der CCR0 übernommen hatte. Zuvor bekam ich nämlich nie einen Überlauf, daher meine Frage. Es sieht so aus:
1 | #define DELAY() TAR=0xFD29;while(!(TACTL&TAIFG));TACTL&=~(TAIFG)
|
2 | |
3 | void delay_100us(uint16_t wTime) |
4 | {
|
5 | while(wTime){ |
6 | DELAY(); |
7 | wTime--; |
8 | }
|
9 | }
|
ICH WEISS, DASS DIES NICHT SEHR SCHÖN IST! Ich hab's ja nur mal testen wollen und festgestellt, dass es auf dem Atmel genauer als auf dem MSP läuft. Was meine ich damit? Das Makro stellt die Zeit auf genau 100us ein. Ruft man die Funktion mit 1 im Argument auf, um 100us zu erzeugen, stimmt's exakt. Ruft man sie hingegen mit 10 auf, um 1ms zu erzeugen, dann messe ich mit dem Scope so ziemlich genau 948us - da hätte ich eher einen Wert grösser 1ms erwartet. Nun gut, schätze, da ist das Polling dann wirklich eine extrem schlechte Option. Der Mega128 läuft da auf jeden Fall genauer. Stimme dir aber uneingeschränkt zu, dass dies prinzipiell ungenau ist und keiner professionellen Umsetzung entspricht. Aber nun doch eine Frage, nur zur Klärung der Vollständigkeit halber: Was spricht dagegen, auf die CCRs gänzlich zu verzichten, wenn ich zum Beispiel nur einen simplen Timer brauche, der Überläuft und einen Interrupt erzeugt? Um es etwas zu konkretisieren: Ich starte den Timer A im Continuous-Mode, dann zählt das TAR-Register bis 0xFFFF und erzeugt beim Überlauf auf 0 einen Interrupt, durch den das TAIFG gesetzt wird. In der ISR kann ich dann per Abfrage das TAR als Quelle ermitteln, z.B. so:
1 | interrupt (TIMERA1_VECTOR) Timer_A(void) |
2 | {
|
3 | switch(TAIV) |
4 | {
|
5 | case 10: |
6 | TAR = 0xFFD6; |
7 | P6OUT ^= 0x80; |
8 | break; |
9 | }
|
10 | }
|
Ich meine, es funktioniert ja perfekt und wenn ich keine weiteren Zeiten benötige, warum dann die CCRs benutzen? An deiner Meinung wäre ich sehr interessiert, siehst du da irgendeinen Nachteil? Ich habe mich nur gewundert, warum die Beispiele einen einfachen Timer nicht auf dieser Basis berücksichtigen. Oder ist das zuuu trivial? Danke dir und einen angenehmen Tag, Gunb :-)
@ Gunb (Gast) >Was spricht dagegen, auf die CCRs gänzlich zu verzichten, wenn ich zum >Beispiel nur einen simplen Timer brauche, der Überläuft und einen >Interrupt erzeugt? Nichts. Aber du brauchst dazu den UP-Modus. Dann kannst du dir das Ganze ungenaue Rücksetzen sparen. MFG Falk
Wenn du das TAR verändern willst, musst du den Timer vorher anhalten, also in den Stopp-Modus bringen. Insgesamt ist das aber alles keine schöne Angelegenheit, weil man da leicht Jitter reinbekommt, je nach Taktfrequenz und Timertakt. Ich mache sowas, um Timer auf Funksensorknoten zu synchronidieren, die laufen aber bloß mit 32Khz und die CPU mit 6MHz, da geht das. Schau dir doch lieber mal die CCR-Geschichten an, die sind sowas von universell, das ist echt eine Freude, damit zu arbeiten. Schon mit dem Timer A kann man 3 unterschiedliche Zeitintervalle ohne CPU-Last erzeugen. Mit dem Timer B sogar 7.
@Falk: DU BIST MEIN HELD! MENSCH, DATT ISSET! Jetzt läuft datt Ding endlich so, wie es soll! TACCR0 geladen und TAR als Zähler - perfekt.Ich hab's vor lauter Bäumen nicht mehr gesehen, zu lange vor dem Compi gesessen ;-) @Chris: Hast natürlich Recht, ich nutze sie ja bereits seit Jahren. In dem oben geschilderten Fall hat mich aber mein Ehrgeiz gepackt und ich wollte einfach wissen, ob das mit dem MSP nicht auch ohne Weiteres geht. "Der muss das doch auch können", habe ich mir gedacht. Nutzen werde ich die CCRs, aber interessant ist's schon. Der Hintergrund ist der, dass ich Geräte entwickle, die per Gesetz gewissen Empfehlungen unterliegen. Wenn ich auch darauf an dieser Stelle nicht weiter eingehen kann, so sei dazu soviel gesagt, dass die Verwendung von Interrupts möglichst vermieden werden sollte. Wenn dies wahrscheinlich auch ein etwas Interrupt-ängstlicher Bürokrat geschrieben hat, so ist doch verständlich, warum der Code für den Atmel bereits das Polling verwendete. Ich wollte dies nun einmal auf dem MSP checken. Nutze aber trotzdem die CCRs :-)))) Danke euch für den Support! MfG Gunb
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.