News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

CCP5 doesn't seem to work

Started by Yves, Dec 31, 2023, 01:29 PM

Previous topic - Next topic

Yves

I am trying to get HPWM function on the portA.4 on the 18F26k22. the looking at the spec it has CCP5 but I cant even get it running on Proteus simulation. The code is as follow:

Declare CCP5_Pin = PORTA.4      ' The pin used for CCP5
   
 
'------------------------------------------------------------------------

While
    HPWM 5, 100, 2000               ' Start a PWM waveform from CCP1
    DelayMS 20000
Wend

not sure where I'm going wrong
Yves
Yves

RGV250

Hi,
I am slightly confused, you say you want HPWM but set the pin for CCP.
This was in the manual for HPWM
QuoteDeclare HPWM5_Pin Port.Pin ' Select HPWM port and bit for PWM 5 module (ch 5

Bob

Yves

sorry small typo but the code below doesn't work.

'Declare CCP5_Pin = PORTA.4      ' The pin used for CCP5
Declare HPWM5_Pin PORTA.4 ' Select HPWM port and bit for PWM 5 module (ch 5)   
HPWM 5, 100, 2000               ' Start a PWM waveform from CCP5
Yves

AlbertoFS

73's de EA3AGV

top204

#4
I've just created a simple test program and ran it on a device and all the HPWM channels work as expected on a PIC18F26K22 device:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Test the HPWM commands on a PIC18F26K22 device.
'
' Written by Les Johnson for the Positron8 compiler.
'
    Device = 18F26K22                                   ' Tell the compiler what device to compile for
    Declare Xtal = 16                                   ' Tell the compiler what frequency the device will be operating at (in MHz)
'
' Setup the CCP pins for the HPWM command (Can also be named: "CCPx_Pin = Port.Pin"
'
    Declare HPWM1_Pin = PORTC.2
    Declare HPWM2_Pin = PORTC.1
    Declare HPWM3_Pin = PORTB.5
    Declare HPWM4_Pin = PORTB.0
    Declare HPWM5_Pin = PORTA.4

'-------------------------------------------------------------------------------------------
' The main program starts here
'
Main:
    HPWM 1, 127, 2000
    HPWM 2, 127, 2000
    HPWM 3, 127, 2000
    HPWM 4, 127, 2000
    HPWM 5, 127, 2000

With my oscilloscope, I can see each CCP pin has a correct square wave being produced from it.

However, the Proteus simulator is not working correctly with CCP3, CCP4 and CCP5, and nothing is output from their pins. No surprise there, because the simulator is actually getting worse as time goes on, and I am using the very latest version of Proteus.

top204

As well as the above demo program listing, you can see how the CCP peripherals actually work as PWM by using the attached "HPWM_18F.inc" library, and it also gives better control than the HPWM commands.

The "HPWM_18F.inc" library's code listing is shown below. It also shows the new Global Shared variables at work, so global variables can be created in procedures when they are called, and shared amongst each other. I'm busy updating the compiler manuals as I type. :-)

$ifndef _HPWM_INC_
$define _HPWM_INC_
'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' CCP peripherals acting as PWM library.
'
' Written by Les Johnson for the Positron8 BASIC compiler.
' https://sites.google.com/view/rosetta-tech/home
'
' HPWM1_SetFreq(pFrequency, pDuty)
' HPWM2_SetFreq(pFrequency, pDuty)
' HPWM3_SetFreq(pFrequency, pDuty)
' HPWM4_SetFreq(pFrequency, pDuty)
' HPWM5_SetFreq(pFrequency, pDuty)
'
' Alters the frequency the a PWM peripheral and the duty cycle then starts it.
'
' pFrequency alters the frequency (in Hz) of a PWM peripheral and can be any value from 0 to 65535,
' however, lower or upper frequencies depend on the oscillator.
' pDuty alters the duty cycle of a PWM peripheral and can be any value from 0 to 255.
'
' Note that all PWM peripherals share a common timer, therefore will all operate at a common frequency.
' On completion, the Carry flag (STATUSbits_C) will hold 1 if the frequency is achievable.
' Use this as a guide indication only and not as an absolute indicator.
'
'-------------------------------------
' HPWM1_Duty(pDuty)
' HPWM2_Duty(pDuty)
' HPWM3_Duty(pDuty)
' HPWM4_Duty(pDuty)
' HPWM5_Duty(pDuty)
'
' Alters the duty of a PWM peripheral.
'
' pDuty alters the duty cycle of a PWM peripheral and can be any value from 0 to 255.
' Note that all PWM peripherals share a common timer, therefore will all operate ata common frequency
'
'-------------------------------------
' HPWM1_Start()
' HPWM2_Start()
' HPWM3_Start()
' HPWM4_Start()
' HPWM5_Start()
'
' Enables a PWM peripheral
'
'-------------------------------------
' HPWM1_Stop()
' HPWM2_Stop()
' HPWM3_Stop()
' HPWM4_Stop()
' HPWM5_Stop()
'
' Disables a PWM peripheral
'
'-------------------------------------------------------------------------------------------------------
    Symbol HPWM_cFosc = _xtal * 1000

'-----------------------------------------------------------------------------
' Helper routine to calculate a duty cycle required for a given PWM frequency
' Input     : HPWM_wFrequency holds the 16-bit frequency of the PWM
'           : HPWM_bPrescaleSelect holds the 8-bit prescale value
'           : HPWM_bDuty holds the 8-bit duty cycle (0 to 255)
' Output    : HPWM_wCalcDuty holds the 16-bit duty cycle value
' Notes     : None
'
Proc HPWM_mCalculateDuty()
    Dim dMaxDuty                As Dword
Global Dim HPWM_wCalcDuty       As Word Shared
Global Dim HPWM_bPrescaleSelect As Byte Shared                          ' Global shared variable, used to hold the Timer2 prescaler required
Global Dim HPWM_bDuty           As Byte Shared                          ' Global shared variable, used to pass the 8-bit duty cycle as a paramater
Global Dim HPWM_wFrequency      As Word Shared                          ' Global shared variable, used to pass the 16-bit frequency value as a parameter

    HPWM_wCalcDuty = HPWM_wFrequency * HPWM_bPrescaleSelect             ' \
    HPWM_wCalcDuty = HPWM_cFosc / HPWM_wCalcDuty                        ' / Determine maximum duty
    dMaxDuty = HPWM_wCalcDuty * HPWM_bDuty                              ' \
    HPWM_wCalcDuty = dMaxDuty / 256                                     ' / Calculate duty value
EndProc

'-----------------------------------------------------------------------------
' Helper procedure to calculate the values required for a given frequency and duty cycle
' Input     : pFrequency holds the 16-bit frequency (in Hz) (0 to 65535)
'           : pInitialDuty holds the 8-bit duty cycle (0 to 255)
' Output    : STATUSbits_C (Carry flag) holds 1 if the frequency is possibly achievable
' Notes     : None
'
Proc HPWM_SetFreq(pFrequency As HPWM_wFrequency, pInitialDuty As HPWM_bDuty)
    Dim HPWM_wPRConst           As Word
    Dim HPWM_wPR2Value          As Word
Global Dim HPWM_bPrescaleSelect As Byte Shared                          ' Global shared variable, used to hold the Timer2 prescaler required
Global Dim HPWM_bDuty           As Byte Shared                          ' Global shared variable, used to pass the 8-bit duty cycle as a paramater
Global Dim HPWM_wFrequency      As Word Shared                          ' Global shared variable, used to pass the 16-bit frequency value as a parameter

    pFrequency = pFrequency / 1000
    HPWM_wPRConst = HPWM_cFosc / pFrequency
    HPWM_wPRConst = HPWM_wPRConst / 4
'
' Loop through the valid prescalers
'
    HPWM_bPrescaleSelect = 1
    Repeat
        HPWM_wPR2Value = HPWM_wPRConst / HPWM_bPrescaleSelect           ' \
        HPWM_wPR2Value = HPWM_wPR2Value - 1                             ' / Calculate a PR2 value
        If HPWM_wPR2Value <= 255 Then                                   ' \ Is the value to place into PR2 valid?
            If HPWM_wPR2Value > 1 Then                                  ' /
                T2CON = %00000000                                       ' Yes. So Default to T2CON loaded with 0
                If HPWM_bPrescaleSelect = 4 Then                        ' Is HPWM_bPrescaleSelect 4?
                    T2CON = %00000001                                   ' Yes. So adjust T2CON accordingly
                Else If HPWM_bPrescaleSelect = 16 Then                  ' Is HPWM_bPrescaleSelect 16?
                    T2CON = %00000011                                   ' Yes. So adjust T2CON accordingly
                EndIf
                PR2 = HPWM_wPR2Value                                    ' Initialise PR2
                HPWM_mCalculateDuty()                                   ' Calculate the duty value
                T2CONbits_TMR2ON  = 1                                   ' Start Timer2
                STATUSbits_C = 1                                        ' Return Carry flag holding 1 if successful
                ExitProc                                                ' Exit the procedure
            EndIf
        EndIf
        HPWM_bPrescaleSelect = HPWM_bPrescaleSelect * 4                 ' Move to the prescaler select value
    Until HPWM_bPrescaleSelect > 16
    STATUSbits_C = 0                                                    ' Return Carry flag holding 0 if unsuccesful
EndProc

'*****************************************************************************
$ifdef _CCP1CON
'-----------------------------------------------------------------------------
' Start CCP1 operation
' Input     : None
' Output    : None
' Notes     : None
'
$define HPWM1_Start()           '
    CCP1CON = $0C               '
    PinOutput __CCP1_PORT_PIN

'-----------------------------------------------------------------------------
' Stop CCP1 operation
' Input     : None
' Output    : None
' Notes     : None
'
$define HPWM1_Stop()            '
   PinInput __CCP1_PORT_PIN     '
   CCP1CON = $00

'-----------------------------------------------------------------------------
' Helper routine to load the duty cycle into CCPR1L:CCP1CON<5:4>
' Input     : HPWM_wCalcDuty holds the 10-bit value
' Output    : None
' Notes     : CCPR1L contains the eight MSbs, and CCP1CON<5:4> contains the two LSbs.
'           : This 10-Bit value is represented by CCPR1L:CCP1CON<5:4>.
'
Proc HPWM1_mSetDuty()
Global Dim HPWM_wCalcDuty As Word Shared                                ' Global shared variable, used to hold the calculated duty value

    CCP1CON = CCP1CON & %11001111
    WREG = HPWM_wCalcDuty << 4
    WREG = WREG & %00110000
    CCP1CON = CCP1CON | WREG
    CCPR1L = HPWM_wCalcDuty >> 2
EndProc

'-----------------------------------------------------------------------------
' Adjust the duty cycle of CCP1
' Input     : WREG holds the 8-bit duty cycle (0 to 255)
' Output    : None
' Notes     : None
'
Proc HPWM1_Duty(pDuty As HPWM_bDuty)
Global Dim HPWM_bDuty As Byte Shared                                    ' Global shared variable, used to pass the 8-bit duty cycle as a paramater

    HPWM_mCalculateDuty()
    HPWM1_mSetDuty()
EndProc

'-----------------------------------------------------------------------------
' Calculate the values required for a required frequency and duty cycle for CCP1
' Input     : pFrequency holds the 16-bit frequency (in Hz)
'           : pDuty holds the 8-bit duty cycle (0 to 255)
' Output    : STATUSbits_C (Carry flag) holds 1 if the frequency is possibly achievable
' Notes     : Also starts the PWM for CCP1
'
Proc HPWM1_SetFreq(pFrequency As HPWM_wFrequency, pDuty As HPWM_bDuty)
Global Dim HPWM_bDuty      As Byte Shared                               ' Global shared variable, used to pass the 8-bit duty cycle as a paramater
Global Dim HPWM_wFrequency As Word Shared                               ' Global shared variable, used to pass the 16-bit frequency value as a parameter

    HPWM_SetFreq(pFrequency, pDuty)                                     ' Calculate the values for a given frequency and duty cycle
    If STATUSbits_C = 1 Then                                            ' Was the frequency accepted?
        HPWM1_mSetDuty()                                                ' Yes. So load the CCP1 registers with the appropriate value
        HPWM1_Start()                                                   ' Start PWM1
        STATUSbits_C = 1                                                ' Indicate everything OK
    EndIf
EndProc
$endif ' _CCP1CON

'*****************************************************************************
$ifdef _CCP2CON
'-----------------------------------------------------------------------------
' Start CCP2 operation
' Input     : None
' Output    : None
' Notes     : None
'
$define HPWM2_Start()           '
    CCP2CON = $0C               '
    PinOutput __CCP2_PORT_PIN

'-----------------------------------------------------------------------------
' Stop CCP2 operation
' Input     : None
' Output    : None
' Notes     : None
'
$define HPWM2_Stop()        '
   PinInput __CCP2_PORT_PIN '
   CCP2CON = $00

'-----------------------------------------------------------------------------
' Helper routine to load the duty cycle into CCPR2L:CCP2CON<5:4>
' Input     : HPWM_wCalcDuty holds the 10-bit value
' Output    : None
' Notes     : CCPR2L contains the eight MSbs, and CCP2CON<5:4> contains the two LSbs.
'           : This 10-Bit value is represented by CCPR2L:CCP2CON<5:4>.
'
Proc HPWM2_mSetDuty()
Global Dim HPWM_wCalcDuty As Word Shared                                ' Global shared variable, used to hold the calculated duty value

    CCP2CON = CCP2CON & %11001111
    WREG = HPWM_wCalcDuty << 4
    WREG = WREG & %00110000
    CCP2CON = CCP2CON | WREG
    CCPR2L = HPWM_wCalcDuty >> 2
EndProc

'-----------------------------------------------------------------------------
' Adjust the duty cycle of CCP2
' Input     : WREG holds the 8-bit duty cycle (0 to 255)
' Output    : None
' Notes     : None
'
Proc HPWM2_Duty(pDuty As HPWM_bDuty)
Global Dim HPWM_bDuty As Byte Shared                                    ' Global shared variable, used to pass the 8-bit duty cycle as a paramater

    HPWM_mCalculateDuty()
    HPWM2_mSetDuty()
EndProc

'-----------------------------------------------------------------------------
' Calculate the values required for a required frequency and duty cycle for CCP2
' Input     : pFrequency holds the 16-bit frequency (in Hz)
'           : pDuty holds the 8-bit duty cycle (0 to 255)
' Output    : STATUSbits_C (Carry flag) holds 1 if the frequency is possibly achievable
' Notes     : Also starts the PWM For CCP2
'
Proc HPWM2_SetFreq(pFrequency As HPWM_wFrequency, pDuty As HPWM_bDuty)
Global Dim HPWM_bDuty      As Byte Shared                               ' Global shared variable, used to pass the 8-bit duty cycle as a paramater
Global Dim HPWM_wFrequency As Word Shared                               ' Global shared variable, used to pass the 16-bit frequency value as a parameter

    HPWM_SetFreq(pFrequency, pDuty)                                     ' Calculate the values for a given frequency and duty cycle
    If STATUSbits_C = 1 Then                                            ' Was the frequency accepted?
        HPWM2_mSetDuty()                                                ' Yes. So load the CCP2 registers with the appropriate value
        HPWM2_Start()                                                   ' Start PWM2
        STATUSbits_C = 1                                                ' Indicate everything OK
    EndIf
EndProc
$endif ' _CCP2CON

'*****************************************************************************
$ifdef _CCP3CON
'-----------------------------------------------------------------------------
' Start CCP3 operation
' Input     : None
' Output    : None
' Notes     : None
'
$define HPWM3_Start()           '
    CCP3CON = $0C               '
#ifSym __CCP3_PIN               '
    PinOutput __CCP3_PORT_PIN   '
#endIfSym

'-----------------------------------------------------------------------------
' Stop CCP3 operation
' Input     : None
' Output    : None
' Notes     : None
'
$define HPWM3_Stop()            '
#ifSym __CCP3_PIN               '
   PinInput __CCP3_PORT_PIN     '
#endIfSym                       '
   CCP3CON = $00

'-----------------------------------------------------------------------------
' Helper routine to load the duty cycle into CCPR3L:CCP3CON<5:4>
' Input     : HPWM_wCalcDuty holds the 10-bit value
' Output    : None
' Notes     : CCPR3L contains the eight MSBs, and CCP3CON<5:4> contains the two LSbs.
'           : This 10-Bit value is represented by CCPR3L:CCP3CON<5:4>.
'
Proc HPWM3_mSetDuty()
Global Dim HPWM_wCalcDuty As Word Shared                                ' Global shared variable, used to hold the calculated duty value

    CCP3CON = CCP3CON & %11001111
    WREG = HPWM_wCalcDuty << 4
    WREG = WREG & %00110000
    CCP3CON = CCP3CON | WREG
    CCPR3L = HPWM_wCalcDuty >> 2
EndProc

'-----------------------------------------------------------------------------
' Adjust the duty cycle of CCP3
' Input     : WREG holds the 8-bit duty cycle (0 to 255)
' Output    : None
' Notes     : None
'
Proc HPWM3_Duty(pDuty As HPWM_bDuty)
Global Dim HPWM_bDuty As Byte Shared                                    ' Global shared variable, used to pass the 8-bit duty cycle as a paramater

    HPWM_mCalculateDuty()
    HPWM3_mSetDuty()
EndProc

'-----------------------------------------------------------------------------
' Calculate the values required for a required frequency and duty cycle for CCP3
' Input     : pFrequency holds the 16-bit frequency (in Hz)
'           : pDuty holds the 8-bit duty cycle (0 to 255)
' Output    : STATUSbits_C (Carry flag) holds 1 if the frequency is possibly achievable
' Notes     : Also starts the PWM For CCP3
'
Proc HPWM3_SetFreq(pFrequency As HPWM_wFrequency, pDuty As HPWM_bDuty)
Global Dim HPWM_bDuty      As Byte Shared                               ' Global shared variable, used to pass the 8-bit duty cycle as a paramater
Global Dim HPWM_wFrequency As Word Shared                               ' Global shared variable, used to pass the 16-bit frequency value as a parameter

    HPWM_SetFreq(pFrequency, pDuty)                                     ' Calculate the values for a given frequency and duty cycle
    If STATUSbits_C = 1 Then                                            ' Was the frequency accepted?
        HPWM3_mSetDuty()                                                ' Yes. So load the CCP3 registers with the appropriate value
        HPWM3_Start()                                                   ' Start PWM3
        STATUSbits_C = 1                                                ' Indicate everything OK
    EndIf
EndProc
$endif  ' _CCP3CON

'*****************************************************************************
$ifdef _CCP4CON
'-----------------------------------------------------------------------------
' Start CCP4 operation
' Input     : None
' Output    : None
' Notes     : None
'
$define HPWM4_Start()           '
    CCP4CON = $0C               '
#ifSym __CCP4_PIN               '
    PinOutput __CCP4_PORT_PIN   '
#endIfSym

'-----------------------------------------------------------------------------
' Stop CCP4 operation
' Input     : None
' Output    : None
' Notes     : None
'
$define HPWM4_Stop()            '
#ifSym __CCP4_PIN               '
   PinInput __CCP4_PORT_PIN     '
#endIfSym                       '
   CCP4CON = $00

'-----------------------------------------------------------------------------
' Helper routine to load the duty cycle into CCPR4L:CCP4CON<5:4>
' Input     : HPWM_wCalcDuty holds the 10-bit value
' Output    : None
' Notes     : CCPR4L contains the eight MSBs, and CCP4CON<5:4> contains the two LSbs.
'           : This 10-Bit value is represented by CCPR4L:CCP4CON<5:4>.
'
Proc HPWM4_mSetDuty()
Global Dim HPWM_wCalcDuty As Word Shared                                ' Global shared variable, used to hold the calculated duty value

    CCP4CON = CCP4CON & %11001111
    WREG = HPWM_wCalcDuty << 4
    WREG = WREG & %00110000
    CCP4CON = CCP4CON | WREG
    CCPR4L = HPWM_wCalcDuty >> 2
EndProc

'-----------------------------------------------------------------------------
' Adjust the duty cycle of CCP4
' Input     : WREG holds the 8-bit duty cycle (0 to 255)
' Output    : None
' Notes     : None
'
Proc HPWM4_Duty(pDuty As HPWM_bDuty)
Global Dim HPWM_bDuty As Byte Shared                                    ' Global shared variable, used to pass the 8-bit duty cycle as a paramater

    HPWM_mCalculateDuty()
    HPWM4_mSetDuty()
EndProc

'-----------------------------------------------------------------------------
' Calculate the values required for a required frequency and duty cycle for CCP4
' Input     : pFrequency holds the 16-bit frequency (in Hz)
'           : pDuty holds the 8-bit duty cycle (0 to 255)
' Output    : STATUSbits_C (Carry flag) holds 1 if the frequency is possibly achievable
' Notes     : Also starts the PWM For CCP4
'
Proc HPWM4_SetFreq(pFrequency As HPWM_wFrequency, pDuty As HPWM_bDuty)
Global Dim HPWM_bDuty      As Byte Shared                               ' Global shared variable, used to pass the 8-bit duty cycle as a paramater
Global Dim HPWM_wFrequency As Word Shared                               ' Global shared variable, used to pass the 16-bit frequency value as a parameter

    HPWM_SetFreq(pFrequency, pDuty)                                     ' Calculate the values for a given frequency and duty cycle
    If STATUSbits_C = 1 Then                                            ' Was the frequency accepted?
        HPWM4_mSetDuty()                                                ' Yes. So load the CCP4 registers with the appropriate value
        HPWM4_Start()                                                   ' Start PWM4
        STATUSbits_C = 1                                                ' Indicate everything OK
    EndIf
EndProc
$endif  ' _CCP4CON

'*****************************************************************************
$ifdef _CCP5CON
'-----------------------------------------------------------------------------
' Start CCP5 operation
' Input     : None
' Output    : None
' Notes     : None
'
$define HPWM5_Start()           '
    CCP5CON = $0C               '
#ifSym __CCP5_PIN               '
    PinOutput __CCP5_PORT_PIN   '
#endIfSym

'-----------------------------------------------------------------------------
' Stop CCP5 operation
' Input     : None
' Output    : None
' Notes     : None
'
$define HPWM5_Stop()            '
#ifSym __CCP5_PIN               '
   PinInput __CCP5_PORT_PIN     '
#endIfSym                       '
   CCP5CON = $00

'-----------------------------------------------------------------------------
' Helper routine to load the duty cycle into CCPR5L:CCP5CON<5:4>
' Input     : HPWM_wCalcDuty holds the 10-bit value
' Output    : None
' Notes     : CCPR5L contains the eight MSBs, and CCP5CON<5:4> contains the two LSbs.
'           : This 10-Bit value is represented by CCPR5L:CCP5CON<5:4>.
'
Proc HPWM5_mSetDuty()
Global Dim HPWM_wCalcDuty As Word Shared                                ' Global shared variable, used to hold the calculated duty value

    CCP5CON = CCP5CON & %11001111
    WREG = HPWM_wCalcDuty << 4
    WREG = WREG & %00110000
    CCP5CON = CCP5CON | WREG
    CCPR5L = HPWM_wCalcDuty >> 2
EndProc

'-----------------------------------------------------------------------------
' Adjust the duty cycle of CCP5
' Input     : WREG holds the 8-bit duty cycle (0 to 255)
' Output    : None
' Notes     : None
'
Proc HPWM5_Duty(pDuty As HPWM_bDuty)
Global Dim HPWM_bDuty As Byte Shared                                    ' Global shared variable, used to pass the 8-bit duty cycle as a paramater

    HPWM_mCalculateDuty()
    HPWM5_mSetDuty()
EndProc

'-----------------------------------------------------------------------------
' Calculate the values required for a required frequency and duty cycle for CCP5
' Input     : pFrequency holds the 16-bit frequency (in Hz)
'           : pDuty holds the 8-bit duty cycle (0 to 255)
' Output    : STATUSbits_C (Carry flag) holds 1 if the frequency is possibly achievable
' Notes     : Also starts the PWM For CCP5
'
Proc HPWM5_SetFreq(pFrequency As HPWM_wFrequency, pDuty As HPWM_bDuty)
Global Dim HPWM_bDuty      As Byte Shared                               ' Global shared variable, used to pass the 8-bit duty cycle as a paramater
Global Dim HPWM_wFrequency As Word Shared                               ' Global shared variable, used to pass the 16-bit frequency value as a parameter

    HPWM_SetFreq(pFrequency, pDuty)                                     ' Calculate the values for a given frequency and duty cycle
    If STATUSbits_C = 1 Then                                            ' Was the frequency accepted?
        HPWM5_mSetDuty()                                                ' Yes. So load the CCP5 registers with the appropriate value
        HPWM5_Start()                                                   ' Start PWM5
        STATUSbits_C = 1                                                ' Indicate everything OK
    EndIf
EndProc
$endif  ' _CCP5CON

$endif      ' _HPWM_INC_

A demonstration program for a PIC18F26K22 device is listed below, that uses the "HPWM_18F.inc" library, and the code listing below actually seems to work in the proteus simulator, so there is a subtlety in the compiler's optimised library assembler code that the proteus simulator does not seem to simulate correctly. :-)

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Demonstrate Hardware PWM routines that make use of the extra CCP peripherals contained on some devices.
' It also allows frequencies upto 65535Hz
' Low end frequencies and high end frequencies depend on the oscillator value used.
' Frequencies may be approximate depending on the oscillator value used and the frequency required.
' This is not due to a limitation of the compiler, but of the peripheral itself.
'
' Note. All PWM peripherals will share a common frequency because they are all set to use Timer2.
'
' Written by Les Johnson for the Positron8 BASIC compiler.
' https://sites.google.com/view/rosetta-tech/home
'
    Device = 18F26K22                                   ' Tell the compiler what device to compile for
    Declare Xtal = 16                                   ' Tell the compiler what frequency the device will be operating at (in MHz)
'
' Setup which pins are used by the CCP peripherals
' Note that for some CCP port.pins, config fuse changes will be required
'
    Declare CCP1_Pin = PORTC.2
    Declare CCP2_Pin = PORTC.1
    Declare CCP3_Pin = PORTB.5
    Declare CCP4_Pin = PORTB.0
    Declare CCP5_Pin = PORTA.4

    Include "HPWM_18F.inc"                              ' Load the HPWM library into the program
'
' Create variables for the demo here
'
    Dim Duty      As Byte                               ' Holds the duty cycle value (0 to 255)
    Dim Frequency As Word                               ' Holds the frequency value

'---------------------------------------------------------------------------
Main:
'
' Adjust the frequency of all the CCP peripherals
'
(*
    For Frequency = 0 To 65535 Step 64                  ' Create a loop for frequency adjustment
        HPWM1_SetFreq(Frequency,127)                    ' Alter frequency with 50% duty cycle
        HPWM2_SetFreq(Frequency,127)                    ' Alter frequency with 50% duty cycle
        HPWM3_SetFreq(Frequency,127)                    ' Alter frequency with 50% duty cycle
        HPWM4_SetFreq(Frequency,127)                    ' Alter frequency with 50% duty cycle
        HPWM5_SetFreq(Frequency,127)                    ' Alter frequency with 50% duty cycle
        DelayMS 1
    Next
*)
'
' Adjust the duty cycles of all peripherals
'
    HPWM_SetFreq(2000,0)                                ' Set the frequency of all PWM peripherals

    HPWM1_Start()                                       ' \
    HPWM2_Start()                                       ' | Enable all peripherals
    HPWM3_Start()                                       ' |
    HPWM4_Start()                                       ' |
    HPWM5_Start()                                       ' /

    Do                                                  ' Create a loop
        For Duty = 0 To 255                             ' Create a duty cycle loop (0 to 255)
            HPWM1_Duty(Duty)                            ' \
            HPWM2_Duty(Duty)                            ' |
            HPWM3_Duty(Duty)                            ' | Adjust the duty cycle of the PWM
            HPWM4_Duty(Duty)                            ' |
            HPWM5_Duty(Duty)                            ' /
            DelayMS 10
        Next
    Loop                                                ' Do it forever

If you want all programs to see the library "HPWM_18F.inc" file, copy it into the users Includes folder here: "C:\Users\User Name\PDS\Includes\". Otherwise, the library include file needs to be in the folder that is including it.

The "HPWM_18F.inc" library and the demo program are attached to this post as a zip file named: "HPWM_18F_Library.zip".

Yves

Hello Les,
First of all, compliments for the season and thank you for your valuable help.

Kind regards,

Yves
Yves