Inverted PWM using NCO mode
ctwardell
Posts: 1,716
I'm working on a driver for the TI DRV8833 motor driver and it needs an inverted PWM signal when used in the "slow decay / brake" mode.
After looking at some code for doing PWM using the counter NCO mode I realized that if I could just count down instead of up I could do "inverted" PWM.
Since NCO mode adds FRQx to PHSx, setting FRQx to -1 (2^32 - 1) allows us to count down. By setting a positive PHSx value and counting down we can do inverted PWM.
This may already be a known technique, but I didn't see it anywhere so I thought I would share it.
An example using a modified version of code from the PEK is given below.
C.W.
After looking at some code for doing PWM using the counter NCO mode I realized that if I could just count down instead of up I could do "inverted" PWM.
Since NCO mode adds FRQx to PHSx, setting FRQx to -1 (2^32 - 1) allows us to count down. By setting a positive PHSx value and counting down we can do inverted PWM.
This may already be a known technique, but I didn't see it anywhere so I thought I would share it.
An example using a modified version of code from the PEK is given below.
C.W.
{{ // TestInvertedPWM.spin // Modified version of TestDualPWM.spin // PEK Manual v1.2 page 164 // Used to demonstrate inverted PWM using counter NCO mode using the LED's // on a QuickStart board. // // The NCO mode outputs that value of phsx[31] on the selected output pin. // // "Normal" PWM usage is to set frqx = 1 and load phsx with the negative of the // desired PWM count. This sets the output pin high until phsx is incremented to 0 // resulting in phsx[31] going low which sets the output pin low. // // "Inverted" PWM usage is to set frqx = -1 and load phsx with the desired PWM count. // This sets the output pin low until phsx is decremented to -1 // resulting in phsx[31] going high which sets the output pin high. // // Setting frqx = -1 sets frqx to 2^32 - 1, adding this value // to phsx results in subtracting 1 from phsx, allowing us to count down instead of up. // // This is useful for cases when an inverted PWM signal is required. }} CON _clkmode = xtal1 + pll16x ' System clock → 80 MHz _xinfreq = 5_000_000 PUB TestPwm | tc, tHa, tHb, t ctra[30..26] := ctrb[30..26] := %00100 ' Counters A and B → NCO single-ended ctra[5..0] := 16 ' Set pins for counters to control ctrb[5..0] := 17 frqa := 1 ' Add 1 to phsa with each clock tick (PWM active high use +1 frqa value) frqb := -1 ' Add -1 to phsb with each clock tick (PWM active low use -1 frqa value) dira[16] := dira[17] := 1 ' Set I/O pins to output tC := clkfreq ' Set up cycle time tHa := clkfreq/5 tHb := clkfreq/5 - 1 'Subtract 1 because 0 is still positive t := cnt ' Mark current time. repeat ' Repeat PWM signal phsa := -tHa ' Define and start the A pulse. PWM active high use negative phsa value. phsb := tHb ' Define and start the B pulse. PWM active low use positive phsa value. t += tC ' Calculate next cycle repeat waitcnt(t) ' Wait for next cycle