Hi manhunt,

Zitat Zitat von manhunt
... vermutlich den Atmega168 ... Phase correct Mode ...
ja, das ist eine hübsche Möglichkeit - allerdings habe ich den Vorteil des Verfahrens bei meinen Anwendungen noch nicht überzeugend gefunden. Ich steuere von einem mega168 in diesem Modus (m)eine irLED:

Code:
/* ============================================================================== */
/* ==  PWM-Routinen zur IRLED-ansteuerung auf OC1A/PB1    ======================= */
  void TC1PWM_init(void)	//Init Timer/Counter 1, PWM-Signal 
{                               //       PWM aktivieren
   TCCR1A |= (1<<COM1A1);       //Clear/set OC1A on Compare Match           doc S132
				//   also Port PB3, vgl. auch PWM-routine unten
   TCCR1B |= (1<<CS10);         // cs10 <=> clk/1 => no prescaling         doc S 134
   TCCR1B |= (1<<WGM13);        // PWM, Phase+Frequency correct            doc S 134
   ICR1    = 278;               // =>PWM-Frequenz 20MHz/(2*278) => 36,0kHz/27,8µs
/* Interrupts deaktivieren. Siehe Registerbelegung :
mega168   Bit7       6        5         4         3         2        1        0
TIMSK1      –        –      ICIE1        –         –       OCIE1B   OCIE1A   TOIE1
im m168     ?        ?        ?         ?         ?         ?        ?        ?   */
//
   TIMSK1 &= ~(1<<OCIE1A);      // Tmr/Cntr1 Oput CompA/B Mtch intrrpt disab
   TIMSK1 &= ~(1<<OCIE1B);      // Tmr/Cntr1 Oput CompA/B Mtch intrrpt disab
   TIMSK1 &= ~(1<<TOIE1);	// Tmr/Cntr1 Overflow interrupt disabled
}
/* ============================================================================== */
  void setSRV1(uint16_t speed1)         //Relative Pulslänge auf OC1A/PB1
{OCR1A = speed1;}                       //  z.B. für SFH5110
/* ============================================================================== */
Diesen Modus gibt es (natürlich) auch bei anderen Controllern. Auf einem tiny2313 hatte ich mir damit eine SEHR feinfühlig arbeitende PWM für einen Servo gemacht:
Code:
// =================================================================================
// ======= Die untere Routine modifiziert für Servotester tiny2313    ==============
// =================================================================================
// ===  Routinen zur Interrupterzeugung auf OC1A/PB1    ============================
  void TC1TMR_init(void)	//Init Timer/Counter 1, PWM-Signal 
  {                             //       PWM aktivieren
    TCCR1B |= (1<<WGM13);       // ???                           doc S???
    TCCR1B |= (1<<CS11);        // cs10 <=> clk/8                           doc S111
                                 
    ICR1     =  25000;
    OCR1A    =  1000;
    TIMSK  |=  (1<<OCIE1A);      // Tmr/Cntr1 Oput CompA Mtch intrrpt enabld
    TIMSK  |=  (1<<OCIE1B);      // Tmr/Cntr1 Oput CompB Mtch intrrpt enabld
                                   
  }
// =================================================================================
// ===  Nicht unterbrechbare ISR für TIMER1_COMPA_vect   ===========================
// ==  Aufgaben: ISRoutine für den ca. 20 ms-Servozyklus
  ISR(TIMER1_COMPA_vect)        // 
  {                                
    PORTB ^=  (1<<PB1);         // Port toggeln	
  }                                
// =================================================================================
Der Bereich des Servosignals geht dabei von
Code:
//  for(loopSrv=500; loopSrv<3750; loopSrv++)   // Servoloop laufen lassen
. . . .           
      OCR1A     = loopSrv;
. . . .
und überstreicht damit etwas mehr als den zulässigen Bereich, in dem meine Servos arbeiten (können). Das Register ICR1 dient dazu, die Phasendauer der PWM auf ungefähr 20ms zu dimensionieren (Controllerquarz mit 20 MHz) und mit dem OCR1A wird die Rampe bemessen. Soweit die Hardwarefunktion. Um die Rampe dann wirklich korrekt zu bekommen, muss in der ISR der Ausgang getoggelt werden - ist ein bisschen tricky, läuft aber eben extrem feinfühlig. So feinfühlig braucht das aber wohl niemand, ich hatte das als Servotester gemacht.