Generating 1 MHZ PWM on Due

You have several ways to generate a PWM pulse:

  • For a fixed 50% duty cycle, you can use PMC_PCKx up to 480 MHz
  • For different duty cycles, you can use either Timer Counters (section 36 of Sam3x datasheet), or PWMHx/Lx (section 38 of Sam3x datasheet).

See below a snippet to generate a 1 MHz PWM with a 50% duty cycle:

/******************************************************************************/
/***               1MHz/ 50% Duty cycle PWM thru TIOA0                      ***/
/******************************************************************************/

void setup() {

/*************  Timer Counter 0 Channel 0 to generate PWM pulses thru TIOA0  ************/
  PMC->PMC_PCER0 |= PMC_PCER0_PID27;                      // Timer Counter 0 channel 0 IS TC0, TCO power ON
  PMC->PMC_PCER0 |= PMC_PCER0_PID12;                      // PIOB power ON, page 38
  
  PIOB->PIO_PDR |= PIO_PDR_P25;
  PIOB->PIO_ABSR |= PIO_ABSR_P25;                        // PB25 is driven by the TC, peripheral type B, page 858

  TC0->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1  // MCK/2, clk on rising edge
                              | TC_CMR_WAVE               // Waveform mode
                              | TC_CMR_WAVSEL_UP_RC        // UP mode with automatic trigger on RC Compare
                              | TC_CMR_ACPA_CLEAR          // Clear TIOA0 on RA compare match
                              | TC_CMR_ACPC_SET;           // Set TIOA0 on RC compare match


  TC0->TC_CHANNEL[0].TC_RC = 42;  //<*********************  Frequency = (Mck/2)/TC_RC  = 1 MHz
  TC0->TC_CHANNEL[0].TC_RA = 21;  //<********************   Duty cycle = (TC_RA/TC_RC) * 100 = 50 %

  TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC0 counter and enable

}

void loop() {
 
}