Hallo,
ich bekomme die Compare-Funktion am Timer1(16-Bit) einfach nicht zum
Laufen.
PD4 und PD5 werden einfach nur gesetzt, und dann passiert nix mehr.
Möglicherweise mache ich beim Schreibzugriff auf die
16bit-Compare-Register was falsch?
Hier mal der Code:
Initialisierung:
1
voidinit()
2
{
3
DDRD=0xFF;//Port D als Ausgang; Compare-Ausgänge liegen auf PD4 und PD5
4
TCCR1A|=(1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0);//Compare Match setzt die Ausgänge
Harald wrote:
> Möglicherweise mache ich beim Schreibzugriff auf die> 16bit-Compare-Register was falsch?
Nicht direkt falsch, aber Du solltest, wenn Du schon komfortabel in C
programmierst, auch die Möglichkeiten der 16-Bit-Zugriffe, die der
Compiler bietet, nutzen. Dann macht der Compiler nämlich die
Zugriffsreihenfolge automatisch korrekt. Also
1
OCR1A=0xAA00;
2
OCR1B=0x3300;
Und wenn Du das ganze noch übersichtlich machen willst, dann schreib
direkt den Dezimalwert rein, also
1
OCR1A=43520;
2
OCR1B=13056;
Dann hast Du direkt die Zykluszahlen vor Augen, und das ist doch das,
was man will...
Allerdings werden mit Deiner Konfiguration die Ausgänge tatsächlich nur
einmal gesetzt (so steht es im Kommentar), wenn das jeweilige
Compare-Ereignis eintritt, und dann passiert nix mehr. Wenn Du noch
sagst, was der Controller Deiner Meinung nach machen sollte , dann
kann man vielleicht noch weiterhelfen.
Hallo Johannes,
vielen Dank für Deine Antwort.
Ich finde die Stelle im Datenblatt jetzt leider nicht mehr, aber ich
könnte schwören, daß ich was gelesen hätte, daß die Ausgänge beim
Zählerüberlauf zurückgesetzt werden... ...wenn ich mich da täusche, ist
anatürlich klar, daß die gesetzt bleiben...
Gruß,
Harald
Harald wrote:
> Ich finde die Stelle im Datenblatt jetzt leider nicht mehr, aber ich> könnte schwören, daß ich was gelesen hätte, daß die Ausgänge beim> Zählerüberlauf zurückgesetzt werden...
Wenn Du einen PWM-Modus einstellst, dann werden sie auch bei Erreichen
des TOP-Wertes zurückgesetzt. Du hast aber keine PWM-Betriebsart
eingestellt, also klappt das so nicht. Schau mal in die Tabelle im
Datenblatt bei der Beschreibung der Steuerregister von Timer 1. Da
stehen die ganzen Modi und wie man die WGM-Bits entsprechend setzen
muss.
Hallo Johannes,
dann muss ich das verwechselt haben.
Ich möchte eigentlich den normalen Mode benutzen.
Wie bekomme ich die Ports dann zurückgesetzt? Die Compare Unit
überschreibt ja die "normale" Funktion der Pins, müsste ein einfaches
Zurücksetzen funktionieren, wenn man es an den Überlauf-Interrupt
bindet?
Gruß,
Harald
Harald wrote:
> Ich möchte eigentlich den normalen Mode benutzen.> Wie bekomme ich die Ports dann zurückgesetzt? Die Compare Unit> überschreibt ja die "normale" Funktion der Pins, müsste ein einfaches> Zurücksetzen funktionieren, wenn man es an den Überlauf-Interrupt> bindet?
Klar kann man den Zustand des Pins jederzeit "von Hand" (also im
Programm) ändern, aber wozu der Umstand? Der µC kann das auch ganz
allein, ohne Interrupt und so.
Hallo,
ich benötige die volle Auflösung des Timers für meine Anwendung, daher
der Aufwand. Wenn ich das Datenblatt richtig interpretiere, stehen mir
die vollen 16 bit nur im Mormalmodus zur Verfügung.
Gruß,
Harald
Harald wrote:
> ich benötige die volle Auflösung des Timers für meine Anwendung, daher> der Aufwand. Wenn ich das Datenblatt richtig interpretiere, stehen mir> die vollen 16 bit nur im Mormalmodus zur Verfügung.
Falls Du kein Input Capture verwendest, kannst Du den PWM-Modus mit ICR1
als TOP-Wert benutzen. Dann hast Du die volle Auflösung.
Hallo nochmal,
Bei dem ganzen geht es darum, daß ein Ventil, eine Zündvorrichtung und
ein Messlaser in einer genau definierten zeitlichen Abfolge angesteuert
werden sollen. Genau heißt in diesem Zusammenhang auf ca. 10...100us
genau. Dabei soll die Sequenz als Reaktion auf ein externes
Triggersignal ebenfalls innerhalb 10...100us gestartet und einmalig
durchlaufen werden.
ich hab jetzt versucht, das ganze, wie beschrieben, in einem der
PWM-Modi zu lösen, was daran scheitert, daß die Werte für die
Compare-Register erst beim nächsten Timerüberlauf übernommen werden. Lt.
Datenblatt ist das im Normalmodus nicht so; da werden die Werte sofort
übernommen.
Mein momentaner Lösungsansatz sieht folgendermaßen aus:
- wenn das Triggersignal ankommt, wird Timer1 gestartet und soll dann zu
den in den Comparregistern voreingestellten Werten die entsprechenden
Ausgänge setzen. Es soll also fogender Ablauf stattfinden:
Eingabe der Zeiten -> Startsignal -> übernahme der aktuellen
Compare-Werte in die Register -> Start des Timers -> Ausführen der
Compare Matches -> Timerüberlauf -> stoppen des Timers -> Eingabe der
Zeiten...
-In den PWM-Modi gibt es nun das Problem, daß die Werte erst beim
nächsten Überlauf tatsächlich in die Register übernommen werden. Da der
letzte Überlauf aber bereits eingetreten ist, wenn der Timer am Ende der
Sequenz gestopt ist, läuft der Vorgang erst nochmal mit den alten Werten
ab und erst beim übernächsten Durchlauf werden die neuen Werte
verwendet.
Im Normalmodus werden werden die Werte zwar sofort übernommen; dafür
konnte ich bisher nicht herausfinden, wie ich die Compare-Ausgänge
wieder zurückgesetzt bekomme (Was in den PWM-Modi automatich beim
Überlauf geschieht).
Oder ist der Timer überhaupt der falsche Lösungsansatz für diese Art
Problem?
Gruß,
Harald
Du kannst doch den Timer (im Normalmodus) einfach durchlaufen lassen und
jeweils im Interrupt Handler einen neuen Wert in das betreffende
Compare-Register laden. Den dazugehörigen Pin stellst Du auf "toggle at
compare match". Dann kannst Du im Prinzip beliebige Sequenzen erzeugen.
Beispiel:
Es soll ein 500 µs langer Impuls ausgegeben werden. Anschließend 1 ms
Pause. Dann ein 2 ms langer Impuls. Dann 5 ms Pause. Dann ein 200 µs
langer Impuls.
0.: Timer wird so getaktet, dass ein Takt 1 µs entspricht
1.: OCR1A = 500, Timer starten, Pin setzen (1)
2.: Wenn TCNT1 500 erreicht -> Compare Match Interrupt, gleichzeitig
wird der Pin automatisch auf Null gesetzt
3.: Im Interrupt Handler wird zu OCR1A 1000 hinzuaddiert (für 1 ms, in
OCR1A steht dann 1500)
4.: Nach insgesamt 1500 µs (also 1000 µs nach dem letzten Interrupt)
gibt's wieder ein Compare Match, Pin wird wieder 1
5.: Im Interrupt Handler zu OCR1A 2000 hinzuaddieren (für 2000 µs, also
2 ms)
6.: usw. Rest dürfte klar sein...
Im Prinzip kannst Du auch mit beiden Compare-Einheiten gleichzeitig
arbeiten, musst nur aufpassen, dass die sich bei zu kurzen Zeiten nicht
in die Quere kommen (Interrupt-Latenzen, Overhead durch die Interrupt
Handler).