Good day everyone!
Please help me with a solution for writing code to control the PWM signal at the outputs of the Arduino Due (Pin 2, 3,4). Sample code below. The PWM output should be switched relative to each other by 17 microseconds, see the attached oscillogram, with the ability to adjust the duty cycle, the carrier frequency is 20 kHz.
For an example of this code, I would like to separately thank (ard_newbie).
//
/ Frequency = 20kHz over pin 2, 3, 4 /
//
#define FreqMin 0
volatile int DUTY=1050;
void setup() {
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
digitalWrite(2, 0);
digitalWrite(3, 0);
digitalWrite(4, 0);
// Set synchro channels list : Channel 0, channel 1 and channel 2
PWM->PWM_DIS = PWM_DIS_CHID0 | PWM_DIS_CHID1 | PWM_DIS_CHID2;
PWM->PWM_SCM = PWM_SCM_SYNC0 // Add SYNCx accordingly, at least SYNC0, plus SYNC1 & SYNC2
| PWM_SCM_SYNC1
| PWM_SCM_SYNC2
| PWM_SCM_UPDM_MODE2; //Automatic write of duty-cycle update registers by the PDC DMA
/* Frequency = 20kHz over pin 2 */
PMC->PMC_PCER0 |= PMC_PCER0_PID27; // TC0 power ON - Timer Counter 0 channel 0 IS TC0 - See page 38
PIOB->PIO_PDR |= PIO_PDR_P25; // The pin is no more driven by GPIO
PIOB->PIO_ABSR |= PIO_PB25B_TIOA0; // Periperal type B - See page 859
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 -- See page 883
| TC_CMR_ACPC_SET; // Set TIOA0 on RC compare match
TC0->TC_CHANNEL[0].TC_RC = 2100; //<********************* Frequency = (Mck/2)/TC_RC Hz = 20 KHz
TC0->TC_CHANNEL[0].TC_RA = 210; //<******************** Duty cycle = (TC_RA/TC_RC) * 100 % = 10% (210); 50% (1050); 100% (2100)
TC0->TC_CHANNEL[0].TC_IER = TC_IER_CPCS; // Interrupt on RC compare match
NVIC_EnableIRQ(TC0_IRQn);
TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC0 counter and enable
/* Frequency = 20kHz over pin 3 */
PMC->PMC_PCER1 |= PMC_PCER1_PID34; // TC7 power ON - Timer Counter 2 channel 1 IS TC7 - See page 38
PIOC->PIO_PDR |= PIO_PDR_P28; // The pin is no more driven by GPIO
PIOC->PIO_ABSR |= PIO_PC28B_TIOA7; // Periperal type B - See page 859
TC2->TC_CHANNEL[1].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 TIOA7 on RA compare match -- See page 883
| TC_CMR_ACPC_SET; // Set TIOA7 on RC compare match
TC2->TC_CHANNEL[1].TC_RC = 2100; //<********************* Frequency = (Mck/2)/TC_RC Hz = 20 KHz
TC2->TC_CHANNEL[1].TC_RA = 210; //<******************** Duty cycle = (TC_RA/TC_RC) * 100 % = 10% (210); 50% (1050); 100% (2100)
TC2->TC_CHANNEL[1].TC_IER = TC_IER_CPCS; // Interrupt on RC compare match
NVIC_EnableIRQ(TC7_IRQn);
TC2->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC7 counter and enable
/* Frequency = 20kHz over pin 4 */
PMC->PMC_PCER1 |= PMC_PCER1_PID33; // TC6 power ON - Timer Counter 2 channel 0 IS TC6 - See page 38
PIOC->PIO_PDR |= PIO_PDR_P26; // The pin is no more driven by GPIO (PIO Controller PIO Disable Register) - Disables the PIO from controlling the corresponding pin (enables peripheral control of the pin). / Запрещает PIO управлять соответствующим выводом (включает периферийное управление выводом).
PIOC->PIO_ABSR |= PIO_PC26B_TIOB6; // Periperal type B - See page 859
TC2->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 // MCK/2, clk on rising edge
| TC_CMR_EEVT_XC0 // External Event Selection-OUTPUT / Выбор внешнего события-OUTPUT
| TC_CMR_WAVE // Waveform mode is enabled / Режим Форма волны включен
| TC_CMR_WAVSEL_UP_RC // UP mode with automatic trigger on RC Compare / Режим UP с автоматическим запуском на RC Сравнить !!!! (TC_CMR_WAVSEL_UPDOWN) - UPDOWN mode without automatic trigger on RC Compare/UPDOWN режим без автоматического запуска на RC Сравнить
| TC_CMR_BCPB_CLEAR // Clear TIOB6 on RA compare match -- See page 883
| TC_CMR_BCPC_SET; // Set TIOB6 on RC compare match
TC2->TC_CHANNEL[0].TC_RC = 2100; //<********************* Frequency = (Mck/2)/TC_RC Hz = 20 KHz
TC2->TC_CHANNEL[0].TC_RB = 210; //<******************** Duty cycle = (TC_RB/TC_RC) * 100 % = 10% (210); 50% (1050); 100% (2100)
TC2->TC_CHANNEL[0].TC_IER = TC_IER_CPCS; // Interrupt on RC compare match
NVIC_EnableIRQ(TC6_IRQn);
TC2->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC6 counter and enable (A software trigger is performed: the counter is reset and the clock is started | Enables the clock if CLKDIS is not 1)
}
void TC0_Handler() {
TC0->TC_CHANNEL[0].TC_SR; //Read and clear status register so that the interrupt handler fires again and again
}
void TC7_Handler() {
TC2->TC_CHANNEL[1].TC_SR; //Read and clear status register so that the interrupt handler fires again and again
}
void TC6_Handler() {
TC2->TC_CHANNEL[0].TC_SR; //Read and clear status register so that the interrupt handler fires again and again
}
void loop() {
TC0->TC_CHANNEL[0].TC_RA = DUTY;
TC2->TC_CHANNEL[1].TC_RA = DUTY;
TC2->TC_CHANNEL[0].TC_RB = DUTY;
delay (50);
}