3
\$\begingroup\$

I have an Arduino Due, which has an Atmel SAM3XE MCU.

I want to generate a PWM signal and I want to change the duty cycle every cycle of the PWM reliably so I can generate an output signal such as a sine on an output pin.

How can I implement this using an interrupt? I need to add an interrupt routine, that will be run in time before next PWM cycle starts.

I have this code so far:

// Output 50% duty cycle PWM at 10kHz on digital pins D4 and D5 using TC6
void setup() {
 
 REG_PMC_PCER1 |= PMC_PCER1_PID33; // Enable peripheral TC6 (TC2 Channel 0)
 REG_PIOC_ABSR |= PIO_ABSR_P26 | PIO_ABSR_P25; // Switch the multiplexer to peripheral B for TIOA6 and TIOB6
 REG_PIOC_PDR |= PIO_PDR_P26 | PIO_PDR_P25; // Disable the GPIO on the corresponding pins
 REG_TC2_CMR0 = TC_CMR_BCPC_SET | // Set TIOB on counter match with RC0
 TC_CMR_ACPC_SET | // Set TIOA on counter match with RC0
 TC_CMR_BCPB_CLEAR | // Clear TIOB on counter match with RB0
 TC_CMR_ACPA_CLEAR | // Clear TIOA on counter match with RA0
 TC_CMR_WAVE | // Enable wave mode
 TC_CMR_WAVSEL_UP_RC | // Count up with automatic trigger on RC compare
 TC_CMR_EEVT_XC0 | // Set event selection to XC0 to make TIOB an output
 TC_CMR_TCCLKS_TIMER_CLOCK1; // Set the timer clock to TCLK1 (MCK/2 = 84MHz/2 = 48MHz)
 REG_TC2_RC0 = 1400; // Load the RC0 register, 30 kHz PWM
 REG_TC2_RA0 = 350; // Load the RB0 register
 REG_TC2_RB0 = 700+350; // Load the RB0 register
 
 REG_TC2_CCR0 = TC_CCR_SWTRG | TC_CCR_CLKEN; // Enable the timer TC6 
}
void loop() {}
ocrdu
9,34123 gold badges33 silver badges43 bronze badges
asked Mar 11, 2018 at 9:24
\$\endgroup\$
1
  • \$\begingroup\$ well, then do write an interrupt service routine that adjusts the duty cycle, and then "register" it as to be triggered on every timer reset event? \$\endgroup\$ Commented Mar 11, 2018 at 11:43

1 Answer 1

1
\$\begingroup\$

You can do something like this. This enables the interrupt handler and you can update the R* register values in the interrupt handler. However I'm not entirely sure if this is the safest way to do it.

 // Output 50% duty cycle PWM at 10kHz on digital pins D4 and D5 using TC6
void setup() {
 REG_PMC_PCER1 |= PMC_PCER1_PID33; // Enable peripheral TC6 (TC2 Channel 0)
 REG_PIOC_ABSR |= PIO_ABSR_P26 | PIO_ABSR_P25; // Switch the multiplexer to peripheral B for TIOA6 and TIOB6
 REG_PIOC_PDR |= PIO_PDR_P26 | PIO_PDR_P25; // Disable the GPIO on the corresponding pins
 REG_TC2_CMR0 = TC_CMR_BCPC_SET | // Set TIOB on counter match with RC0
 TC_CMR_ACPC_SET | // Set TIOA on counter match with RC0
 TC_CMR_BCPB_CLEAR | // Clear TIOB on counter match with RB0
 TC_CMR_ACPA_CLEAR | // Clear TIOA on counter match with RA0
 TC_CMR_WAVE | // Enable wave mode
 TC_CMR_WAVSEL_UP_RC | // Count up with automatic trigger on RC compare
 TC_CMR_EEVT_XC0 | // Set event selection to XC0 to make TIOB an output
 TC_CMR_TCCLKS_TIMER_CLOCK1; // Set the timer clock to TCLK1 (MCK/2 = 84MHz/2 = 48MHz)
 REG_TC2_RC0 = 1400; // Load the RC0 register, 30 kHz PWM
 REG_TC2_RA0 = 350; // Load the RB0 register
 REG_TC2_RB0 = 700+350; // Load the RB0 register
 // enable interrupts
 TC2 -> TC_CHANNEL[0].TC_IER = TC_IER_CPAS // interrupt on RA compare match
 | TC_IER_CPBS // interrupt on RB compare match
 | TC_IER_CPCS; // interrupt on RC compare match
 // enable interrupt vector
 NVIC_EnableIRQ(TC6_IRQn);
 REG_TC2_CCR0 = TC_CCR_SWTRG | TC_CCR_CLKEN; // Enable the timer TC6
}
void loop() {}
//TC6 interrupt handler
void TC6_Handler() {
 // read interrupt status
 uint32_t status = TC2 -> TC_CHANNEL[0].TC_SR;
 if (status & TC_SR_CPAS) {
 // RA compare match
 } else if (status & TC_SR_CPBS) {
 // RB compare match
 } else if (status & TC_SR_CPCS) {
 // RC compare match
 TC2 -> TC_CHANNEL[0].TC_RC = 2000;
 }
}

You can also program a PMW signal using the PWM controller on the Due. This way you can let the PDC DMA update the duty cycle values automatically. If needed I can look to make a quick sketch to test it out.

answered Mar 25, 2018 at 12:52
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.