Complementary PWM channels Output

I'm using the following code to synchronize three channels and output a pair of complementary outputs per channel.

void setup() {

  PMC->PMC_PCER1 |= PMC_PCER1_PID36; //Enable PWM (Power On)

  PWM->PWM_DIS = PWM_DIS_CHID0;       //Disable PWM on Channel 0
  //PWM->PWM_DIS = PWM_DIS_CHID1;

  PIOC->PIO_PDR |= PIO_PDR_P3 | PIO_PDR_P5 | PIO_PDR_P7; // Setting pins 3,5,7 (DUE Pins 35, 37, 39) to PWM Peripheral, not GPIO
  PIOC->PIO_ABSR |= PIO_PC3B_PWMH0 | PIO_PC5B_PWMH1 | PIO_PC7B_PWMH2; // Setting pins to Peripheral B

  PIOC->PIO_PDR |= PIO_PDR_P2 | PIO_PDR_P4 | PIO_PDR_P6; // Setting pins 2,4,6 (DUE Pins 34, 36, 38) to PWM Peripheral, not GPIO
  PIOC->PIO_ABSR |= PIO_PC2B_PWML0 | PIO_PC4B_PWML1 | PIO_PC6B_PWML2; // Setting pins to Peripheral B

  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(42); //Set PWM clock rate to 2MHz (84MHz/42)
  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA; // Period is left aligned,clock source is CLKA on Channel 0

  REG_PWM_SCM |= PWM_SCM_SYNC0 | PWM_SCM_SYNC1 | PWM_SCM_SYNC2; // Synchronizing of Channels 0, 1 and 2

  //PWM->PWM_CLK = PWM_CLK_PREA(1) | PWM_CLK_DIVA(42);
  //PWM->PWM_CH_NUM[1].PWM_CMR = PWM_CMR_CPRE_CLKA;

  REG_PWM_CPRD0 = 1000000; //Channel 0 Period f = 2MHz/(2*CPRD)
  REG_PWM_CDTY0 = 200000; //Channel 0 Duty Cycle x% = (CDTY/ CPRD)*100%
  REG_PWM_CPRD1 = 1000000;
  REG_PWM_CDTY1 = 1000000;
  REG_PWM_CPRD2 = 1000000;
  REG_PWM_CDTY2 = 0;
  
  PWM->PWM_ENA = PWM_ENA_CHID0; // Enable PWM on Channel 0
  //PWM->PWM_ENA = PWM_ENA_CHID1;

  //NVIC_EnableIRQ(TC0_IRQn); // enable TC0 interrupts
}

void loop() {
  // put your main code here, to run repeatedly:

}

When the duty cycle is set to 0%, 20%, 40%, 60%, 80% and 100% (0, 200000, 400000, 600000, 800000, 1000000) it outputs correctly. However any other value just gives me the output for 100% duty cycle. Can anyone explain this to me and offer some guidance on how to rectify this problem?

Hi jonnygainz,

To generate synchronous, complementary PWM using method 1 (mode0): manual duty-cycle and trigger update, it's necessary to set the update unlock bit (PWM_SCUC_UPDULOCK) in the Sync Channels Update Control register (SCUC), to trigger once the duty-cycle registers have been changed:

PWM->PWM_SCUC = PWM_SCUC_UPDULOCK;      // Set the update unlock bit to trigger an update at the end of the next PWM period

Here's an example of using 3 synchronous, complementary channels on channel 0 (D34, D35), 1 (D36, D37) and 2 (D38, D39). The PWM is at 50Hz and switches between 25% and 75% duty-cycle every 1/2 second:

// Enable synchronous, complementary output, single-slope PWM at 50Hz on 3 channels (0 to 2), at 50% duty cycle
void setup() {
  // Set-up 6 PWM outputs on 3 complementary channels on on pins D34, D35, D36, D37, D38, and D39 for channels 0 through to 2 respectively
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                                               // Enable PWM   
  PIOC->PIO_ABSR |= PIO_ABSR_P7 | PIO_ABSR_P6 | PIO_ABSR_P5 | PIO_ABSR_P4 |        // Set the port C PWM pins to peripheral type B
                    PIO_ABSR_P3 | PIO_ABSR_P2; 
  PIOC->PIO_PDR |= PIO_PDR_P7 | PIO_PDR_P6 | PIO_PDR_P5 | PIO_PDR_P4 |             // Set the port C PWM pins to outputs
                   PIO_PDR_P3 | PIO_PDR_P2;
  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(84);                               // Set the PWM clock A rate to 1MHz (84MHz/84)
  PWM->PWM_SCM |= PWM_SCM_SYNC2 | PWM_SCM_SYNC1 | PWM_SCM_SYNC0;                   // Set the PWM channels as synchronous                  
  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA;      // Enable single slope PWM and set the clock source as CLKA for all synchronous channels
  PWM->PWM_CH_NUM[0].PWM_CPRD = 19999;                 // Set the PWM frequency 1MHz/(19999 + 1) = 50Hz for all synchronous channels
  for (uint8_t i = 0; i < 3; i++)                      // Loop for each PWM channel (8 in total)
  {
    PWM->PWM_CH_NUM[i].PWM_CDTY = 9999;                // Set the PWM duty cycle to 50%
  } 
  PWM->PWM_ENA = PWM_ENA_CHID0;                        // Enable all synchronous PWM channels
  PWM->PWM_SCUC = PWM_SCUC_UPDULOCK;      // Set the update unlock bit to trigger an update at the end of the next PWM period
}

void loop() 
{
  for (uint8_t i = 0; i < 3; i++)                      // Loop for each PWM channel (3 in total)
  {
    PWM->PWM_CH_NUM[i].PWM_CDTYUPD = 4999;             // Set the PWM duty cycle to 25%
  }
  PWM->PWM_SCUC = PWM_SCUC_UPDULOCK;      // Set the update unlock bit to trigger an update at the end of the next PWM period
  delay(500);
  for (uint8_t i = 0; i < 3; i++)                      // Loop for each PWM channel (3 in total)
  {
    PWM->PWM_CH_NUM[i].PWM_CDTYUPD = 14999;            // Set the PWM duty cycle to 75%
  }
  PWM->PWM_SCUC = PWM_SCUC_UPDULOCK;      // Set the update unlock bit to trigger an update at the end of the next PWM period
  delay(500); 
}

Also, the PWM controller's timers and duty-cycle registers (PWM_CDTY and PWM_CDTYUPD) are essentially only 16-bit, therefore it's not possible to load them with values over 65535 (2^16 - 1).

Thank you very much for the help, I'll let you know if I get through with what I'm doing.

Is there a way to set the update unlock bit at the end of every period without using the delay function? I'm working on a three phase inverter with variable frequency and voltage and the period i will be working with is too small for the delay function. I stayed away from mode 2 because i was having problems understanding how to configure the PDC DMA, can you explain to me how does it work? I'm reading through the datasheet and I'm having some difficulty understanding how it works.

To automatically update the duty-cycle at the end of a timer period without having to set the update unlock bit, it's possible to use method 2 (mode1): manual duty-cycle update with automatic trigger.

The mode 1 bitfield is set in the Sync Channels Mode register:

PWM->PWM_SCM |= PWM_SCM_UPDM_MODE1 |                                             // Automatically update the duty-cycle register each timer cycle                    
                PWM_SCM_SYNC2 | PWM_SCM_SYNC1 | PWM_SCM_SYNC0;                   // Set the PWM channels as synchronous

Here's a similar example to the one above, but using mode 1 (and without the complementary outputs):

// Enable synchronous, complementary output, single-slope PWM at 50Hz on 3 channels (0 to 2), at 50% duty cycle
void setup() {
  // Set-up 6 PWM outputs on 3 complementary channels on on pins D34, D35, D36, D37, D38, and D39 for channels 0 through to 2 respectively
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                                               // Enable PWM   
  PIOC->PIO_ABSR |= PIO_ABSR_P6 | PIO_ABSR_P4 | PIO_ABSR_P2;                       // Set the port C PWM pins to peripheral type B                
  PIOC->PIO_PDR |= PIO_PDR_P6 | PIO_PDR_P4 | PIO_PDR_P2;                           // Set the port C PWM pins to outputs                 
  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(84);                               // Set the PWM clock A rate to 1MHz (84MHz/84)
  PWM->PWM_SCM |= PWM_SCM_UPDM_MODE1 |                                             // Automatically update the duty-cycle register each timer cycle                    
                  PWM_SCM_SYNC2 | PWM_SCM_SYNC1 | PWM_SCM_SYNC0;                   // Set the PWM channels as synchronous                  
  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA;      // Enable single slope PWM and set the clock source as CLKA for all synchronous channels
  PWM->PWM_CH_NUM[0].PWM_CPRD = 19999;                 // Set the PWM frequency 1MHz/(19999 + 1) = 50Hz for all synchronous channels
  for (uint8_t i = 0; i < 3; i++)                      // Loop for each PWM channel (8 in total)
  {
    PWM->PWM_CH_NUM[i].PWM_CDTY = 9999;                // Set the PWM duty cycle to 50%
  } 
  PWM->PWM_ENA = PWM_ENA_CHID0;                        // Enable all synchronous PWM channels
}

void loop() 
{
  for (uint8_t i = 0; i < 3; i++)                      // Loop for each PWM channel (3 in total)
  {
    PWM->PWM_CH_NUM[i].PWM_CDTYUPD = 4999;             // Set the PWM duty cycle to 25%
  }
  delay(500);
  for (uint8_t i = 0; i < 3; i++)                      // Loop for each PWM channel (3 in total)
  {
    PWM->PWM_CH_NUM[i].PWM_CDTYUPD = 14999;            // Set the PWM duty cycle to 75%
  }
  delay(500); 
}

I’m trying to update the duty cycle without using the delay function because in an inverter the time in which the duty cycle must be updated is very small and the delay function will not be able to accommodate that time. Also the frequency will have to be adjustable by an keypad or pot and hence cannot be a fixed value. Will the mode 2 help with this?

Regarding mode 2 operation using the PDC: automatic duty-cycle update and trigger, this mode is geared towards updating the duty-cycle each period (or for a specified number of periods) with a set of predefined duty-cycles held in memory.

Here's an example of mode 2 in operation, (based on ard_newbie's example: https://forum.arduino.cc/index.php?topic=530217.0):

// Enable synchronous, complementary output, single-slope PWM at 50Hz on 3 channels (0 to 2), at 50% duty cycle
uint16_t data[] = { 0, 4999, 14999, 4999, 4999, 14999, 9999, 4999, 14999, 14999, 4999, 14999, 19999, 4999, 14999 }; 

void setup() {
  // Set-up 6 PWM outputs on 3 complementary channels on on pins D34, D35, D36, D37, D38, and D39 for channels 0 through to 2 respectively
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                                               // Enable PWM   
  PIOC->PIO_ABSR |= PIO_ABSR_P6 | PIO_ABSR_P4 | PIO_ABSR_P2;                       // Set the port C PWM pins to peripheral type B                
  PIOC->PIO_PDR |= PIO_PDR_P6 | PIO_PDR_P4 | PIO_PDR_P2;                           // Set the port C PWM pins to outputs                 
  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(84);                               // Set the PWM clock A rate to 1MHz (84MHz/84)
  PWM->PWM_SCM |= PWM_SCM_UPDM_MODE2 |                                             // Automatically load the duty-cycle register with the PDC each timer cycle                    
                  PWM_SCM_SYNC2 | PWM_SCM_SYNC1 | PWM_SCM_SYNC0;                   // Set the PWM channels as synchronous                  
  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA;      // Enable single slope PWM and set the clock source as CLKA for all synchronous channels
  PWM->PWM_CH_NUM[0].PWM_CPRD = 19999;                 // Set the PWM frequency 1MHz/(19999 + 1) = 50Hz for all synchronous channels
  for (uint8_t i = 0; i < 3; i++)                      // Loop for each PWM channel (8 in total)
  {
    PWM->PWM_CH_NUM[i].PWM_CDTY = 9999;                // Set the PWM duty cycle to 50%
  } 
  NVIC_SetPriority(PWM_IRQn, 0);                       // Set the Nested Vector Interrupt Controller (NVIC) priority for the PWM controller to 0 (highest) 
  NVIC_EnableIRQ(PWM_IRQn);                            // Connect PWM Controller to Nested Vector Interrupt Controller (NVIC)
  PWM->PWM_IER2 = PWM_IER2_WRDY;                       // Enable interrupt when Write Ready (WRDY) is set
  
  PWM->PWM_TPR = (uint32_t)data;                       // Set the address of the transmit data pointer
  PWM->PWM_TCR = 15;                                   // Set the length of the transmit data
  PWM->PWM_TNPR = (uint32_t)data;                      // Set the next transmit data pointer
  PWM->PWM_TNCR = 15;                                  // Set the next transmit counter
  PWM->PWM_PTCR |= PWM_PTCR_TXTEN;                     // Enable the Peripheral DMA Controller 
  PWM->PWM_ENA = PWM_ENA_CHID0;                        // Enable all synchronous PWM channels
}

void loop() {}

void PWM_Handler() 
{
  PWM->PWM_TNPR = (uint32_t)data;                      // Set the next transmit data pointer
  PWM->PWM_TNCR = 15;                                  // Set the next transmit counter
  PWM->PWM_ISR2;                                       // Clear the interrupt status register 2
}

The duty-cycles are held in the data array and are stored { channel0, channel1, channel2, channel 0, channel 1, channel2, channel0, etc...

In this example the PWM interrupt handler simply reloads the next transmit data pointer (TNPR) and counter (TNCR) so that the duty-cycle pattern repeats indefinitely.

Could you explain what this is in a little more detail for me? If it's not too much trouble?

  PWM->PWM_TPR = (uint32_t)data;                       // Set the address of the transmit data pointer
  PWM->PWM_TCR = 15;                                   // Set the length of the transmit data
  PWM->PWM_TNPR = (uint32_t)data;                      // Set the next transmit data pointer
  PWM->PWM_TNCR = 15;                                  // Set the next transmit counter
  PWM->PWM_PTCR |= PWM_PTCR_TXTEN;                     // Enable the Peripheral DMA Controller
  PWM->PWM_ENA = PWM_ENA_CHID0;                        // Enable all synchronous PWM channels
}

void loop() {}

void PWM_Handler()
{
  PWM->PWM_TNPR = (uint32_t)data;                      // Set the next transmit data pointer
  PWM->PWM_TNCR = 15;                                  // Set the next transmit counter
  PWM->PWM_ISR2;                                       // Clear the interrupt status register 2
}

It's possible to change the period during operation using the period update register (PWM_CPRDUPD), followed by setting set the update unlock bit (PWM_SCUC_UPDULOCK) in the Sync Channels Update Control register (SCUC) :

PWM->PWM_CH_NUM[0].PWM_CPRDUPD = 19999;
PWM->PWM_SCUC = PWM_SCUC_UPDULOCK;

If all the channels are synchronised, this will change the period for all the channels.

I'm trying to update the duty cycle without using the delay function because in an inverter the time in which the duty cycle must be updated is very small and the delay function will not be able to accommodate that time. Also the frequency will have to be adjustable by an keypad or pot and hence cannot be a fixed value. Will the mode 2 help with this?

Might I ask what you mean by using the delay() function?

See in #4 how you used the delay(500) to update the duty cycle I can't use that because after a while it will not be able to accommodate the times. I am making a three phase space vector modulated inverter and every period i will have to calculate new duty cycles to load into each channel. Depending on the supply frequency you want the period in which these duty cycle calues must be calculated will be extremely small. If you want to find out more detail about how this works you can take a look at this page:

https://hvdc.ca/webhelp/Master_Library_Models/HVDC_and_FACTS/Space_Vector_Modulation/SVM_Theory.htm

Could you explain what this is in a little more detail for me? If it’s not too much trouble?

The PDC has a transmit data pointer (TDP), this is a register that contains the address or location of the first data item in the data array, in this example it’s the address of the data array: data or &data[0]. The PDC also has a transmit counter (TCR), a 16-bit counter that initially contains the number of data items in the array, in our case 15.

Each PWM timer period, the PRC copies the data from the array into PWM timer’s PWM_CDTYUPD register and decrements the counter by 1. When the counter reaches zero the PDC checks the next transmit data pointer (TNPR) and (TNCR) registers. If the TNCR is zero the transfer is terminated. If however the TNPR and TNCR contain new data, it’s copied to the TCP and TCR registers and the TNPR and TNCR are set to zero.

To keep the PWM timer cycling around the array indefinitely, (should this be a requirement), it’s necessary to use the PWM Controller’s interrupt service routine (ISR): PWM_Handler() function, to reload the PDC’s next registers oncemore.

It’s possible to just remove the delay() functions and call on the PWM timer to output whatever duty-cycle and period you require, whenever you need it. The PWM timer will output the new waveform at the beginning of the next cycle.

I should say that there are two things I'm working on the first is generating three phase quasi-square waves using an inverter circuit and then implementing Space Vector Modulation to produce three phase sinusoidal waves from the quasi-square waves. For the quasi-square waves, only 6 circuit configurations are required in a specific order for a fixed period for duty cycles of either 0% or 100%. Space Vector Modulation however is much more complex than that.

Programming has never been my strong point, and working with this Due is a little difficult for me, but it is much more capable to do what i need it to do than the rest of the boards offered by arduino.

@MartinL is there a way to do what you did using the data array “uint16_t data” but with a switch case or if statements using a counter? So if i want to update the duty cycle for the following code using a switch case or if statements:

This is what I’m working with:

// Enable synchronous, complementary output, single-slope PWM at 5Hz on 3 channels (0 to 2), at varying duty cycle
uint16_t data[] = { 65535, 0, 0, 65535, 65535, 0, 0, 65535, 0, 0, 65535, 65535, 0, 0, 65535, 65535, 0, 65535};



void setup() {
  // Set-up 6 PWM outputs on 3 complementary channels on on pins D34, D35, D36, D37, D38, and D39 for channels 0 through to 2 respectively
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                                               // Enable PWM   
  PIOC->PIO_ABSR |= PIO_ABSR_P6 | PIO_ABSR_P4 | PIO_ABSR_P2;                       // Set the port C PWM pins to peripheral type B  
  PIOC->PIO_ABSR |= PIO_ABSR_P7 | PIO_ABSR_P5 | PIO_ABSR_P3;               
  PIOC->PIO_PDR |= PIO_PDR_P6 | PIO_PDR_P4 | PIO_PDR_P2;                           // Set the port C PWM pins to outputs 
  PIOC->PIO_PDR |= PIO_PDR_P7 | PIO_PDR_P5 | PIO_PDR_P3;    
              
  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(255);                               // Set the PWM clock A rate to 1MHz (84MHz/255)
  PWM->PWM_SCM |= PWM_SCM_UPDM_MODE2 |                                             // Automatically load the duty-cycle register with the PDC each timer cycle                   
                  PWM_SCM_SYNC2 | PWM_SCM_SYNC1 | PWM_SCM_SYNC0;                   // Set the PWM channels as synchronous                 
  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA;      // Enable single slope PWM and set the clock source as CLKA for all synchronous channels
  PWM->PWM_CH_NUM[0].PWM_CPRD = 65535;                 // Set the PWM frequency 329411MHz/(65536) = 5Hz for all synchronous channels
  for (uint8_t i = 0; i < 3; i++)                      // Loop for each PWM channel (8 in total)
  {
    PWM->PWM_CH_NUM[i].PWM_CDTY = 0;                   // Set the PWM duty cycle to 50%
  }
  NVIC_SetPriority(PWM_IRQn, 0);                       // Set the Nested Vector Interrupt Controller (NVIC) priority for the PWM controller to 0 (highest)
  NVIC_EnableIRQ(PWM_IRQn);                            // Connect PWM Controller to Nested Vector Interrupt Controller (NVIC)
  PWM->PWM_IER2 = PWM_IER2_WRDY;                       // Enable interrupt when Write Ready (WRDY) is set
 
  PWM->PWM_TPR = (uint32_t)data;                       // Set the address of the transmit data pointer
  PWM->PWM_TCR = 18;                                   // Set the length of the transmit data
  PWM->PWM_TNPR = (uint32_t)data;                      // Set the next transmit data pointer
  PWM->PWM_TNCR = 18;                                  // Set the next transmit counter
  PWM->PWM_PTCR |= PWM_PTCR_TXTEN;                     // Enable the Peripheral DMA Controller
  PWM->PWM_ENA = PWM_ENA_CHID0;                        // Enable all synchronous PWM channels

}

void loop() {}

void PWM_Handler()
{

  PWM->PWM_TNPR = (uint32_t)data;                      // Set the next transmit data pointer
  PWM->PWM_TNCR = 18;                                  // Set the next transmit counter
  PWM->PWM_ISR2;                                       // Clear the interrupt status register 2
  
}

Instead of a data array i would like to use a switch case or if statements to change the duty cycle values. The duty cycle must change every period in the same pattern seen in the data array. Something like this:

int count = 0;

switch(count)
{
     case 1:
     //Update duty cycle
     break;
     
     case 2;
     //Update duty cycle
     break;
     //......
     case 6;
     //Update Duty cycle
     break;

}

It depends what you mean by "update duty cycle" in your switch statement and whether the vectors are updated on a per pattern or per PWM period basis.

If you mean change the vector sequencing to a different pattern, then it's possible to provide the Transmit Next Data Pointer (PWM->PWM_TNPR) register with a new pointer to an array pattern, say data2[]. At end of the current pattern a new pattern will be loaded and output.

If however you mean change the vector on a period by period basis, then it's probably better to go back to synchronous mode 0 or 1 and set the duty-cycle update registers in the PWM Controller's interrupt service routine manually.

This requires the interrupt service routine to be called at the end of each PWM period, by enabling the counter event on channel 0 interrupt:

PWM->PWM_IER1 = PWM_IER1_CHID0;                        // Enable interrupt on PWM channel 0 triggered at end of PWM period

Then implementing the switch statement to change the duty-cycle update register for each channel (PWM->CH_NUM[X].PWM_CDYUPD) within the PWM_Handler() function.

How should I write the ISR routine if i want to use the Switch Case to change the duty cycle? I tried doing it but it doesn't work.

byte count = 0;

void setup() 
{
  Serial.begin(57600);
  
  PMC->PMC_PCER1 |= PMC_PCER1_PID36; //Enable PWM (Power On)

  PWM->PWM_DIS = PWM_DIS_CHID0;       //Disable PWM on Channel 0

  PIOC->PIO_PDR |= PIO_PDR_P3 | PIO_PDR_P5; // Setting pins 3,5, (DUE Pins 35, 37, 39) to PWM Peripheral, not GPIO
  PIOC->PIO_ABSR |= PIO_PC3B_PWMH0 | PIO_PC5B_PWMH1; // Setting pins to Peripheral B

  PIOC->PIO_PDR |= PIO_PDR_P2 | PIO_PDR_P4; // Setting pins 2,4, (DUE Pins 34, 36, 38) to PWM Peripheral, not GPIO
  PIOC->PIO_ABSR |= PIO_PC2B_PWML0 | PIO_PC4B_PWML1; // Setting pins to Peripheral B

  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(42); //Set PWM clocke rate to 2MHz (84MHz/42)
  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA; // Period is left aligned,clock source is CLKA on Channel 0

  REG_PWM_SCM |= PWM_SCM_SYNC0 | PWM_SCM_SYNC1; // Synchronizing of Channels 0, 1 and 2

  REG_PWM_SCM |= PWM_SCM_UPDM_MODE1;  // Manual Write of duty-cycle automatic trigger of the update

  PWM->PWM_SCUP = PWM_SCUP_UPR(0); // Defining update period (UPR + 1)

  PWM->PWM_IER2 = PWM_IER2_WRDY; // Enable Interrupt when WRDY flag is set

  //PWM_SCM_PTRM == 0;; // The WRDY flag in PWM_ISR2 and the PDC transfer request are set to 1 as soon as the update period is elapsed.


  REG_PWM_CPRD0 = 1000000; //Channel 0 Period f = 2MHz/(2*CPRD)
  //REG_PWM_CDTY0 = 0; //Channel 0 Duty Cycle x% = (CDTY/ CPRD)*100%
  REG_PWM_CPRD1 = 1000000;
  //REG_PWM_CDTY1 = 1000000;

  PWM->PWM_ENA = PWM_ENA_CHID0; // Enable PWM on Channel 0

  update_Duty_Cycle();

  //NVIC_EnableIRQ(PWM_IRQn); // enable PWM interrupts


}

void loop() 
{
  // put your main code here, to run repeatedly:
   // Serial.print("count = ");
   // Serial.print(count);
  //  Serial.print(" ");
} 


void PWM_Interrupt_Handler()
{
  PWM->PWM_ISR2;      // Read ISR2 and clear status register
  //update_Duty_Cycle(); 
  
}

void update_Duty_Cycle()
{
  if(count > 3){
    count = 0;}
    switch(count) 
    {
      case 0:
      REG_PWM_CDTYUPD0 = 1000000;
      REG_PWM_CDTYUPD1 = 0;
      break;
      case 1:
      REG_PWM_CDTYUPD1 = 1000000;
      break;
      case 2:
      REG_PWM_CDTYUPD0 = 0;
      break;
      case 3:
      REG_PWM_CDTYUPD1 = 0;
      break;
      default:
      break;
    }
    //SquareWave(count);
    //count++; 
}

/*
void SquareWave(byte Sector)
{
    switch(Sector) 
    {
      case 0:
      REG_PWM_CDTYUPD0 = 1000000;
      REG_PWM_CDTYUPD1 = 0;
      break;
      case 1:
      REG_PWM_CDTYUPD1 = 1000000;
      break;
      case 2:
      REG_PWM_CDTYUPD0 = 0;
      break;
      case 3:
      REG_PWM_CDTYUPD1 = 0;
      break;
      default:
      break;
    }
}
*/

This is what I tried to do, I know some of the configuration is wrong but this is essentially what I want to do

Here's a working example based on your code, using the two complementary channels: 0 (D34, D35) and 1 (D36, D37):

void setup()
{
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                  // Enable PWM (Power On)

  PIOC->PIO_PDR |= PIO_PDR_P3 | PIO_PDR_P5;           // Setting pins 3,5, (DUE Pins 35, 37, 39) to PWM Peripheral, not GPIO
  PIOC->PIO_ABSR |= PIO_ABSR_P3 | PIO_ABSR_P5;        // Setting pins to Peripheral B

  PIOC->PIO_PDR |= PIO_PDR_P2 | PIO_PDR_P4;           // Setting pins 2,4, (DUE Pins 34, 36, 38) to PWM Peripheral, not GPIO
  PIOC->PIO_ABSR |= PIO_ABSR_P2 | PIO_ABSR_P4;        // Setting pins to Peripheral B

  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(42);  // Set PWM clocke rate to 2MHz (84MHz/42)
  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA;     // Period is left aligned,clock source is CLKA on Channel 0

  PWM->PWM_SCM |= PWM_SCM_SYNC0 | PWM_SCM_SYNC1;      // Synchronizing of Channels 0, 1 and 2
  PWM->PWM_SCM |= PWM_SCM_UPDM_MODE1;                 // Manual Write of duty-cycle automatic trigger of the update
  //PWM->PWM_SCUP = PWM_SCUP_UPR(0);                    // Defining update period (UPR + 1)

  NVIC_SetPriority(PWM_IRQn, 0);                      // Set the Nested Vector Interrupt Controller (NVIC) priority for the PWM controller to 0 (highest) 
  NVIC_EnableIRQ(PWM_IRQn);                           // Connect PWM Controller to Nested Vector Interrupt Controller (NVIC)

  PWM->PWM_IER1 = PWM_IER1_CHID0;                     // Enable interrupt on PWM channel 0 triggered at end of PWM period

  PWM->PWM_CH_NUM[0].PWM_CPRD = 10000;                // Channel 0 Period f = 2MHz/(2*CPRD)
  PWM->PWM_CH_NUM[0].PWM_CDTY = 0;                    // Channel 0 duty-cycle at 0%
  PWM->PWM_CH_NUM[1].PWM_CDTY = 0;                    // Channel 1 duty-cycle at 0%

  PWM->PWM_ENA = PWM_ENA_CHID0;                       // Enable synchronous PWM on Channel 0
}

void loop(){}

void PWM_Handler()                       // PWM Interrupt Service Routine (ISR)
{
  if (PWM->PWM_ISR1 & PWM_ISR1_CHID0)    // Check if an update condition has occured
  {       
    update_Duty_Cycle();                 // Update the duty cycles
  }
}

void update_Duty_Cycle()
{
  static byte count = 0;
  
  switch(count)
  {
    case 0:
      PWM->PWM_CH_NUM[0].PWM_CDTYUPD = 10000;
      PWM->PWM_CH_NUM[1].PWM_CDTYUPD = 0;
    break;
    case 1:
      PWM->PWM_CH_NUM[1].PWM_CDTYUPD = 10000;
    break;
    case 2:
      PWM->PWM_CH_NUM[0].PWM_CDTYUPD = 0;
    break;
    case 3:
      PWM->PWM_CH_NUM[1].PWM_CDTYUPD = 0;
    break;
    default:
    break;
  }
  count = (count + 1) % 4;
}

Thank you very much, you have been very helpful to me thus far, I would like to also find out how to add dead times to the code in #16.

To insert dead-times there's the dead-time (PWM->PWM_CH_NUM[X].PWM_DT) and the dead-time update (PWM->PWM_CH_NUM[X].PWM_DTUPD) registers.

Like the duty-cycle and period registers, the DT register takes effect immediately at the PWM output, while changes to the DTUPD register occur on the next timer cycle.

The DT and DTUPD are both 32-bit registers and contain two 16-bit bitfields. The upper 16-bits are for the PWMLx output and are named DTL/DTLUPD, while the lower 16-bits are for the PWMHx output and are named DTH/DTHUPD. Although each bitfield contains 16-bits, only the lower 12-bits in each bitfield are significant (valid), a value between 0 and 4095.

To insert dead-time on channel 0's PWML0 output for example:

PWM->PWM_CH_NUM[0].PWM_DT = PWM_DT_DTH(0) | PWM_DT_DTL(167);    // Set the PWML0 output dead-time

How do you enable the dead time? I see in the datasheet you need to use a dead time enable bit to get the dead-time working.