Page 1 of 1

HPWM16 - 16bit hardware PWM module

Posted: Thu Dec 07, 2023 3:08 pm
by Jerry Messina
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

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