Warum bestehst du nun auf den 10µs? Diese Variante ruft die ISR in einem 20ms-Zyklus genau Servos+1 mal auf. Viel Resourcenschonender gehts nimmer und das auch noch quasi fertig zur Verwendung. Du brauchst nur noch die Pins eintragen:
Code:
// Servoansteuerung mit 16Bit-Timer1 mic 10.1.2012
// Drei Servos an PD6,PC4 und PC6
// https://www.roboternetz.de/community/threads/56242-Problem-beim-Konfigurieren-von-TIMER1-beim-M32-Board
#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint8_t count_20ms;
volatile uint16_t servo[9] ={1700, 1700, 1700, 1700, 1700, 1700, 1111, 1111, 40000}; // Servopositionen
void sleep(uint8_t pause); // 1/50 Sekunde blockierende Pause
int main(void)
{
cli();
// für 16MHz-ATMega16
TCCR1A = (0<<WGM11)|(0<<WGM10); // CTC-Mode 4
TCCR1B = (0<<WGM13)|(1<<WGM12);
TCCR1B |= (0<<CS12)|(1<<CS11)|(0<<CS10); // prescaler /8
TIMSK = (1<<OCIE1A); // MatchCompare-Interrupt erlauben
//DDRB = 0b00000011; // Datenrichtung Servoausgänge setzen
//DDRC = 0b11111100;
DDRC |= (1<<PC6)|(1<<PC4);
DDRD |= (1<<PD6);
sei();
sleep(100);
while(1) // Demo
{
cli();
servo[0]=2500;
servo[1]=servo[2]=1600;
sei();
sleep(50);
cli();
servo[0]=servo[1]=servo[2]=1700;
sei();
sleep(50);
}
return(0);
}
ISR(TIMER1_COMPA_vect)
{
static uint8_t nr=8; // Nummer des aktuellen Servos
//PORTB &= ~0b00000011; // alle Servoimpulse low
//PORTC &= ~0b11111100;
PORTC &= ~((1<<PC6)|(1<<PC4));
PORTD &= ~(1<<PD6);
if(nr < 3) // Impuls für Servo oder Pause? (8 Servos)
{
//if(nr<2) PORTB |= (1<<nr); // Impulsleitung des aktuellen Servos
//else PORTC |= (1<<nr); // auf High setzen und
if(nr==0) PORTD |= (1<<PD6);
else if(nr==1) PORTC |= (1<<PC4);
else if(nr==2) PORTC |= (1<<PC6);
OCR1A = servo[nr]; // Impulslänge in OCR1A laden
servo[8] -= servo[nr]; // Impulslänge von der Pause abziehen
nr++; // nächstes Servo
}
else
{
OCR1A = servo[8]; // servo[8] ist die Impulspause
servo[8] = 40000; // Startwert 20ms laden
nr = 0; // beim nächsten ISR-Aufruf Impuls
// für Servo 0 erzeugen
if(count_20ms) count_20ms--; // blockierende Pause aktiv?
}
}
void sleep(uint8_t pause) // 1/50 Sekunde blockierende Pause
{
count_20ms=pause+1;
while(count_20ms);
}
Lesezeichen