DUE ungenauer Timer/Interrupt?

Mein Due soll in seiner endgültigen Behausung ein sauberes, genaues PPM-Signal erzeugen.

  • PPM ist eine aneinanderreihung von verschiedenen PWM-Signalen.

Bisher machte das ein MEGA, allerdings wünsche ich mir inzwischen mehr Performance für zusätzliche Aufgaben. Nötige Toleranz ist höchstens 3us (Mikrosekunden), besser unter 1. Der MEGA macht diese Aufgabe, das PPM-Signal zu erzeugen, absolut perfekt, sehr exakt und fehlerfrei, seit über einem Jahr.

Jetzt habe ich dazu einen Timer/Interrupt für den DUE geschrieben, aus Codefetzen die man so findet und bin mit dem erzeugten Signal absolut unzufrieden. Die Signale sind etwa 10% - 15% zu kurz. 100us rein, 83-86 kommen raus. Viele andere Zeiten bis 2500us getestet und statt 2500 kommen nur etwa 2100 an, das ist viiiieel zu ungenau.

#define kanalanzahl 8
#define rahmen 236250 //22500us
#define puls 3150 //300us
#define polaritaet 1
#define signalPin 10
uint16_t ppm[];

void setup() {

pinMode (signalPin, OUTPUT);
ppm[0] = 1050; //100; 
ppm[1] = 5250; //500; 
ppm[2] = 6300; //600; 
ppm[3] = 9450; //900; 
ppm[4] = 12600; //1200; 
ppm[5] = 18900; //1800; 
ppm[6] = 22050; //2100; 
ppm[7] = 26250; //2500; 

    pmc_set_writeprotect(false);    // Schreibschutz deaktivieren
    pmc_enable_periph_clk(ID_TC6);  // Timer 6 anschalten    
    NVIC_EnableIRQ(TC6_IRQn);
    TC_Configure(TC2, 0, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK2);   // Timer 6 Wave, zähle bis RC, 10,5MHz
    TC_SetRA(TC2, 0, 0); 
    TC_SetRC(TC2, 0, 100);   // erster Interrupt nach 100 durchläufen
    TC_Start(TC2, 0);   // Timer 6 starten    
    TC2->TC_CHANNEL[0].TC_IER=TC_IER_CPCS;   // IER = interrupt enable register
    TC2->TC_CHANNEL[0].TC_IDR=~TC_IER_CPCS;  // IDR = interrupt disable register    
}

void loop() {

}

void TC6_Handler(){
  static boolean state = true;
  TC_GetStatus(TC2, 0);
  
  if (state){
    digitalWrite(signalPin,polaritaet);
    TC_SetRC(TC2, 0, puls);
    state = false;
  } 
  else 
  {
    static byte cur_chan_numb;
    static unsigned int calc_rest;
    digitalWrite(signalPin,!polaritaet);
    state = true;
    
    if(cur_chan_numb >= kanalanzahl){
      cur_chan_numb = 0;
      calc_rest = calc_rest + puls;
      TC_SetRC(TC2, 0, (rahmen - calc_rest));
      calc_rest = 0;
    } 
    else 
    {
      TC_SetRC(TC2, 0, ppm[cur_chan_numb]); 
      calc_rest = calc_rest + ppm[cur_chan_numb] + puls;
      cur_chan_numb++;
      }
  }
}

Kann mir bitte wer sagen, wo ich den Fehler gemacht habe? Kann und Will nicht wirklich glaube das der TC im DUE so unpräzise ist.

Danke und Grüße