Complementary PWM channels Output

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.

Sorry, I noticed that I omitted the dead-time enable bit in my description above. You just need to set the DTE bit in the Due's Channel Mode Register (CMRx) for the given PWM channel, for example for channel 0:

PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_DTE | PWM_CMR_CPRE_CLKA;

How does the dead time operate for synchronous channels? I'm putting in dead times and it significantly reducing my period value. When using in synchronous channels, do you have to just enable it on channel 0 and use channel 0's clock? or you have to enable for each channel and use the clock for each channel? my period value is supposed to be 0.002777778, but i'm getting 0.001933333 when I insert dead times. Even with '0' in the DTH and DTL I'm still getting 0.001933333.

I just want to get a dead time of about 1 micro second

When the DTE bit is disabled, I'm getting the correct period 0.002777778s, but when DTE is enabled, regardless of what I put in the DTH and DTL registers, I'm still getting a period of 0.0019333333s. Both complementary outputs look exactly the same on the oscilloscope also, one isn't slightly bigger and the other and both start and end on the exact same time intervals.

Dead-time insertion doesn't actually change the period of the complementary waveforms, it simply delays the waveforms' edge with respect to the beginning of the timer cycle.

If the duty-cycle (and period) of the waveform remains unchanged then inserting a delay will shorten the pulse width. To maintain the pulse width it's necessary to add the delay time to the duty-cycle register, in order to extend it oncemore, however this can only be achieved so long as the duty-cycle does not exceed the period.

An example of using dead-time insertion is given in post number #10 here: How do I make a PWM signal run once only. - Arduino Due - Arduino Forum.

This example shows how it works for 1 channel, how does dead time work for three synchronized channels? like how I have CH0, CH1 and CH2 synchronized.

This example shows how it works for 1 channel, how does dead time work for three synchronized channels? like how I have CH0, CH1 and CH2 synchronized.

You just have to set the dead time enable bit for each channel:

PWM->PWM_CH_NUM[1].PWM_CMR = PWM_CMR_DTE;                         // Enable channel 1 dead-time insertion

Here's an example with 3 pairs of complementary and synchronous PWM outputs at 100kHz:

// Enable synchronous, complementary output, single-slope PWM at 100kHz on 3 channels (0 to 2), at 75% duty cycle
// with various dead-times for each channel
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 |                     // Set the port C PWM pins to peripheral type B
                    PIO_ABSR_P5 | PIO_ABSR_P4 |
                    PIO_ABSR_P3 | PIO_ABSR_P2; 
  PIOC->PIO_PDR |= PIO_PDR_P7 | PIO_PDR_P6 |                        // Set the port C PWM pins to outputs
                   PIO_PDR_P5 | PIO_PDR_P4 |
                   PIO_PDR_P3 | PIO_PDR_P2;                 
  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(1);                 // Set the PWM clock A rate to 84MHz (84MHz/1)
  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_CPRD = 839;                                // Set the PWM frequency to 100kHz (84MHz/(839 + 1)) for all synchronous channels
  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_DTE | PWM_CMR_CPRE_CLKA;     // Enable channel 0 dead-time insertion and set the clock source as CLKA for all synchronous channels
  PWM->PWM_CH_NUM[1].PWM_CMR = PWM_CMR_DTE;                         // Enable channel 1 dead-time insertion
  PWM->PWM_CH_NUM[2].PWM_CMR = PWM_CMR_DTE;                         // Enable channel 2 dead-time insertion
  PWM->PWM_CH_NUM[0].PWM_CDTY = 630;                                // Set channel 0 PWM duty cycle to 75%
  PWM->PWM_CH_NUM[1].PWM_CDTY = 630;                                // Set channel 1 PWM duty cycle to 75%
  PWM->PWM_CH_NUM[2].PWM_CDTY = 630;                                // Set channel 2 PWM duty cycle to 75%
  PWM->PWM_CH_NUM[0].PWM_DT = PWM_DT_DTH(0) | PWM_DT_DTL(0);        // Set channel dead-time for a 0us delay on output PWML0
  PWM->PWM_CH_NUM[1].PWM_DT = PWM_DT_DTH(0) | PWM_DT_DTL(105);      // Set channel dead-time for a 1.25us delay on output PWML1
  PWM->PWM_CH_NUM[2].PWM_DT = PWM_DT_DTH(0) | PWM_DT_DTL(210);      // Set channel dead-time for a 2.5us delay on output PWML2
  PWM->PWM_ENA = PWM_ENA_CHID0;                                     // Enable all synchronous PWM channels
}

void loop() {}

Here's the output top to bottom of channels PWML0, PWML1, PWML2 and PWMH0 respectively:

DeadTimeInsertion3.png

PWML0 (yellow) and its complement PWMH0 (dark blue) have no dead-time insertion, PWML1 (light blue) has 1.25us of dead-time insertion, while PWML2 (pink) has 2.5us.

DeadTimeInsertion3.png

How do I update the dead time every period, because I tried what you showed me in #26 but the dead times aren't being inserted. I'm still just getting both complementary wave-forms being exactly the same.

/* This code generates Quasi-Square Waves at 60Hz*/
static byte stateCount = 0;
static float CPRDV = 0;
static float inverterFrequency = 60;
int divA = 42;      // Set DIVA

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

  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_ABSR_P3 | PIO_ABSR_P5 | PIO_ABSR_P7;       // 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_ABSR_P2 | PIO_ABSR_P4 | PIO_ABSR_P6;       // Setting pins to Peripheral B

  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(divA);  // Set PWM clocke rate to 2MHz (84MHz/42)
  PWM->PWM_SCM |= PWM_SCM_SYNC0 | PWM_SCM_SYNC1 | PWM_SCM_SYNC2;      // Synchronizing of Channels 0, 1 and 2
  PWM->PWM_SCM |= PWM_SCM_UPDM_MODE1;                 // Manual Write of duty-cycle automatic trigger of the update
  
  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

  calcCPRDV();  // CPRD is calculated
  /*Serial.print("CPRDV = ");
  Serial.print(CPRDV);
  Serial.print("\n");*/
  PWM->PWM_CH_NUM[0].PWM_CPRD = CPRDV;                // Channel 0 Period f = 2MHz/(CPRD)= 100Hz = 0.01s |CPRD = 2MHz/f
  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA | PWM_CMR_DTE;     // Period is left aligned,clock source is CLKA on Channel 0
  PWM->PWM_CH_NUM[1].PWM_CMR = PWM_CMR_DTE;
  PWM->PWM_CH_NUM[2].PWM_CMR = PWM_CMR_DTE;

  PWM->PWM_CH_NUM[0].PWM_DT = PWM_DT_DTH(0)| PWM_DT_DTL(2);   
  PWM->PWM_CH_NUM[1].PWM_DT = PWM_DT_DTH(0)| PWM_DT_DTL(2); // Dead time of 1us [DT = (1/2778)*5555 = 2
  PWM->PWM_CH_NUM[2].PWM_DT = PWM_DT_DTH(0)| PWM_DT_DTL(2);
  
  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 calcCPRDV () // Used to calculate the CPRD value
{
  //inverterFrequency = 60;
  static float numOfVectors = 6;
  static float adMCKFreq = 84000000;
  static float timerFreq = (adMCKFreq/divA); //2MHz
  static float period = 1/inverterFrequency;
  static float Ts = period/numOfVectors;
  static float switchingFreq = 1/Ts;
  CPRDV = (timerFreq/(1*switchingFreq));
  /*Serial.print("Inverter Frequency = "); Serial.print(inverterFrequency);Serial.print("\n");
  Serial.print("Num of Vectors = "); Serial.print(numOfVectors); Serial.print("\n");
  Serial.print("Timer Freq = "); Serial.print(timerFreq); Serial.print("\n");
  Serial.print("Period = "); Serial.print(period, 8); Serial.print("\n");
  Serial.print("SSV Period = "); Serial.print(Ts, 8); Serial.print("\n");
  Serial.print("Switching Freq = "); Serial.print(switchingFreq); Serial.print("\n");*/

}

void update_Duty_Cycle()
{
  
  
    if(stateCount < 6)
    {
          PWM->PWM_CH_NUM[0].PWM_CDTYUPD = 0;
          PWM->PWM_CH_NUM[1].PWM_CDTYUPD = 0;
          PWM->PWM_CH_NUM[2].PWM_CDTYUPD = 0;
          stateCount++;
          /*Serial.print("Counter = ");
          Serial.print(stateCount); Serial.print("\n");*/
    }
    else
    {
  
      static byte count = 0;
      static float p = CPRDV;
      static float n = 0;
      //Serial.print("Sector = "); Serial.print(count); Serial.print("\n");
      switch(count)
        {
          case 0: //pnn = 100 => 012
            PWM->PWM_CH_NUM[0].PWM_CDTYUPD = p;
            PWM->PWM_CH_NUM[1].PWM_CDTYUPD = n;
            PWM->PWM_CH_NUM[2].PWM_CDTYUPD = n;
            
            PWM->PWM_CH_NUM[0].PWM_DT = PWM_DT_DTH(0)| PWM_DT_DTL(20);
            PWM->PWM_CH_NUM[1].PWM_DT = PWM_DT_DTH(0)| PWM_DT_DTL(20);
            PWM->PWM_CH_NUM[2].PWM_DT = PWM_DT_DTH(0)| PWM_DT_DTL(20);
          break;
          case 1: //ppn = 110 => 012 
            PWM->PWM_CH_NUM[0].PWM_CDTYUPD = p;
            PWM->PWM_CH_NUM[1].PWM_CDTYUPD = p;
            PWM->PWM_CH_NUM[2].PWM_CDTYUPD = n;
          break;
          case 2: //npn = 010 => 012
            PWM->PWM_CH_NUM[0].PWM_CDTYUPD = n;
            PWM->PWM_CH_NUM[1].PWM_CDTYUPD = p;
            PWM->PWM_CH_NUM[2].PWM_CDTYUPD = n;
          break;
          case 3: //npp = 011 => 012
            PWM->PWM_CH_NUM[0].PWM_CDTYUPD = n;
            PWM->PWM_CH_NUM[1].PWM_CDTYUPD = p;
            PWM->PWM_CH_NUM[2].PWM_CDTYUPD = p;
          break;
          case 4: //nnp = 001 => 012
            PWM->PWM_CH_NUM[0].PWM_CDTYUPD = n;
            PWM->PWM_CH_NUM[1].PWM_CDTYUPD = n;
            PWM->PWM_CH_NUM[2].PWM_CDTYUPD = p;
          break;
          case 5: //pnp = 101 => 012
            PWM->PWM_CH_NUM[0].PWM_CDTYUPD = p;
            PWM->PWM_CH_NUM[1].PWM_CDTYUPD = n;
            PWM->PWM_CH_NUM[2].PWM_CDTYUPD = p;
          break;
          default:
          break;
        }
        count = (count + 1) % 6;


    }
}

I just want a deadtime of 1us, my CPRD value is 5555 and my period is 2778us, therefore DT=(1/2778)*55555 = 1.999 = 2. When i look at it on an oscilloscope I'm not seeing the dead time. So I'm thinking that I need to update the dead time every period for them to show up.