Hey Leute, ich möchte mit einem atmega48 mithilfe des Timer1 drei Modellbauservos ansteuern. Allerdings habe ich das Problem, das der Chip keine Impulse mehr ausgibt wenn ich den Wert im OCR1A Register höher als 42000 einstelle. Dadurch kann ich meinen Servo nicht bis an die Endlage fahren. Hier mal ein Auszug aus dem Programm mit der Initialisierung des Timers und der dazu gehörigen ISR: ISR(TIMER1_COMPA_vect) { PORTB&=~((1<<PB0)|(1<<PB1)|(1<<PB2)); //aktuelleImpulsausgabe beenden Servo_Port = Servo_Bit[Servo_Nr]; //nächsten Impuls beginnen OCR1A = 44000; //die länge des nächsten Impulses festlegen TCNT1 = 0; //das Zählregister zurrücksetzen //die Zählvariable erhöhen, damit beim nächsten Durchgang der nächste Pin gsetzt wird Servo_Nr++; if(Servo_Nr==Servo_Anzahl){ Servo_Nr=0; } } int main(void) { DDRB|=(1<<PB0)|(1<<PB1)|(1<<PB2); //Ausgänge für die Servos TCCR1B |= (1<<WGM12)|(1<<WGM13)|(1<<CS10);//Timer1 im CTC initialiserien TCCR1A&=~((1<<WGM10)|(1<<WGM11)); TIMSK1 |= (1<<OCIE1A); //Interrupt für Timer1 freigeben ICR1H = 0xFF; //Top Wert für Timer1 festlegen ICR1L = 0xFF; //Top Wert für Timer1 festlegen sei(); } Das das ICR1 Register so beschrieben wird, war nur ein test, weil mir so langsam die Ideen ausgehen woran das liegen könnte. Danke schon mal im Voraus.
Mir fehlt in diesem Code
1 | int main(void) { |
2 | |
3 | DDRB|=(1<<PB0)|(1<<PB1)|(1<<PB2); //Ausgänge für die Servos |
4 | TCCR1B |= (1<<WGM12)|(1<<WGM13)|(1<<CS10);//Timer1 im CTC initialiserien |
5 | TCCR1A&=~((1<<WGM10)|(1<<WGM11)); |
6 | TIMSK1 |= (1<<OCIE1A); //Interrupt für Timer1 |
7 | freigeben
|
8 | ICR1H = 0xFF; //Top Wert für Timer1 |
9 | festlegen
|
10 | ICR1L = 0xFF; //Top Wert für Timer1 |
11 | festlegen
|
12 | sei(); |
13 | }
|
die Hauptschleife. Auch wenn es nichts zu tun gibt, MUSST du eine Hauptschleife haben! Selbst dann wenn sie leer ist. Du willst dein Programm niemals aus main() rauslassen. Denn dann kommt der Code zum Zug, der main() aufgerufen hat und der ... dreht als erstes die Interrupts ab. Das ist aber für dich fatal, denn du brauchst die Interrupts um die Pulse zu generieren! Also flugs ein
1 | while( 1 ) { |
2 | }
|
mit eingebaut. Zu deiner Timersache. Warum so kompliziert? Lass doch den Timer ganz einfach im normalen Modus durchlaufen. Kein CTC und auch kein ICR Register, einfach durchlaufen lassen mit aktiviertem Compare Match. Und in der ISR zählst du einfach zum OCR Register die gewünschte Zeit zum nächsten Compare Match dazu. Dann brauchst du auch den Timer nicht zurücksetzen.
1 | ISR(TIMER1_COMPA_vect) { |
2 | PORTB&=~((1<<PB0)|(1<<PB1)|(1<<PB2)); //aktuelleImpulsausgabe beenden |
3 | Servo_Port = Servo_Bit[Servo_Nr]; //nächsten Impuls beginnen |
4 | |
5 | OCR1A += 44000; //die länge des nächsten Impulses festlegen |
6 | |
7 | //die Zählvariable erhöhen, damit beim nächsten Durchgang der nächste Pin gsetzt wird
|
8 | Servo_Nr++; |
9 | if(Servo_Nr==Servo_Anzahl){ |
10 | Servo_Nr=0; |
11 | }
|
12 | }
|
das ist die allereinfachste Variante.
Hi Karl Heinz, erst einmal Danke für deine schnelle Antwort. In meinem richtigen Programm habe ich natürlich eine Hauptschleife. Diese habe ich nur nicht kopiert, weil ja eh nichts drin steht.^^ Und das mit dem addieren des OCR1A Register funktioniert? Wenn ich das richtig verstehe würde zum Beispiel wenn im einen Durchgang 48000 drin steht und im nächsten addiere ich 48000 dann kommt eine Zahl raus die größer ist als 16 bit und somit zu groß. Naja egal. Ich werde es mal probieren. Aber komisch ist es doch trotzdem das der timer keinen höheren OCR Wert zulässt.
Apfelsaft schrob: >zum Beispiel wenn im einen Durchgang 48000 drin steht und im nächsten >addiere ich 48000 dann kommt eine Zahl raus die größer ist als 16 bit >und somit zu groß. Nein, das ist ein Trugschluß: Es wird bis 65535 gezählt und dann springt es wieder auf 0. Es wäre also bei Deinem Beispiel so, daß wenn er 48000 drin stehen hat, noch 17536 Schritte bis 65535 und dann noch einmal 30464. Der nächste Zählerstand wäre also: 48000 (vom ersten Durchlauf)+48000 dazu vom nächsten Durchlauf ergäbe den neuen Stand von 30464. Es kann nicht "überlaufen", da der Kollege Zähler nur 16-Bit "hoch" ist, geht es nach dem Überlauf wieder von vorne los. MfG Paul
apfelsaft schrieb: > Hi Karl Heinz, > > erst einmal Danke für deine schnelle Antwort. In meinem richtigen > Programm habe ich natürlich eine Hauptschleife. Diese habe ich nur nicht > kopiert, weil ja eh nichts drin steht.^^ Dann bin ich raus. Ich mag es nämlich nicht, wenn ich mir den Kopf darüber zerbreche, was in deinem Code alles schief gehen könnte und wie der beobachtete Effekt erklärbar wird, wenn du dann gar nicht deinen richtigen Code zeigst. > Und das mit dem addieren des > OCR1A Register funktioniert? Wenn ich das richtig verstehe würde zum > Beispiel wenn im einen Durchgang 48000 drin steht und im nächsten > addiere ich 48000 dann kommt eine Zahl raus die größer ist als 16 bit > und somit zu groß. Eine Uhr hat ein Ziffernblatt auf dem 60 Sekunden markiert sind. Wenn der Sekundenzeiger auf 48 steht und die Uhr 23 mal tickt, auf welcher Zahl steht der Zeiger dann?
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.