is it possible run HPWM module 10hz with 8MHZ osc?(18F25K22)

Started by Maxi, Mar 10, 2021, 06:55 AM

Previous topic - Next topic



No, to get 10Hz you would need to slow the system clock right down to 2MHz.

The only option that I can think of is to write your own using timer interrupts.


There is a sample program installed with the compilers to do an interrupt driven slow, software based, PWM, in the "New Samples" directory. It is named: "Slow_PWM_Interrupt_Driven.bas"

It is written for a PIC18F25K20 device, but all it needs for a different device is the Timer configured. It uses a Special Event interrupt for accurate timings. i.e. A Timer value matching a CCP peripheral's fixed value causes the interrupt to happen.

The sample programs are always installed here: "C:\Users\User Name\PDS\Samples\"


To use Les' sample code on the 18F25K22 after the line CCP2CON = %00001011 add a new line



Quote from: See_Mos on Mar 12, 2021, 01:50 PMTo use Les' sample code on the 18F25K22 after the line CCP2CON = %00001011 add a new line

just after this line, may I use les` code over 18F25K22?
ofcourse I change too


I tested it using the .INC file below. Save it as something like "18F25K22" in the same folder as your project.

In the example code change the Include "" to the same name as the saved file

'*  Name    : UNTITLED.BAS                                      *
'*  Author  : [select VIEW...EDITOR OPTIONS]                    *
'*  Notice  : Copyright (c) 2021 [select VIEW...EDITOR OPTIONS] *
'*          : All Rights Reserved                               *
'*  Date    : 12/03/2021                                        *
'*  Version : 1.0                                               *
'*  Notes   : for PIC18F25K22 with 8MHz internal oscillator     *
'*          :                                                   *

Device = 18F25K22

Xtal 8
Symbol True = 1
Symbol False = 0
All_Digital = True
Declare Watchdog = off   
' if using INTOSC don't put any delays before OSCON is set !
OSCCON = %01101100     ' 8MHz internal oscillator
;**** Added by Fuse Configurator ****
; Use the Fuse Configurator plug-in to change these settings
  FOSC = INTIO67 ; A6 and A7 available for I/O
  PRICLKEN = On ;Primary clock enabled
  FCMEN = OFF ;Fail-Safe Clock Monitor disabled
  IESO = OFF ;Oscillator Switchover mode disabled
  PWRTEN = OFF ;Power up timer disabled
  BOREN = SBORDIS ;Brown-out Reset enabled in hardware only (SBOREN is disabled)
  BORV = 190 ;VBOR set to 1.90 V nominal
  WDTEN = Off ;WDT is ON
  WDTPS = 32768 ;1:32768
  CCP2MX = PORTC1 ;CCP2 input/output is multiplexed with RC1
  PBADEN = OFF ;PORTB<5:0> pins are configured as digital I/O on Reset
  CCP3MX = PORTB5 ;P3A/CCP3 input/output is multiplexed with RB5
  HFOFST = On ;HFINTOSC output and ready status are not delayed by the oscillator stable status
  T3CMX = PORTC0 ;T3CKI is on RC0
  P2BMX = PORTB5 ;P2B is on RB5
  MCLRE = EXTMCLR ;MCLR pin enabled, RE3 input pin disabled
  STVREN = On ;Stack full/underflow will cause Reset
  LVP = OFF ;Single-Supply ICSP disabled
  XINST = OFF ;Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
  Debug = OFF ;Disabled
  Cp0 = OFF ;Block 0 (000800-001FFFh) not code-protected
  CP1 = OFF ;Block 1 (002000-003FFFh) not code-protected
  CP2 = OFF ;Block 2 (004000-005FFFh) not code-protected
  CP3 = OFF ;Block 3 (006000-007FFFh) not code-protected
  CPB = OFF ;Boot block (000000-0007FFh) not code-protected
  CPD = OFF ;Data EEPROM not code-protected
  WRT0 = OFF ;Block 0 (000800-001FFFh) not write-protected
  WRT1 = OFF ;Block 1 (002000-003FFFh) not write-protected
  WRT2 = OFF ;Block 2 (004000-005FFFh) not write-protected
  WRT3 = OFF ;Block 3 (006000-007FFFh) not write-protected
  WRTC = OFF ;Configuration registers (300000-3000FFh) not write-protected
  WRTB = OFF ;Boot Block (000000-0007FFh) not write-protected
  WRTD = OFF ;Data EEPROM not write-protected
  EBTR0 = OFF ;Block 0 (000800-001FFFh) not protected from table reads executed in other blocks
  EBTR1 = OFF ;Block 1 (002000-003FFFh) not protected from table reads executed in other blocks
  EBTR2 = OFF ;Block 2 (004000-005FFFh) not protected from table reads executed in other blocks
  EBTR3 = OFF ;Block 3 (006000-007FFFh) not protected from table reads executed in other blocks
  EBTRB = OFF ;Boot Block (000000-0007FFh) not protected from table reads executed in other blocks

' **** End of Fuse Configurator Settings ****


This is a simple code that I did before Les reminded me of the one in the sample folder.  It is not as versatile as the example. It uses the same .INC file as above.

' Simple slow PWM using timer interrupts

' multiply the output frequency by the number of steps (ticks) required.
' 10Hz * 1000 = interrupt frequency of 10KHz
' 15Hz * 255 = interrupt frequency of 3825 Hz
' need to calculate prescaler and preload values instead of using PIC Multi_Calc
' or Mikroelektronika calculator

Include ""
Dim T1 As Word                          ' maximum number of ticks
Dim T2 As Word                          ' high time in ticks
Dim T3 As Word                          ' ticks counter

Dim Timer1_Reg As TMR1L.Word             ' Alias to TMR1H and TMR1L
Dim Timer1_Val As Word

Symbol TMR1IF = PIR1.0                  ' TMR1 Overflow Interrupt Flag bit

On_Hardware_Interrupt GoTo Hardware_Int
GoTo Start

    Context Save
      If TMR1IF  = True Then
        Timer1_Reg = Timer1_Reg + Timer1_Val    ' Reload timer 1 
        TMR1IF = 0
        Inc T3                                  ' ticks counter
        If T3 >= T1 Then T3 = 0                 ' zero if count > 1000
        If T3 < T2 Then                         ' high time
            LATB.1 = 1                          ' PWM Output pin
        Else                                    ' low time
            LATB.1 = 0                         
        End If

   PIR1.0 = 0                                   ' Clear the interrupt flag
   Context Restore
'--------------------------------- End of interrupt code  ----------------------

    T1 = 255                                    ' maximum number of steps
    T2 = 127                                    ' high time test values
    T3 = 0                                      ' zero ticks counter
'--------------------------------- interrupt setup ----------------------------

    Timer1_Val = $FDF5                       ' value for 255 steps at 15Hz
'    Timer1_Val = $FF38                       ' value for 10KHz, output = 10Hz
'    Timer1_Val = $FF7B                       ' value for 15KHz, output = 15Hz
'    Timer1_Val = $FF9C                       ' value for 20KHz, output = 20Hz

    Timer1_Reg = Timer1_Val

    IPR1  = 128                             ' set interrupt priorities
    IPR2  = 0
    PIR1.0 = 0                              ' Clear Timer 1 interrupt flag
    PIE1.0 = 1                              ' Enable timer 1 interrupt
    T1CON = 1                               ' Turn on Timer 1
    INTCON =  $C0                           ' Enable interrupts
'--------------------------------- End of interrupt setup ----------------------

    TRISB = 0
    While 1 = 1 : Wend


Thank you thank you its works, Im happy

a little problem but not importand
when freq value set to 10hz at the 18F25K20 I read out 9-10hz (proteus)
but set freq 10hz 18F25K22 out is ~33 hz (proteus)


T1 is the number of steps.  Multiply T1 times the final frequency then use PIC Multi_Calc or Mikroelektronika timer calculator to find the value for Timer1_Val

For 255 steps at 10Hz T1 = 255, Timer1_Val = $FCF0

T2 has to be less than T1