When I was reading the datasheet of the Atmel SAM3X8E, I found that this MCU includes a PWM macrocell which controls 8 channels independently, and that each channel controls two complementary square output waveforms.
The Arduino Due has 4 of the 8 PWM channels mapped to its pwm pins labeled PWM6, PWM7, PWM8, PWM9 on board respectively, as 4 independent single outputs.
What I'm trying to do is to use PWM8 as one of my PWM output, and use the pin44 as its complementary signal, these two pins correspond to the HIGH and LOW output of PWM channel 5, which you will see in the attached DUE pin mapping diagram.
I tried using the PIO_Configure( PIOC, PIO_PERIPH_B, 44, PIO_DEFAULT) to assign the pin44 to the PWM Peripheral Function, but after analogwrite(8,100), only got the pwm signal on PWM8, got no signal on pin44, should be complementary signal out there....
Any suggestions would be appreciated!
You can generate PWM signals thru the Timer Counters or the PWM controller or analogWrite().
analogWrite() produces PWM pulses throughout pins 2 to 13, plus DAC0 and DAC1, BUT do not produces complementary pulses. Unlike PWM or TC direct register programming, analogWrite() has only very limited features:
The Arduino DUE supports analogWrite() on pins 2 through 13, plus pins DAC0 and DAC1. Unlike the PWM pins, DAC0 and DAC1 are Digital to Analog converters, and act as true analog outputs.
You do not need to call pinMode() to set the pin as an output before calling analogWrite().
To output complementary pulses, e.g. on pin 44 (PWMH5) and pin 8 (PWML5), you have to program directly the PWM controller. Here is an example sketch to program PWMH2/PWML2 :
void setup () {
// PWM Set-up on pins PC7 and PA20 (Arduino Pins 39(PWMH2) and 43(PWML2)): see Datasheet chap. 38.5.1 page 973
PMC->PMC_PCER1 |= PMC_PCER1_PID36; // PWM power ON
PWM->PWM_DIS = PWM_DIS_CHID2; // Disable PWM channel 2
// Select Instance=PWM; Signal=PWMH2 (channel 2); I/O Line=PC7 (P7, Arduino pin 39, see pinout diagram) ; Peripheral type =B
PIOC->PIO_PDR |= PIO_PDR_P7; // Set the pin to the peripheral PWM, not the GPIO
PIOC->PIO_ABSR |= PIO_PC7B_PWMH2; // Set PWM pin perhipheral type B
// Select Instance=PWM; Signal=PWML2 (channel 2); I/O Line=PA20 (P20, Arduino pin 43, see pinout diagram) ; Peripheral=B
PIOA->PIO_PDR |= PIO_PDR_P20; // Set the pin to the peripheral PWM, not the GPIO
PIOA->PIO_ABSR |= PIO_PA20B_PWML2; // Set PWM pin perhipheral type B
// Enable the PWM channel 2 (see datasheet page 973)
PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(42); // Set the PWM clock rate to 2MHz (84MHz/42). Adjust DIVA for the resolution you are looking for
PWM->PWM_CH_NUM[2].PWM_CMR = PWM_CMR_CPRE_CLKA; // The period is left aligned, clock source as CLKA on channel 2
PWM->PWM_CH_NUM[2].PWM_CPRD = 100; // Channel 2 : Set the PWM frequency 2MHz/(2 * CPRD) = F ;
PWM->PWM_CH_NUM[2].PWM_CDTY = 50; // Channel 2: Set the PWM duty cycle to x%= (CDTY/ CPRD) * 100 % ;
PWM->PWM_ENA = PWM_ENA_CHID2;
// Alternately, you can use this format : REG_PWM_CPRD2 = 50;
}
void loop() {
}
wouldn't it perhaps be easier to generate a standard pwm signal and then use a MOSFET (perhaps p-channel) to invert it?
What do you call a standard PWM ?
the genuine, non-complementary one.
ard_newbie:
You can generate PWM signals thru the Timer Counters or the PWM controller or analogWrite().analogWrite() produces PWM pulses throughout pins 2 to 13, plus DAC0 and DAC1, BUT do not produces complementary pulses. Unlike PWM or TC direct register programming, analogWrite() has only very limited features:
analogWrite() - Arduino Reference
The Arduino DUE supports analogWrite() on pins 2 through 13, plus pins DAC0 and DAC1. Unlike the PWM pins, DAC0 and DAC1 are Digital to Analog converters, and act as true analog outputs.
You do not need to call pinMode() to set the pin as an output before calling analogWrite().To output complementary pulses, e.g. on pin 44 (PWMH5) and pin 8 (PWML5), you have to program directly the PWM controller. Here is an example sketch to program PWMH2/PWML2 :
void setup () {
// PWM Set-up on pins PC7 and PA20 (Arduino Pins 39(PWMH2) and 43(PWML2)): see Datasheet chap. 38.5.1 page 973
PMC->PMC_PCER1 |= PMC_PCER1_PID36; // PWM power ON
PWM->PWM_DIS = PWM_DIS_CHID2; // Disable PWM channel 2
// Select Instance=PWM; Signal=PWMH2 (channel 2); I/O Line=PC7 (P7, Arduino pin 39, see pinout diagram) ; Peripheral type =B
PIOC->PIO_PDR |= PIO_PDR_P7; // Set the pin to the peripheral PWM, not the GPIO
PIOC->PIO_ABSR |= PIO_PC7B_PWMH2; // Set PWM pin perhipheral type B
// Select Instance=PWM; Signal=PWML2 (channel 2); I/O Line=PA20 (P20, Arduino pin 43, see pinout diagram) ; Peripheral=B
PIOA->PIO_PDR |= PIO_PDR_P20; // Set the pin to the peripheral PWM, not the GPIO
PIOA->PIO_ABSR |= PIO_PA20B_PWML2; // Set PWM pin perhipheral type B
// Enable the PWM channel 2 (see datasheet page 973)
PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(42); // Set the PWM clock rate to 2MHz (84MHz/42). Adjust DIVA for the resolution you are looking for
PWM->PWM_CH_NUM[2].PWM_CMR = PWM_CMR_CPRE_CLKA; // The period is left aligned, clock source as CLKA on channel 2
PWM->PWM_CH_NUM[2].PWM_CPRD = 100; // Channel 2 : Set the PWM frequency 2MHz/(2 * CPRD) = F ;
PWM->PWM_CH_NUM[2].PWM_CDTY = 50; // Channel 2: Set the PWM duty cycle to x%= (CDTY/ CPRD) * 100 % ;
PWM->PWM_ENA = PWM_ENA_CHID2;
// Alternately, you can use this format : REG_PWM_CPRD2 = 50;
}
void loop() {
}
That works, thanks a lot!