News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

PIC16F18425 PWM

Started by joesaliba, Dec 05, 2025, 04:39 PM

Previous topic - Next topic

joesaliba

Finally I have some limited time to get going with some projects I left standstill for a very long period of time.

I am trying to make use of PWM on a PIC16F18425, however, I am unable to do so.

I first changed the PPS to the desired pin: -

Proc Setup()
    PPS_UnLock()
        RC5PPS = 0x0D           ' RC5 CCP1(Pin 3) bi-directional to Module CCP1
    PPS_Lock()
 EndProc

Then so far all I did is the following. I seen many examples re TMR2 but I just cannot get my head around it.

pwm6con.4 = 0
 pwm6con.7 = 1

for jb = 0 to 255
    delayms 200
   
    PW = jb
    PW = PW << 5
    pwm6dc = PW                     ' Load the MSB of the 10-bit duty value

next

Thank you




joesaliba

I tried to add a TMR2 but still nothing: -

trisc.5 = 1

 ' Let's assume you want a PWM frequency of 1 kHz. So PR2 = 199 for a 1 kHz PWM frequency
 pr2 = 199
 t2con.4 = 0
 t2con.5 = 0
 t2con.6 = 0
 t2con.7 = 1

 ' Configure CCP1 for PWM
 ccp1con.0 = 0
 ccp1con.1 = 0
 ccp1con.2 = 1
 ccp1con.3 = 1

 ' Set the 8 most significant bits of the duty cycle (50% of 255)
 ccpr1l = 100

 ' Enable PWM output on RC5 pin
 trisc.5 = 0
 ccp1con.7 = 1

Changed PPS to : -

Proc Setup()
    PPS_UnLock()
    CCP1PPS = 0x15              'RC5 CCP1(Pin 5) bi-directional to Module CCP1
    RC5PPS  = 0x09              'RC5 CCP1(Pin 5) bi-directional to Module CCP1
    PPS_Lock()
 EndProc

top204

#2
Try the code listing below Joe.

It is not actually tested because I do not have that particular device, but according to the datasheet, it should work. Famous last words. :-)
If not, it should give you some ideas on how to implement the CCP peripherals as PWM, and the PWM peripherals.

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Internal Oscillator operating at 32MHz code listing template for a PIC16F18425 device.
' Experimental PWM1 (CCP1) and PWM6 setups.
'
' Written by Les Johnson for the Positron8 BASIC Compiler.
'
    Device = 16F18425                                       ' Tell the compiler what device to compile for
    Declare Xtal = 32                                       ' Tell the compiler what frequency the device is operating at (in MHz)
    Declare Auto_Heap_Strings = On                          ' Make all Strings "Heap" types, so they always get placed after standard variables
    Declare Auto_Variable_Bank_Cross = On                   ' Make sure all multi-byte variables remain within a single RAM bank (for extra efficiency)
'
' Setup USART1
'
    Declare Hserial_Baud = 9600                             ' Set the Baud rate for USART1
    Declare HRSOut1_Pin  = PORTC.4                          ' Tell the compiler to setup pin PORTC.4 for USART1 Tx
    Declare HRSIn1_Pin   = PORTC.5                          ' Tell the compiler to setup pin PORTC.5 for USART1 Rx
'
' Create global variable here
'
    Dim wDuty As Word

'------------------------------------------------------------------------------------------
' The main program starts here
' Alter PWM duty values
'
Main:
    Setup()                                                         ' Setup the program and any peripherals

    Do
        For wDuty = 0 To 255
            PWM1_Duty(wDuty)
            PWM6_Duty(wDuty)
            DelayMs 10
        Next
    Loop

'------------------------------------------------------------------------------------------
' Setup the program and any peripherals
' Input     : None
' Outout    : None
' Notes     : None
'
Proc Setup()
    Osc_32MHz()                                                     ' Initialise the oscillator on a PIC16F18425 device to operate at 32MHz
    PPS_Unlock()
    RC0PPS = PPS_Fn_CCP1                                            ' PORTC.0 is CCP1 Out
    RC1PPS = PPS_Fn_PWM6OUT                                         ' PORTC.1 is PWM6 Out
    Timer2_Init()                                                   ' Setup Timer2 to operate as the PWM clock
    PWM1_Init()                                                     ' Setup CCP1 to operate as PWM
    PWM6_Init()                                                     ' Setup the PWM6 peripheral
    PinOutput PORTC.0
    PinOutput PORTC.1
EndProc

'------------------------------------------------------------------------------------------
' Setup Timer2
' Input     : None
' Outout    : None
' Notes     : Operates at 100 us (10KHz), when used on a device running at 32MHz
'
Proc Timer2_Init()
    T2CLKCON = $01                                                  ' T2CS is FOSC/4
    T2HLT = $00
    T2RST = $00
    T2PR = $18
    T2TMR = $00
    PIR4bits_TMR2IF = 0
    T2CON = %11010000                                               ' Prescaler is 1:32. Postscaler is 1:1. Timer2 on
EndProc

'------------------------------------------------------------------------------------------
' Setup CCP1 to operate as PWM
' Input     : None
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM1_Init()
    CCP1CON = %10001100                                             ' Mode is PWM. CCP1 enabled. FMT is right aligned
    CCPR1H = $00
    CCPR1L = $31
    CCPTMRS0.0 = 1                                                  ' \ Select Timer2 as the PWM source
    CCPTMRS0.1 = 0                                                  ' /
EndProc

'------------------------------------------------------------------------------------------
' Write the duty value to PWM1
' Input     : pDuty holds the duty value
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM1_Duty(pDuty As Word)
    pDuty = pDuty & $03FF
'
' Load the duty cycle value
'
    'If CCP1CONbits_FMT = 1 Then
    '    pDuty = pDuty << 6
    '    CCPR1H = pDuty >> 8
    '    CCPR1L = pDuty
    'Else
        CCPR1H = pDuty.Byte1
        CCPR1L = pDuty.Byte0
    'EndIf
EndProc

'------------------------------------------------------------------------------------------
' Setup PWM6
' Input     : None
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM6_Init()
    PWM6CON = %10000000                                             ' PWM6POL is active high. PWM6 is enabled
    PWM6DCH = $0C
    PWM6DCL = $40
    CCPTMRS1.2 = 1                                                  ' Select Timer2 as the PWM source
    CCPTMRS1.3 = 0
EndProc

'------------------------------------------------------------------------------------------
' Write the duty value to PWM6
' Input     : pDuty holds the duty value
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM6_Duty(pDuty As Word)
     PWM6DCH = (pDuty & $03FC) >> 2                                 ' Write to 8 MSBs of PWM duty cycle in PWMDCH register
     PWM6DCL = (pDuty & $0003) << 6                                 ' Write to 2 LSBs of PWM duty cycle in PWMDCL register
EndProc

'------------------------------------------------------------------------------------------
' Initialise the device to use its internal oscillator at 32MHz
' Input     : None
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc Osc_32MHz()
    OSCCON1 = %01100000
    OSCCON3 = %00000000
    OSCEN =   %00000000
    OSCFRQ =  %00000110                                             ' HFFRQ is 32MHz
    OSCTUNE = %00000000
EndProc

'------------------------------------------------------------------------------------------
' Setup the config fuses for an internal oscillator on a PIC16F18425 device
' The OSC pins are general purpose I/O lines
'
    Config1 FEXTOSC_OFF,_                                           ' External Oscillator not enabled
            RSTOSC_HFINT1,_                                         ' Power-up default is HFINTOSC
            CLKOUTEN_OFF,_                                          ' CLKOUT function is disabled
            CSWEN_ON,_                                              ' Writing to NOSC and NDIV is allowed
            FCMEN_ON                                                ' Fail-Safe Clock Monitor  enabled

    Config2 MCLRE_ON,_                                              ' MCLR pin is Master Clear function
            PWRTS_OFF,_                                             ' Power-up Timer disabled
            LPBOREN_OFF,_                                           ' Low-Power BOR disabled
            BOREN_ON,_                                              ' Brown-out resetEnabled, SBOREN bit is ignored
            BORV_LO,_                                               ' Brown-out Reset Voltage (VBOR) set to 2.45V
            ZCDDIS_OFF,_                                            ' Zero-cross detect circuit is disabled at POR
            PPS1WAY_OFF,_                                           ' The PPSLOCK bit can be cleared and set multiple times in software
            STVREN_ON                                               ' Stack Overflow or Underflow will cause a reset

    Config3 WDTCPS_WDTCPS_31,_                                      ' WDT Period Divider ratio 1:65536. Software control of WDTPS
            WDTE_OFF,_                                              ' WDT Disabled, SWDTEN is ignored
            WDTCWS_WDTCWS_7,_                                       ' WDT window always open (100%). Software control
            WDTCCS_SC                                               ' WDT input clock is Software Control

    Config4 BBSIZE_BB512,_                                          ' Boot Block Size 512 words boot block size
            BBEN_OFF,_                                              ' Boot Block disabled
            SAFEN_OFF,_                                             ' SAF disabled
            WRTAPP_OFF,_                                            ' Application Block not write protected
            WRTB_OFF,_                                              ' Boot Block not write protected
            WRTC_OFF,_                                              ' Configuration Register not write protected
            WRTD_OFF,_                                              ' Data EEPROM not write protected
            WRTSAF_OFF,_                                            ' Storage Area Flash not write protected
            LVP_OFF                                                 ' High Voltage on MCLR/Vpp must be used for programming

    Config5 CP_OFF                                                  ' UserNVM Program memory code protection disabled

joesaliba

Many thanks Les for the code.

I got the PWM6 working. Did not try the other.

Since I am only driving an LED, and running the PIC at 4MHz, I tried to change the frequency to 1.2KHz.

I changed T2PR to $4B, and T2CON to %10000000.

Seems to be working ok, not sure about the frequency as I do not have an oscilloscope at the moment.

If I want to change the pin to use it as a normal output pin, what shall I do to the PPS? Just clear the RC5PPS in my case PORTC.5?

Please check your storypainter email.

Thank you
Kind regards

joe

joesaliba

Les,

I can understand that the code is meant for an 8-bit PWM. What shall I do to change it to 10-bit?

The reason is that I have some timings which will be better if 10-bit resolution is used.

PIC is running at 4MHz.

midali

Hi Joe.

Test this code if it's working at 32MHz:

    Device = 16F18425                                       ' Tell the compiler what device to compile for
    Declare Xtal = 32                                       ' Tell the compiler what frequency the device is operating at (in MHz)
    Declare Auto_Heap_Strings = On                          ' Make all Strings "Heap" types, so they always get placed after standard variables
    Declare Auto_Variable_Bank_Cross = On                   ' Make sure all multi-byte variables remain within a single RAM bank (for extra efficiency)
'
' Setup USART1
'
    Declare Hserial_Baud = 9600                             ' Set the Baud rate for USART1
    Declare HRSOut1_Pin  = PORTC.4                          ' Tell the compiler to setup pin PORTC.4 for USART1 Tx
    Declare HRSIn1_Pin   = PORTC.5                          ' Tell the compiler to setup pin PORTC.5 for USART1 Rx
'
' Create global variable here
'
    Dim wDuty As Word
    Dim wDuty10Bit As Word

'------------------------------------------------------------------------------------------
' The main program starts here
' Alter PWM duty values with 10-bit resolution (0-1023)
'
Main:
    Setup()                                                         ' Setup the program and any peripherals

    Do
        ' Sweep from 0 to 1023 (10-bit resolution)
        For wDuty10Bit = 0 To 1023
            PWM1_Duty10Bit(wDuty10Bit)                             ' Set PWM1 duty (0-1023)
            PWM6_Duty10Bit(wDuty10Bit)                             ' Set PWM6 duty (0-1023)
           
            ' For debugging: send duty value to serial
            HRSOut "Duty: ", Dec4 wDuty10Bit, " (",
                   Dec (wDuty10Bit * 100 / 1023), "%)"
            HRSOutLn ""
           
            DelayMs 20
        Next
       
        ' Sweep back from 1023 to 0
        For wDuty10Bit = 1023 To 0 Step -1
            PWM1_Duty10Bit(wDuty10Bit)
            PWM6_Duty10Bit(wDuty10Bit)
            DelayMs 20
        Next
    Loop

'------------------------------------------------------------------------------------------
' Setup the program and any peripherals
' Input     : None
' Outout    : None
' Notes     : None
'
Proc Setup()
    Osc_32MHz()                                                     ' Initialise the oscillator on a PIC16F18425 device to operate at 32MHz
    PPS_Unlock()
    RC0PPS = PPS_Fn_CCP1                                            ' PORTC.0 is CCP1 Out
    RC1PPS = PPS_Fn_PWM6OUT                                         ' PORTC.1 is PWM6 Out
    Timer2_Init()                                                   ' Setup Timer2 to operate as the PWM clock
    PWM1_Init()                                                     ' Setup CCP1 to operate as PWM with 10-bit resolution
    PWM6_Init()                                                     ' Setup the PWM6 peripheral with 10-bit resolution
    PinOutput PORTC.0
    PinOutput PORTC.1
   
    HRSOutLn "10-bit PWM Demo Started"
    HRSOutLn "Range: 0-1023 (10-bit resolution)"
    HRSOutLn ""
EndProc

'------------------------------------------------------------------------------------------
' Setup Timer2 for 10-bit PWM resolution
' Input     : None
' Outout    : None
' Notes     : Timer period set for 10-bit resolution
'
Proc Timer2_Init()
    T2CLKCON = $01                                                  ' T2CS is FOSC/4
    T2HLT = $00
    T2RST = $00
    T2PR = $FF                                                      ' Maximum period for 10-bit resolution
    T2TMR = $00
    PIR4bits_TMR2IF = 0
    T2CON = %10000000                                               ' Prescaler is 1:1. Timer2 on
EndProc

'------------------------------------------------------------------------------------------
' Setup CCP1 to operate as PWM with 10-bit resolution
' Input     : None
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM1_Init()
    CCP1CON = %10001100                                             ' Mode is PWM. CCP1 enabled. FMT is right aligned (10-bit)
    CCPR1H = $00                                                    ' Start with 0% duty
    CCPR1L = $00
    CCPTMRS0.0 = 1                                                  ' \ Select Timer2 as the PWM source
    CCPTMRS0.1 = 0                                                  ' /
EndProc

'------------------------------------------------------------------------------------------
' Write the 10-bit duty value to PWM1
' Input     : pDuty holds the duty value (0-1023)
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM1_Duty10Bit(pDuty As Word)
    ' Ensure value is within 10-bit range
    If pDuty > 1023 Then pDuty = 1023
   
    ' For 10-bit right-aligned mode:
    ' CCPR1L contains bits 1:0 of duty cycle
    ' CCPR1H contains bits 9:2 of duty cycle
   
    CCPR1H = (pDuty >> 2) And $FF      ' Bits 9:2
    CCPR1L = (pDuty << 6) And $C0      ' Bits 1:0 shifted to bits 7:6
EndProc

'------------------------------------------------------------------------------------------
' Write the 8-bit duty value to PWM1 (backward compatibility)
' Input     : pDuty holds the duty value (0-255)
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM1_Duty(pDuty As Byte)
    ' Convert 8-bit to 10-bit (scale 0-255 to 0-1023)
    Dim wDuty10 As Word
    wDuty10 = pDuty * 4
    PWM1_Duty10Bit(wDuty10)
EndProc

'------------------------------------------------------------------------------------------
' Setup PWM6 for 10-bit resolution
' Input     : None
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM6_Init()
    PWM6CON = %10000000                                             ' PWM6POL is active high. PWM6 is enabled
    PWM6DCH = $00                                                   ' Start with 0% duty
    PWM6DCL = $00
    CCPTMRS1.2 = 1                                                  ' Select Timer2 as the PWM source
    CCPTMRS1.3 = 0
EndProc

'------------------------------------------------------------------------------------------
' Write the 10-bit duty value to PWM6
' Input     : pDuty holds the duty value (0-1023)
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM6_Duty10Bit(pDuty As Word)
    ' Ensure value is within 10-bit range
    If pDuty > 1023 Then pDuty = 1023
   
    ' For 10-bit PWM6:
    ' PWM6DCL contains bits 1:0 of duty cycle in bits 7:6
    ' PWM6DCH contains bits 9:2 of duty cycle
   
    PWM6DCH = (pDuty >> 2) And $FF      ' Bits 9:2
    PWM6DCL = (pDuty << 6) And $C0      ' Bits 1:0 shifted to bits 7:6
EndProc

'------------------------------------------------------------------------------------------
' Write the 8-bit duty value to PWM6 (backward compatibility)
' Input     : pDuty holds the duty value (0-255)
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM6_Duty(pDuty As Byte)
    ' Convert 8-bit to 10-bit (scale 0-255 to 0-1023)
    Dim wDuty10 As Word
    wDuty10 = pDuty * 4
    PWM6_Duty10Bit(wDuty10)
EndProc

'------------------------------------------------------------------------------------------
' Initialise the device to use its internal oscillator at 32MHz
' Input     : None
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc Osc_32MHz()
    OSCCON1 = %01100000
    OSCCON3 = %00000000
    OSCEN =   %00000000
    OSCFRQ =  %00000110                                             ' HFFRQ is 32MHz
    OSCTUNE = %00000000
EndProc

'------------------------------------------------------------------------------------------
' Setup the config fuses for an internal oscillator on a PIC16F18425 device
' The OSC pins are general purpose I/O lines
'
    Config1 FEXTOSC_OFF,_                                           ' External Oscillator not enabled
            RSTOSC_HFINT1,_                                         ' Power-up default is HFINTOSC
            CLKOUTEN_OFF,_                                          ' CLKOUT function is disabled
            CSWEN_ON,_                                              ' Writing to NOSC and NDIV is allowed
            FCMEN_ON                                                ' Fail-Safe Clock Monitor  enabled

    Config2 MCLRE_ON,_                                              ' MCLR pin is Master Clear function
            PWRTS_OFF,_                                             ' Power-up Timer disabled
            LPBOREN_OFF,_                                           ' Low-Power BOR disabled
            BOREN_ON,_                                              ' Brown-out resetEnabled, SBOREN bit is ignored
            BORV_LO,_                                               ' Brown-out Reset Voltage (VBOR) set to 2.45V
            ZCDDIS_OFF,_                                            ' Zero-cross detect circuit is disabled at POR
            PPS1WAY_OFF,_                                           ' The PPSLOCK bit can be cleared and set multiple times in software
            STVREN_ON                                               ' Stack Overflow or Underflow will cause a reset

    Config3 WDTCPS_WDTCPS_31,_                                      ' WDT Period Divider ratio 1:65536. Software control of WDTPS
            WDTE_OFF,_                                              ' WDT Disabled, SWDTEN is ignored
            WDTCWS_WDTCWS_7,_                                       ' WDT window always open (100%). Software control
            WDTCCS_SC                                               ' WDT input clock is Software Control

    Config4 BBSIZE_BB512,_                                          ' Boot Block Size 512 words boot block size
            BBEN_OFF,_                                              ' Boot Block disabled
            SAFEN_OFF,_                                             ' SAF disabled
            WRTAPP_OFF,_                                            ' Application Block not write protected
            WRTB_OFF,_                                              ' Boot Block not write protected
            WRTC_OFF,_                                              ' Configuration Register not write protected
            WRTD_OFF,_                                              ' Data EEPROM not write protected
            WRTSAF_OFF,_                                            ' Storage Area Flash not write protected
            LVP_OFF                                                 ' High Voltage on MCLR/Vpp must be used for programming

    Config5 CP_OFF                                                  ' UserNVM Program memory code protection disabled

midali

And  4MHZ , 10 bit , generated with AI :

Device = 16F18425                                       ' Tell the compiler what device to compile for
    Declare Xtal = 4                                        ' Tell the compiler what frequency the device is operating at (in MHz)
    Declare Auto_Heap_Strings = On                          ' Make all Strings "Heap" types, so they always get placed after standard variables
    Declare Auto_Variable_Bank_Cross = On                   ' Make sure all multi-byte variables remain within a single RAM bank (for extra efficiency)
'
' Setup USART1 for 4MHz (baud rate adjusted)
'
    Declare Hserial_Baud = 2400                             ' Lower baud rate for 4MHz clock
    Declare HRSOut1_Pin  = PORTC.4                          ' Tell the compiler to setup pin PORTC.4 for USART1 Tx
    Declare HRSIn1_Pin   = PORTC.5                          ' Tell the compiler to setup pin PORTC.5 for USART1 Rx
'
' Create global variable here
'
    Dim wDuty10Bit As Word
    Dim bPercent As Byte

'------------------------------------------------------------------------------------------
' The main program starts here
' Alter PWM duty values with 10-bit resolution (0-1023)
'
Main:
    Setup()                                                         ' Setup the program and any peripherals

    HRSOutLn "4MHz 10-bit PWM Demo"
    HRSOutLn "Sweeping 0-1023..."
    HRSOutLn ""
   
    Do
        ' Sweep from 0 to 1023 (10-bit resolution)
        wDuty10Bit = 0
        While wDuty10Bit <= 1023
            PWM1_Duty10Bit(wDuty10Bit)                             ' Set PWM1 duty (0-1023)
            PWM6_Duty10Bit(wDuty10Bit)                             ' Set PWM6 duty (0-1023)
           
            ' Calculate percentage for display
            bPercent = (wDuty10Bit * 100) / 1024
           
            ' Send duty value to serial (less frequent)
            If (wDuty10Bit & $3F) = 0 Then                         ' Display every 64 steps
                HRSOut "Duty: ", Dec wDuty10Bit, " (",
                       Dec bPercent, "%)"
                HRSOutLn ""
            EndIf
           
            DelayMS 50                                              ' Longer delay for 4MHz
            wDuty10Bit = wDuty10Bit + 4                            ' Increment by 4
        Wend
       
        HRSOutLn "Max reached, sweeping down..."
       
        ' Sweep back from 1023 to 0
        wDuty10Bit = 1023
        While wDuty10Bit >= 0
            PWM1_Duty10Bit(wDuty10Bit)
            PWM6_Duty10Bit(wDuty10Bit)
            DelayMS 50
            wDuty10Bit = wDuty10Bit - 4
        Wend
       
        HRSOutLn "Min reached, sweeping up..."
        HRSOutLn ""
    Loop

'------------------------------------------------------------------------------------------
' Setup the program and any peripherals
' Input     : None
' Outout    : None
' Notes     : None
'
Proc Setup()
    Osc_4MHz()                                                      ' Initialise the oscillator to operate at 4MHz
    PPS_Unlock()
    RC0PPS = PPS_Fn_CCP1                                            ' PORTC.0 is CCP1 Out
    RC1PPS = PPS_Fn_PWM6OUT                                         ' PORTC.1 is PWM6 Out
    Timer2_Init()                                                   ' Setup Timer2 to operate as the PWM clock
    PWM1_Init()                                                     ' Setup CCP1 to operate as PWM with 10-bit resolution
    PWM6_Init()                                                     ' Setup the PWM6 peripheral with 10-bit resolution
    PinOutput PORTC.0
    PinOutput PORTC.1
   
    DelayMS 100                                                     ' Allow time for serial to initialize
EndProc

'------------------------------------------------------------------------------------------
' Setup Timer2 for 10-bit PWM resolution at 4MHz
' Input     : None
' Outout    : None
' Notes     : Timer period optimized for 4MHz
'
Proc Timer2_Init()
    T2CLKCON = $01                                                  ' T2CS is FOSC/4 = 1MHz
    T2HLT = $00
    T2RST = $00
    T2PR = $FF                                                      ' Period = 256
    T2TMR = $00
    PIR4bits_TMR2IF = 0
    T2CON = %10010000                                               ' Prescaler is 1:4, Timer2 on
EndProc

'------------------------------------------------------------------------------------------
' Setup CCP1 to operate as PWM with 10-bit resolution
' Input     : None
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM1_Init()
    CCP1CON = %10001100                                             ' Mode is PWM. CCP1 enabled. FMT is right aligned (10-bit)
    CCPR1H = $00                                                    ' Start with 0% duty
    CCPR1L = $00
    CCPTMRS0.0 = 1                                                  ' \ Select Timer2 as the PWM source
    CCPTMRS0.1 = 0                                                  ' /
EndProc

'------------------------------------------------------------------------------------------
' Write the 10-bit duty value to PWM1
' Input     : pDuty holds the duty value (0-1023)
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM1_Duty10Bit(pDuty As Word)
    Dim bTempH As Byte
    Dim bTempL As Byte
   
    ' Ensure value is within 10-bit range
    If pDuty > 1023 Then pDuty = 1023
   
    ' Extract bits 9:2 for CCPR1H
    bTempH = pDuty.Byte1
    bTempH = bTempH << 2
    bTempH = bTempH | (pDuty.Byte0 >> 6)
   
    ' Extract bits 1:0 for CCPR1L (bits 7:6)
    bTempL = pDuty.Byte0 << 6
   
    CCPR1H = bTempH
    CCPR1L = bTempL
EndProc

'------------------------------------------------------------------------------------------
' Setup PWM6 for 10-bit resolution
' Input     : None
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM6_Init()
    PWM6CON = %10000000                                             ' PWM6POL is active high. PWM6 is enabled
    PWM6DCH = $00                                                   ' Start with 0% duty
    PWM6DCL = $00
    CCPTMRS1.2 = 1                                                  ' Select Timer2 as the PWM source
    CCPTMRS1.3 = 0
EndProc

'------------------------------------------------------------------------------------------
' Write the 10-bit duty value to PWM6
' Input     : pDuty holds the duty value (0-1023)
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc PWM6_Duty10Bit(pDuty As Word)
    Dim bTempH As Byte
    Dim bTempL As Byte
   
    ' Ensure value is within 10-bit range
    If pDuty > 1023 Then pDuty = 1023
   
    ' Extract bits 9:2 for PWM6DCH
    bTempH = pDuty.Byte1
    bTempH = bTempH << 2
    bTempH = bTempH | (pDuty.Byte0 >> 6)
   
    ' Extract bits 1:0 for PWM6DCL (bits 7:6)
    bTempL = pDuty.Byte0 << 6
   
    PWM6DCH = bTempH
    PWM6DCL = bTempL
EndProc

'------------------------------------------------------------------------------------------
' Initialise the device to use its internal oscillator at 4MHz
' Input     : None
' Outout    : None
' Notes     : For a PIC16F18425 device
'
Proc Osc_4MHz()
    OSCCON1 = %01100000
    OSCCON3 = %00000000
    OSCEN =   %00000000
    OSCFRQ =  %00000001                                             ' HFFRQ is 4MHz
    OSCTUNE = %00000000
    DelayMS 10                                                      ' Allow oscillator to stabilize
EndProc

'------------------------------------------------------------------------------------------
' Setup the config fuses for an internal oscillator on a PIC16F18425 device
' The OSC pins are general purpose I/O lines
'
    Config1 FEXTOSC_OFF,_                                           ' External Oscillator not enabled
            RSTOSC_HFINT32,_                                        ' Power-up default is HFINTOSC at 32MHz
            CLKOUTEN_OFF,_                                          ' CLKOUT function is disabled
            CSWEN_ON,_                                              ' Writing to NOSC and NDIV is allowed
            FCMEN_ON                                                ' Fail-Safe Clock Monitor  enabled

    Config2 MCLRE_ON,_                                              ' MCLR pin is Master Clear function
            PWRTS_OFF,_                                             ' Power-up Timer disabled
            LPBOREN_OFF,_                                           ' Low-Power BOR disabled
            BOREN_ON,_                                              ' Brown-out resetEnabled, SBOREN bit is ignored
            BORV_LO,_                                               ' Brown-out Reset Voltage (VBOR) set to 2.45V
            ZCDDIS_OFF,_                                            ' Zero-cross detect circuit is disabled at POR
            PPS1WAY_OFF,_                                           ' The PPSLOCK bit can be cleared and set multiple times in software
            STVREN_ON                                               ' Stack Overflow or Underflow will cause a reset

    Config3 WDTCPS_WDTCPS_31,_                                      ' WDT Period Divider ratio 1:65536. Software control of WDTPS
            WDTE_OFF,_                                              ' WDT Disabled, SWDTEN is ignored
            WDTCWS_WDTCWS_7,_                                       ' WDT window always open (100%). Software control
            WDTCCS_SC                                               ' WDT input clock is Software Control

    Config4 BBSIZE_BB512,_                                          ' Boot Block Size 512 words boot block size
            BBEN_OFF,_                                              ' Boot Block disabled
            SAFEN_OFF,_                                             ' SAF disabled
            WRTAPP_OFF,_                                            ' Application Block not write protected
            WRTB_OFF,_                                              ' Boot Block not write protected
            WRTC_OFF,_                                              ' Configuration Register not write protected
            WRTD_OFF,_                                              ' Data EEPROM not write protected
            WRTSAF_OFF,_                                            ' Storage Area Flash not write protected
            LVP_OFF                                                 ' High Voltage on MCLR/Vpp must be used for programming

    Config5 CP_OFF                                                  ' UserNVM Program memory code protection disabled

charliecoutas

You say "..generated with AI". That looks very, very much like our Les's coding.

Charlie

midali

It's Les code but modified to 10 bit/32MHz and 10bit/4MHz

charliecoutas

I was worried that "AI" had taken Les's code and reproduced it verbatim.

Regards
Charlie

joesaliba

Thanks for the hints,

The AI generated needed a little tweaking to work. First, the T2CON prescaler 1:1 is wrong.

I came up with the following and it seems to be working: -

Proc Timer2_Init()
    T2CLKCON = $01                      ' T2CS is FOSC/4
    T2HLT = $00
    T2RST = $00
    t2pr = $FF
    'T2PR = $18                         ' Les original
    T2TMR = $00
    PIR4bits_TMR2IF = 0
   ' T2CON = %11010000                   ' Prescaler is 1:32. Postscaler is 1:1; Timer 2 ON; Les original
    t2con = %10000000                   ' Prescaler 1:1; Timer 2 ON
 EndProc


and a small change here: -

' Write the 10-bit duty value to PWM6
 ' Input     : pDuty holds the duty value (0-1023)
 ' Outout    : None
 ' Notes     : For a PIC16F18425 device
 '
 Proc PWM6_Duty10Bit(pDuty As Word)
    PWM6DCH = pDuty >> 2              ' High 8 bits
    PWM6DCL = pDuty & %00000011 << 6  ' Low 2 bits shifted into bits 7:6
 EndProc

Seems to be working ok.