HPWM16 - 16bit hardware PWM module
Posted: Thu Dec 07, 2023 3:08 pm
Here's a preview of the 16-bit hardware PWM module for devices with a PWM module (Q family).
These devices have multiple PWM modules with up to 2 outputs each, so a single HPWM16.bas instance can provide up to 8 PWM outputs depending on the device and configuration.
main_ex1.bas
These devices have multiple PWM modules with up to 2 outputs each, so a single HPWM16.bas instance can provide up to 8 PWM outputs depending on the device and configuration.
main_ex1.bas
Code: Select all
// HPWM16 example
device = 18F27Q43 // 3 PWM modules
clock = 64
include "intosc.bas"
#option DIGITALIO_INIT = true // call SetAllDigital at startup
include "setdigitalio.bas"
// pps module
include "pps.bas"
// if using the device files from SF v2240 you must define the max number of PWM modules supported by the device
// later versions of device files include this setting
#if not defined(_device_file_version) or (_device_file_version < 200)
#warning "must add '#const _pwm' for this version device file"
#const _pwm = 3 // 18FxxQ43
#endif
// hpwm16 module
include "HPWM16.bas"
// map PWM outputs to PORTC via PPS
sub initIO()
// set PORTC to output
LATC = 0
TRISC = 0
// map PWM outputs
pps.unlock()
// module: PWM1
pps.assign_output(RC0PPS, PPS_PWM1S1P1_OUT) // PWM11 > RC0
pps.assign_output(RC1PPS, PPS_PWM1S1P2_OUT) // PWM12 > RC1
#if (_pwm >= 2)
// module: PWM2
pps.assign_output(RC2PPS, PPS_PWM2S1P1_OUT) // PWM21 > RC2
pps.assign_output(RC3PPS, PPS_PWM2S1P2_OUT) // PWM22 > RC3
#endif
#if (_pwm >= 3)
// module: PWM3
pps.assign_output(RC4PPS, PPS_PWM3S1P1_OUT) // PWM31 > RC4
pps.assign_output(RC5PPS, PPS_PWM3S1P2_OUT) // PWM32 > RC5
#endif
#if (_pwm >= 4)
// module: PWM4
pps.assign_output(RC6PPS, PPS_PWM4S1P1_OUT) // PWM41 > RC6
pps.assign_output(RC7PPS, PPS_PWM4S1P2_OUT) // PWM42 > RC7
#endif
end sub
dim cfg as byte
// main program
initIO()
// PWM1 - using the default clock source setting
HPWM16.SetConfig(1, PWMxCFG_DEFAULT_CONFIG) // out1 pol=high true, out2 pol=high true, LEFT_ALIGN mode
HPWM16.SetFreq(1, 100000, 50, 25) // pwm freq = 100khz, out1=50% dutycycle, out2=25% dutycycle
// PWM2 - low-level control
HPWM16.SetConfig(2, PWMxCFG_DEFAULT_CONFIG) // out1 pol=high true, out2 pol=high true, LEFT_ALIGN mode
HPWM16.SetClockSrc(2, PWMxCLK_FOSC) // clock source is FOSC
HPWM16.SetPrescaler(2, 64) // prescaler 1:64
HPWM16.SetPeriod(2, 20000) // set period
HPWM16.SetPWM1(2, 10000) // out1=50% dutycycle
HPWM16.SetPWM2(2, 5000) // out2=25% dutycycle
HPWM16.PWMEnable(2) // start
// PWM3 - vary duty cycles
HPWM16.SetConfig(3, PWMxCFG_DEFAULT_CONFIG) // out1 pol=high true, out2 pol=high true, LEFT_ALIGN mode
HPWM16.SetClockSrc(3, PWMxCLK_FOSC) // clock source is FOSC
HPWM16.SetFreq(3, MaxFreq(3)/10) // pwm freq is max freq/10
HPWM16.SetDutyCycle1(3, 0) // out1 0% (low)
HPWM16.SetDutyCycle1(3, 100) // out1 100% (high)
HPWM16.SetDutyCycle1(3, 50) // out1 50%
HPWM16.SetDutyCycle2(3, 50) // out2 50%
// invert out2
cfg = PWMxCFG_LEFT_ALIGN
cfg.bits(POL2) = 1
cfg.bits(POL1) = 0
SetConfig(3, cfg)
PWMEnable(3)
while (true)
end while