Hallo zusammen,

seit ein paar Wochen versuche ich mit einem Atmega32 8 Servos anzusteuern, jedoch kamen einige Probleme auf mich zu.
Ich denke, dass ich alle Hardware-Fehler beseitigt habe, jedoch funktioniert noch nichts.

Zur Ansteuerung der Servomotoren wollte ich mich am Quellcode von der Seite
http://www.mikrocontroller.net/artic...vo_Ansteuerung
orientieren.

Ich habe alle Einstellungen mit dem Datenblatt des Atmega 32 verglichen und konnte keine Fehler oder Änderungen feststellen.
Des Weiteren arbeite ich mit 16MHz, nicht mit 11Mhz wie im Beispiel. Dies habe ich im Quellcode geändert.
Alle 8 Servomotoren sollen am PortC angeschlossen werden.

Code:
//
// Programm fuer einen ATmega32
//
#define F_CPU 16000000UL
 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
 
//
// Der Prescaler muss so gewählt werden, dass der Ausdruck
// für MILLISEC_BASE einen Wert kleiner als 128 ergibt
// MILLISEC_BASE ist der Timerwert, der 1 Millisekunde Zeitdauer ergeben
// soll.
//
#define PRESCALER      128
#define PRESCALER_BITS (1<<CS22) | ( 1 << CS20 )
 
#define MILLISEC_BASE  ( F_CPU / PRESCALER / 1000 )
#define CENTER         ( MILLISEC_BASE /2 ) 
 
//
// Konfiguration der Servoleitungen
//
#define NR_SERVOS      8
#define SERVO_DDR      DDRC
#define SERVO_PORT     PORTC
uint8_t ServoPuls[NR_SERVOS] = { 1<<PC0, 1<<PC1, 1<<PC2, 1<<PC3,
                                 1<<PC4, 1<<PC5, 1<<PC6, 1<<PC7 };
//
// Werte für die Servoposition
// Gültige Werte laufen von 0 bis 2 * CENTER
// 0           ... ganz links
// CENTER      ... Mittelstellung
// 2 * CENTER  ... ganz rechts
//
volatile uint16_t ServoValue[NR_SERVOS];
 
ISR (TIMER2_COMP_vect) 
{
  static uint8_t ServoId = 0;
 
  //
  // den Puls des aktuellen Servos beenden
  //
  SERVO_PORT &= ~ServoPuls[ServoId];
 
  //
  // welches ist das nächste aktuelle Servo?
  //
  if( ++ServoId >= NR_SERVOS )
    ServoId = 0;
 
  //
  // die Ausgangsleitung fuer dieses Servo auf 1; den Puls beginnen
  //
  SERVO_PORT |= ServoPuls[ServoId];
 
  //
  // den Timer so einstellen, dass bei Pulsende, die ISR erneut aufgerufen wird
  //
  OCR2 = MILLISEC_BASE + ServoValue[ServoId];
}
 
void InitServo()
{
  uint8_t i;
 
  //
  // Die Servoleitungen auf Ausgang stellen
  //
  SERVO_DDR = ServoPuls[0] | ServoPuls[1] | ServoPuls[2] | ServoPuls[3] |
              ServoPuls[4] | ServoPuls[5] | ServoPuls[6] | ServoPuls[7];
 
  //
  // Alle Servos in Mittelstellung
  //
  for( i = 0; i < NR_SERVOS; ++i )
    ServoValue[i] = CENTER;
 
  //
  // Timer auf CTC Modus konfigurieren
  //
  OCR2 = MILLISEC_BASE + ServoValue[0];
  TIMSK |= (1<<OCIE2);
  TCCR2 = (1<<WGM21) | PRESCALER_BITS;  // CTC mode
}
 
int main(void)
{
  InitServo();
 
  sei();
 
  _delay_ms( 1000 );
 
  //
  // testweise einfach alle 8 Servos ansteuern
  // jedes Servo soll sich unterschiedlich schnell bewegen
  //
  while( 1 ) {
     
    ServoValue[0] += 2;
    if( ServoValue[0] > 2*CENTER )
      ServoValue[0] -= 2*CENTER;
 
    ServoValue[1] += 1;
    if( ServoValue[1] > 2*CENTER )
      ServoValue[1] -= 2*CENTER;
 
    ServoValue[2] += 2;
    if( ServoValue[2] > 2*CENTER )
      ServoValue[2] -= 2*CENTER;
 
    ServoValue[3] += 3;
    if( ServoValue[3] > 2*CENTER )
      ServoValue[3] -= 2*CENTER;
 
    ServoValue[4] += 1;
    if( ServoValue[4] > 2*CENTER )
      ServoValue[4] -= 2*CENTER;
 
    ServoValue[5] += 3;
    if( ServoValue[5] > 2*CENTER )
      ServoValue[5] -= 2*CENTER;
 
    ServoValue[6] += 2;
    if( ServoValue[6] > 2*CENTER )
      ServoValue[6] -= 2*CENTER;
 
    ServoValue[7] += 1;
    if( ServoValue[7] > 2*CENTER )
      ServoValue[7] -= 2*CENTER;
 
    _delay_ms( 400 );
  }
}
Kann mir jemand meine Fehler aufzeigen? Bzw. mir einen Tipp geben?

Grüße High Light