Beim Code vom Roboternetz, nimmt man den Timer2 dazu, aller 10us einen Overflow auszulösen.
Dies geschieht, indem man den OCR in Abhängigkeit von der CPU-Frequenz setzt und bei erreichen des OCR-Wertes den Timer wieder auf null setzt (CTC=Clear Timer on Compare)
Code:
TCCR2 |= (1<<WGM21) | (1<<CS20); //Prescale=1, CTC mode
OCR2 = F_CPU/100000; //alle 10µS ein IRQ
In der entsprechenden Interrupt-Routine wir nun zum einen bis 2000 gezählt um 2000x10us = 20ms Periode zu erreichen. Ist der count unter bspw. 150(servopos) wird der Port angeschaltet (150x10us=1500ms), ansonsten wird er abgeschaltet.
Das Ganze kann man dann auf beliebig viele Servos ausweiten, indem man einfach die entsprechenden Ports und Servo-Positionen da mit einbaut.
Als Port nimmst du da die ganz normalen I/O-Pins, da das hier ja eher ein Software-PWM ist (das togglen der Pins wird ja vom Programmierer vorgegeben)
Ja und mit den Registern... ich red ja blöderweise auch die ganze Zeit vom Timer1, weil ich alle 3 PWM Channels benutze. Da kann man das noch angeben, beim Timer2 (den du ja benutzen willst) nicht.
Bei mir sieht das Ganze dann so aus:
Code:
cli(); //disable interrupts
TCCR1A |= (1<<WGM11)|(1<<COM1A1)|(1<<COM1A0); //9BIT PWM, inverted
TCCR1B = (1<<CS12); //Prescaler 256
// macht bei meinem 12MHz mega8 21.84ms
servo1_move(defaultPos); //setzt den OCR1A entsprechend
//TIMSK |= (1<<OCIE1A); //activate timer1 compare match interrupt for timing debugging
DDRB |= (1 << PB1); //set PB1 output
PORTB |= ( 1 << PB1 ); //set PB1 Pull up on
sei();
Was benutzt du zum programmieren? AVRStudio? Da kann man das relativ gut debuggen und sieht, was für Timings rauskommen. Spart man sich den Oszi.
Lesezeichen