Log in

View Full Version : My TMR1_INT Blinky is not blinking



Demon
- 28th September 2024, 02:40
16F18877

Mostly taken from:
https://dt.picbasic.co.uk/INT14/TMR1INT



#CONFIG
__config _CONFIG1, _FEXTOSC_OFF & _RSTOSC_HFINT32 & _CLKOUTEN_OFF & _CSWEN_OFF & _FCMEN_ON
__config _CONFIG2, _MCLRE_ON & _PWRTE_OFF & _LPBOREN_OFF & _BOREN_ON & _BORV_LO & _ZCD_OFF & _PPS1WAY_OFF & _STVREN_ON & _DEBUG_OFF
__config _CONFIG3, _WDTCPS_WDTCPS_11 & _WDTE_OFF & _WDTCWS_WDTCWS_7 & _WDTCCS_LFINTOSC
__config _CONFIG4, _WRT_OFF & _SCANE_available & _LVP_OFF
__config _CONFIG5, _CP_OFF & _CPD_OFF
#ENDCONFIG

include "I:\Project_v2\PBP\PBP_Includes\DT_INTS-14_16F18877.bas"
include "I:\Project_v2\PBP\PBP_Includes\ReEnterPBP.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _ToggleLED1, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

DEFINE OSC 32
ANSELA = %00000000
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00000000
ANSELE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %00000000
TRISD = %00000000
TRISE = %00000000

T1CON = $31 ; Prescaler=8, TMR1ON
@ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts

Main:
toggle LatB.3
PAUSE 1
GOTO Main

ToggleLED1:
toggle LatB.4
@ INT_RETURN



My custom DT_INTS-14_16F18877.bas:


'************************************************* **************************
'* Name : DT_INTS-14_16F18877.bas *
'* Author : Darrel Taylor (modified by Demon) *
'* Version : 1.15 (8/29/2024) *
'* Date : OCT 13, 2009 *
'************************************************* **************************
'* REV 1.15 Customized for 16F1885xx-7x (IOC, USART-RX, CCPx) *
'* REV 1.10 Fixes Duplicate label error when Handlers cross page boundary *
'* Fixes error with 16F1's and MPLAB 8.53 (high) *
'* REV 1.00 Completely re-written, with optimization and F1 chips in mind *
'* REV 0.93 Fixed CMIF and EEIF problem with older PIC's *
'* that have the Flags in PIR1 instead of PIR2 *
'* Rev 0.92 solves a "Missed Interrupt" and *
'* banking switching problem *
'************************************************* **************************
DEFINE DT_INTS_VERSION 110
DEFINE INTHAND INT_ENTRY

;-- Place a copy of these variables in your Main program -------------------
;-- The compiler will tell you which lines to un-comment --
;-- Do Not un-comment these lines --
;---------------------------------------------------------------------------
;wsave VAR BYTE $20 SYSTEM ' location for W if in bank0
;wsave VAR BYTE $70 SYSTEM ' alternate save location for W
' if using $70, comment wsave1-3

' --- IF any of these three lines cause an error ?? ------------------------
' Comment them out to fix the problem ----
' -- Which variables are needed, depends on the Chip you are using --
;wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
;wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
;wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3
' --------------------------------------------------------------------------

ssave VAR BYTE BANK0 SYSTEM ' location for STATUS register
psave VAR BYTE BANK0 SYSTEM ' location for PCLATH register
fsave VAR BYTE BANK0 SYSTEM ' location for FSR register
RetAddr VAR WORD BANK0
INT_Bits VAR BYTE BANK0
Serviced VAR INT_Bits.0
Vars_Saved VAR INT_Bits.1

GIE VAR INTCON.7
PEIE VAR INTCON.6

ASM
ifdef PM_USED ; verify MPASM is the assembler
"ERROR: DT_INTS does not support the PM assembler, USE MPASM"
endif

;---------------------------------------------------------------------------
ifdef ReEnterUsed
ifdef ReEnterVersion
if (ReEnterVersion < 34)
error "Wrong version of ReEnterPBP.bas - Ver 3.4 or higher required
endif
else
error "Wrong version of ReEnterPBP.bas - Ver 3.4 or higher required
endif
endif

;---------------------------------------------------------------------------
if (BANK0_END == 0x7F)
ifdef BANK1_END
if (BANK1_END == 0xEF) ; doesn't find 12F683
variable ACCESSRAM = 1
else
variable ACCESSRAM = 0
endif
else
variable ACCESSRAM = 0
endif
else
variable ACCESSRAM = 0
endif

;---------------------------------------------------------------------------
#define OrChange Or change to wsave BYTE $70 SYSTEM
AddWsave macro B
if (B == 0)
if (ACCESSRAM == 1)
error " Add:" wsave VAR BYTE $70 SYSTEM
else
error " Add:" wsave VAR BYTE $20 SYSTEM
endif
endif
if (B == 1)
if (ACCESSRAM == 1)
error " Add:" wsave1 VAR BYTE $A0 SYSTEM, OrChange
else
error " Add:" wsave1 VAR BYTE $A0 SYSTEM
endif
endif
if (B == 2)
if (ACCESSRAM == 1)
error " Add:" wsave2 VAR BYTE $120 SYSTEM, OrChange
else
error " Add:" wsave2 VAR BYTE $120 SYSTEM
endif
endif
if (B == 3)
if (ACCESSRAM == 1)
error " Add:" wsave3 VAR BYTE $1A0 SYSTEM, OrChange
else
error " Add:" wsave3 VAR BYTE $1A0 SYSTEM
endif
endif
endm

#define WsaveE1(B) Chip has RAM in BANK#v(B), but wsave#v(B) was not found.
;#define WsaveE2(B) Uncomment wsave#v(B) in the DT_INTS-14.bas file.
#define WsaveCouldBe This chip has access RAM at $70

#define WsaveError(B) error WsaveE1(B)
ifndef FSR0L ; not a 16F1
ifndef wsave
; if (ACCESSRAM == 1)
error wsave variable not found,
AddWsave(0)
variable wsave = 0 ; stop further wsave errors
; else

; endif
else
if (wsave == 0x70)
if (ACCESSRAM == 0)
error This chip does not have AccessRAM at $70, change to wsave VAR BYTE $20 SYSTEM
endif
else
if (wsave != 0x20)
error wsave must be either $20 or $70
endif
endif
endif
ifdef BANK1_START
ifndef wsave1
ifdef wsave
if (wsave != 0x70)
WsaveError(1)
AddWsave(1)
endif
else
if (ACCESSRAM == 1)
if (wsave != 0x70)
WsaveCouldBe
endif
endif
endif
endif
endif
ifdef BANK2_START
ifndef wsave2
ifdef wsave
if (wsave != 0x70)
WsaveError(2)
AddWsave(2)
endif
endif
endif
endif
ifdef BANK3_START
ifndef wsave3
ifdef wsave
if (wsave != 0x70)
WsaveError(3)
AddWsave(3)
endif
endif
endif
endif


endif
ENDASM

ASM
asm = 0
Asm = 0
ASM = 0
pbp = 1
Pbp = 1
PBP = 1
yes = 1
Yes = 1
YES = 1
no = 0
No = 0
NO = 0


;---[Original DEFINES]------------------------------------------------------
#define ALL_INT INTCON,GIE, INTCON,GIE ;-- Global Interrupts *
; #define IOC_INT INTCON,IOCIF, INTCON,IOCIE ;-- Int On Change
; #define RX_INT PIR1,RCIF, PIE1,RCIE ;-- USART Receive
; #define CCP1_INT PIR1,CCP1IF, PIE1,CCP1IE ;-- CCP1
; #define CCP2_INT PIR2,CCP2IF, PIE2,CCP2IE ;-- CCP2
; #define CCP3_INT PIR3,CCP3IF, PIE3,CCP3IE ;-- CCP3
; #define CCP4_INT PIR3,CCP4IF, PIE3,CCP4IE ;-- CCP4
; #define CCP5_INT PIR3,CCP5IF, PIE3,CCP5IE ;-- CCP5
#define IOC_INT PIR0,IOCIF, PIE0,IOCIE ;-- Int On Change
#define TMR1_INT PIR4,TMR1IF, PIE4,TMR1IE ;-- Timer1
#define RX_INT PIR3,RCIF, PIE3,RCIE ;-- USART Receive
#define CCP1_INT PIR6,CCP1IF, PIE6,CCP1IE ;-- CCP1
#define CCP2_INT PIR6,CCP2IF, PIE6,CCP2IE ;-- CCP2
#define CCP3_INT PIR6,CCP3IF, PIE6,CCP3IE ;-- CCP3
#define CCP4_INT PIR6,CCP4IF, PIE6,CCP4IE ;-- CCP4
#define CCP5_INT PIR6,CCP5IF, PIE6,CCP5IE ;-- CCP5
ENDASM


ASM
;---[Returns the Address of a Label as a Word]------------------------------
GetAddress macro Label, Wout
CHK?RP Wout
movlw low Label ; get low byte
movwf Wout
; movlw High Label ; get high byte MPLAB 8.53 killed high
movlw Label >> 8 ; get high byte
movwf Wout + 1
endm

;---[find correct bank for a BIT variable]----------------------------------
CHKRP?T macro reg, bit
CHK?RP reg
endm

;---[This creates the main Interrupt Service Routine (ISR)]-----------------
INT_CREATE macro
local OverCREATE
L?GOTO OverCREATE

INT_ENTRY
ifndef FSR0L
if (CODE_SIZE <= 2)
movwf wsave ; 1 copy W to wsave register
swapf STATUS,W ; 2 swap status reg to be saved into W
clrf STATUS ; 3 change to bank 0
movwf ssave ; 4 save status reg to a bank 0 register
movf PCLATH,W ; 5 move PCLATH reg to be saved into W reg
movwf psave ; 6 save PCLATH reg to a bank 0 register
endIF
movf FSR,W ; 7 move FSR reg to be saved into W reg
movwf fsave ; 8 save FSR reg to a bank 0 register
else
banksel 0 ; BANK 0 for F1 chips
endif
variable PREV_BANK = 0
MOVE?CT 0, _Vars_Saved

List_Start
ifdef LoopWhenServiced
MOVE?CT 0, _Serviced ; indicate nothing has been serviced
endif

INT_LIST ; Expand the users list of interrupt handlers
; INT_LIST macro must be defined in main program

ifdef LoopWhenServiced
BIT?GOTO 1, _Serviced, List_Start
endif

ifdef ReEnterUsed ; if ReEnterPBP.bas was included
CHKRP?T _Vars_Saved
btfss _Vars_Saved ; if PBP system vars have been saved
goto INT_EXIT
L?GOTO _RestorePBP ; Restore PBP system Vars
endif

INT_EXIT
variable PREV_BANK = 0
ifndef FSR0L ; if chip is not an F1 - restore context
clrf STATUS ; BANK 0
movf fsave,W ; Restore the FSR reg
movwf FSR
movf psave,w ; Restore the PCLATH reg
movwf PCLATH
swapf ssave,w ; Restore the STATUS reg
movwf STATUS
swapf wsave,f
swapf wsave,w ; Restore W reg
endif
retfie ; Exit the interrupt routine
;-----------------------------
LABEL?L OverCREATE
bsf INTCON, 6 ; Enable Peripheral interrupts
bsf INTCON, 7 ; Enable Global interrupts
endm

ENDASM

ASM
;---[Add an Interrupt Source to the user's list of INT Handlers]------------
#INT_HANDLER macro FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
list
local AfterSave, AfterUserRoutine, NoInt
ifdef FlagBit
CHK?RP EnableReg
btfss EnableReg, EnableBit ; if the INT is enabled
goto NoInt
CHK?RP FlagReg
btfss FlagReg, FlagBit ; and the Flag set?
goto NoInt
ifdef LoopWhenServiced
MOVE?CT 1, _Serviced
endif

if (Type == PBP) ; If INT handler is PBP
ifdef ReEnterUsed
btfsc _Vars_Saved
goto AfterSave
GetAddress AfterSave, _RetAddr
L?GOTO _SavePBP ; Save PBP system Vars
LABEL?L AfterSave
else
error ReEnterPBP must be INCLUDEd to use PBP type interrupts
endif
endif
GetAddress AfterUserRoutine, _RetAddr ; save return address
L?GOTO Label ; goto the users INT handler
LABEL?L AfterUserRoutine

if (Reset == YES)
CHK?RP FlagReg
bcf FlagReg, FlagBit ; reset flag (if specified)
endif
else
INT_ERROR "INT_Handler"
endif
NoInt
banksel 0
PREV_BANK = 0
endm
;-----------------------------------
#define INT_HANDLER(FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset) #INT_HANDLER FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
ifndef INT_Handler
#define INT_Handler(FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset) #INT_HANDLER FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
#define int_handler(FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset) #INT_HANDLER FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
#define Int_Handler(FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset) #INT_HANDLER FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
#define Int_handler(FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset) #INT_HANDLER FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
#define int_Handler(FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset) #INT_HANDLER FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
endif

;---[Returns from a "goto" subroutine]--------(RetAddr must be set first)---
#INT_RETURN macro
CHK?RP _RetAddr
movf _RetAddr + 1, W ; Set PCLATH with top byte of return address
movwf PCLATH
movf _RetAddr, W ; Go back to where we were
movwf PCL
endm
;_____________________________
#define INT_RETURN #INT_RETURN
ifndef INT_Return
#define INT_Return #INT_RETURN
#define int_return #INT_RETURN
#define Int_Return #INT_RETURN
#define Int_return #INT_RETURN
#define int_Return #INT_RETURN
endif

;----[Display not found error]----------------------------------------------
INT_ERROR macro From
error From - Interrupt Flag ( FlagReg,FlagBit ) not found.
endm

;---[Enable an interrupt source]--------------------------------------------
ifndef INT_ENABLECLEARFIRST
#define INT_ENABLECLEARFIRST 1 ; default to Clear First
endif ; use DEFINE INT_ENABLECLEARFIRST 0 to NOT clear First

#INT_ENABLE macro FlagReg, FlagBit, EnableReg, EnableBit
ifdef FlagBit
ifdef INT_ENABLECLEARFIRST
if (INT_ENABLECLEARFIRST == 1) ; if specified
MOVE?CT 0, FlagReg, FlagBit ; clear the flag first
endif
endif
MOVE?CT 1, EnableReg, EnableBit ; enable the INT source
else
INT_ERROR "INT_ENABLE"
endif
endm
;_____________________________
#define INT_ENABLE(FlagReg, FlagBit, EnableReg, EnableBit) #INT_ENABLE FlagReg, FlagBit, EnableReg, EnableBit
ifndef INT_Enable
#define INT_Enable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_ENABLE FlagReg, FlagBit, EnableReg, EnableBit
#define int_enable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_ENABLE FlagReg, FlagBit, EnableReg, EnableBit
#define Int_Enable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_ENABLE FlagReg, FlagBit, EnableReg, EnableBit
#define Int_enable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_ENABLE FlagReg, FlagBit, EnableReg, EnableBit
#define int_Enable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_ENABLE FlagReg, FlagBit, EnableReg, EnableBit
endif

;---[Disable an interrupt source]-------------------------------------------
#INT_DISABLE macro FlagReg, FlagBit, EnableReg, EnableBit
ifdef FlagBit
MOVE?CT 0, EnableReg, EnableBit ; disable the INT source
else
INT_ERROR "INT_DISABLE"
endif
endm
;_____________________________
#define INT_DISABLE(FlagReg, FlagBit, EnableReg, EnableBit) #INT_DISABLE FlagReg, FlagBit, EnableReg, EnableBit
ifndef INT_Disable
#define INT_Disable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_DISABLE FlagReg, FlagBit, EnableReg, EnableBit
#define int_disable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_DISABLE FlagReg, FlagBit, EnableReg, EnableBit
#define Int_Disable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_DISABLE FlagReg, FlagBit, EnableReg, EnableBit
#define Int_disable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_DISABLE FlagReg, FlagBit, EnableReg, EnableBit
#define int_Disable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_DISABLE FlagReg, FlagBit, EnableReg, EnableBit
endif

;---[Clear an interrupt Flag]-----------------------------------------------
#INT_CLEAR macro FlagReg, FlagBit, EnableReg, EnableBit
ifdef FlagBit
MOVE?CT 0, FlagReg, FlagBit ; clear the flag
else
INT_ERROR "INT_CLEAR"
endif
endm
;_____________________________
#define INT_CLEAR(FlagReg, FlagBit, EnableReg, EnableBit) #INT_CLEAR FlagReg, FlagBit, EnableReg, EnableBit
ifndef INT_Clear
#define INT_Clear(FlagReg, FlagBit, EnableReg, EnableBit) #INT_CLEAR FlagReg, FlagBit, EnableReg, EnableBit
#define int_clear(FlagReg, FlagBit, EnableReg, EnableBit) #INT_CLEAR FlagReg, FlagBit, EnableReg, EnableBit
#define Int_Clear(FlagReg, FlagBit, EnableReg, EnableBit) #INT_CLEAR FlagReg, FlagBit, EnableReg, EnableBit
#define Int_clear(FlagReg, FlagBit, EnableReg, EnableBit) #INT_CLEAR FlagReg, FlagBit, EnableReg, EnableBit
#define int_Clear(FlagReg, FlagBit, EnableReg, EnableBit) #INT_CLEAR FlagReg, FlagBit, EnableReg, EnableBit
endif
ENDASM



I end up with only the heartbeat pulse on B3.

Does ENABLE only sets it up, or does it start the timer?

richard
- 28th September 2024, 05:52
there are a number of problems
1, toggle LatB.4 is a no no. toggle or any other pbp high level command will not function correctly with LATx regs and can only be safely used with PORTx regs
2. you have not selected a clock source for timer1 see T1CLK in data sheet
3. dt ints will not enable intcon PEIE you need to

amgen
- 28th September 2024, 15:42
this is PBP 2.6 and 20MHZ clock, and 10 times a second tmr1 interrupt....... on interrupt routine, need to, 1) stop timer... 2) reload tmr1 counters for timing period... 3) do something ( I set a flag so next loop in basic can see if something happened) .... turn tmr1 back on and leave int... of course you have to adjust for your stuff and PBP3


include "D:\All_PIC\Project_18f2525 RTOS\A_18F2525_Setup.pbp" 'f2525 setup stuff
include "D:\All_PIC\Project_18f2525 RTOS\A_TX_RX.pbp"
output portc.2 ' LED on pin 13 of F2525
T1CON = $31 ' Prescaler = 8, TMR1ON
BH=11 : BL=190 '...MAIN INT TIMING PRELOAD FOR TIMER1 INT = 10X/SEC
L0=0:B3=10

'''' interrupts for T1 timeout (main timing loop), etc''''''''''''''''
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _T1int, PBP, yes
INT_Handler RX_INT, _RCint, PBP, yes
INT_Handler TX_INT, _TRint, PBP, no
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

@ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts
@ INT_DISABLE RX_INT ; enable RX interrupts
@ INT_DISABLE TX_INT ;disable tx int
''''______________________________________________ _________'''


''''''''''''''''''''''-----END OF MAIN LOOP-------'''''''''''''''

''''''''''''''-----INTERRUPTS HERE----------''''''''''''''''''

'''''''T1 main''Interrupt Routine''''''''''''''''''
T1int:
T1CON.0=0
TMR1h=bh :TMR1l=bl 'load tmr1
FLG1 =0
T1CON.0=1
@ INT_RETURN ;RESET FLAG FOR BASIC LOOP

'''-------------RCV INT ROUTINE----------------''''
RCint:
RCX=RCREG
'@ bcf RCSTA,4
'@ bsf RCSTA,4
'''@ CLRF CREN ;RESET RCV overrun
'''@ SETF CREN

Demon
- 28th September 2024, 18:17
Thanks both!

Demon
- 28th September 2024, 20:28
I get 66.18msec intervals. I'd like to bring that down to 65msec.

MultiCalc says 536 decimal pre-load gives 65mSec (32MHz, 16bits, 1:8)

How do you store 536 in TMR1H and TMR1L?

I manually get this in binary for 536:
00000010 00011000

In decimal, that gives 2 24.


#CONFIG
__config _CONFIG1, _FEXTOSC_OFF & _RSTOSC_HFINT32 & _CLKOUTEN_OFF & _CSWEN_OFF & _FCMEN_ON
__config _CONFIG2, _MCLRE_ON & _PWRTE_OFF & _LPBOREN_OFF & _BOREN_ON & _BORV_LO & _ZCD_OFF & _PPS1WAY_OFF & _STVREN_ON & _DEBUG_OFF
__config _CONFIG3, _WDTCPS_WDTCPS_11 & _WDTE_OFF & _WDTCWS_WDTCWS_7 & _WDTCCS_LFINTOSC
__config _CONFIG4, _WRT_OFF & _SCANE_available & _LVP_OFF
__config _CONFIG5, _CP_OFF & _CPD_OFF
#ENDCONFIG

include "I:\Project_v2\PBP\PBP_Includes\DT_INTS-14_16F18877.bas"
include "I:\Project_v2\PBP\PBP_Includes\ReEnterPBP.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _ToggleLED1, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

DEFINE OSC 32
ANSELA = %00000000
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00000000
ANSELE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %00000000
TRISD = %00000000
TRISE = %00000000

T1CON = %00110001 ' 1:8 Prescale, Enables Timer1
' bit 7-6 Unimplemented: Read as ‘0’
' bit 5-4 CKPS<1:0>: Timer1 Input Clock Prescale Select bits
' ----> 11 = 1:8 Prescale value
' 10 = 1:4 Prescale value
' 01 = 1:2 Prescale value
' 00 = 1:1 Prescale value
' bit 3 Unimplemented: Read as ‘0’
' bit 2 SYNC: Timer1 Synchronization Control bit
' When TMR1CLK = FOSC or FOSC/4
' This bit is ignored. The timer uses the internal clock and no
' additional synchronization is performed.
' When TMR1CS<1:0> = (any setting other than FOSC or FOSC/4)
' 1 = Do not synchronize external clock input
' 0 = Synchronized external clock input with system clock
' bit 1 RD16: Timer1 On bit
' 1 = All 16 bits of Timer1 can be read simultaneously (TMR1H is buffered)
' 0 = 16-bit reads of Timer1 are disabled (TMR1H is not buffered)
' bit 0 ON: Timer1 On bit
' ----> 1 = Enables Timer1
' 0 = Stops Timer1 and clears Timer1 gate flip-flop

T1CLK = %00000001 ' FOSC/4 Timer1 Clock
' bit 7-4 Unimplemented: Read as ‘0’
' bit 3-0 TxCS<3:0>: Timer1/3/5 Clock Select bits
' 1111 = LC4_out
' 1110 = LC3_out
' 1101 = LC2_out
' 1100 = LC1_out
' 1011 = TMR5 overflow output(3)
' 1010 = TMR3 overflow output(2)
' 1001 = TMR1 overflow output(1)
' 1000 = TMR0 overflow output
' 0111 = CLKR output clock
' 0110 = SOSC
' 0101 = MFINTOSC ' 1.05msec @ 32MHz with no preload
' 0100 = LFINTOSC ' n/a
' 0011 = HFINTOSC ' 16.56msec @ 32MHz with no preload
' 0010 = FOSC ' 16.54msec @ 32MHz with no preload
' ----> 0001 = FOSC/4 ' 66.18msec @ 32MHz with no preload
' 0000 = TxCKIPPS

TOGGLE PortB.4
TMR1H = 2 : TMR1L = 24
' TMR1H = 4 : TMR1L = 161
PIE4.0 = 1 ' Activates Timer1

Main:
TOGGLE PortB.5 ' Heartbeat
GOTO Main

ToggleLED1:
PIE4.0 = 0 ' Stops Timer1
TOGGLE PortB.4
T1CON.0 = 0 ' Resets Timer1 gate
T1CON.0 = 1
TMR1H = 2 : TMR1L = 24
' TMR1H = 4 : TMR1L = 161
PIE4.0 = 1 ' Restarts Timer1
@ INT_RETURN



TMR1H = 2 : TMR1L = 24 gives 65.6mSec intervals according to Logic.


I have to use TMR1H = 4 : TMR1L = 161 to get 65.05mSec (after a lot of trial and error).

I must be doing something wrong...?

amgen
- 28th September 2024, 21:37
internal osc, what is the error %...... xtal osc matches with multicalc calculations

Demon
- 28th September 2024, 21:42
internal osc, what is the error %...... xtal osc matches with multicalc calculations


High-Precision Internal Oscillator:

- Software selectable frequency range up to 32 MHz, ±1% typical

I hadn't thought of that.

richard
- 29th September 2024, 01:14
Lets have a look at this



ToggleLED1:
PIE4.0 = 0 ' Stops Timer1 no it dosent
TOGGLE PortB.4
T1CON.0 = 0 ' Resets Timer1 gate no it dosent
T1CON.0 = 1
TMR1H = 2 : TMR1L = 24
' TMR1H = 4 : TMR1L = 161
PIE4.0 = 1 ' Restarts Timer1 no it dosent
@ INT_RETURN




should be more like



ToggleLED1:
T1CON.0 = 0 ' Stops Timer1
TMR1H = 2 : TMR1L = 18
T1CON.0 = 1 ' Restarts Timer1
TOGGLE PortB.4
@ INT_RETURN

richard
- 29th September 2024, 01:23
to get 65ms from my chip
TMR1H = 0 : TMR1L = 18
is required, so the int osc is not all that accurate
with multicalc figure i get about 64.8mS

Demon
- 29th September 2024, 01:45
...PIE4.0 = 1 ' Restarts Timer1 no it dosent...

Now I'm confused. :confused: I thought you said I had to handle it?


... dt ints will not enable intcon PEIE you need to


This runs 50msec non-stop:


#CONFIG
__config _CONFIG1, _FEXTOSC_OFF & _RSTOSC_HFINT32 & _CLKOUTEN_OFF & _CSWEN_OFF & _FCMEN_ON
__config _CONFIG2, _MCLRE_ON & _PWRTE_OFF & _LPBOREN_OFF & _BOREN_ON & _BORV_LO & _ZCD_OFF & _PPS1WAY_OFF & _STVREN_ON & _DEBUG_OFF
__config _CONFIG3, _WDTCPS_WDTCPS_11 & _WDTE_OFF & _WDTCWS_WDTCWS_7 & _WDTCCS_LFINTOSC
__config _CONFIG4, _WRT_OFF & _SCANE_available & _LVP_OFF
__config _CONFIG5, _CP_OFF & _CPD_OFF
#ENDCONFIG

include "I:\Project_v2\PBP\PBP_Includes\DT_INTS-14_16F18877.bas"
include "I:\Project_v2\PBP\PBP_Includes\ReEnterPBP.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _ToggleLED1, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

DEFINE OSC 32
ANSELA = %00000000
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00000000
ANSELE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %00000000
TRISD = %00000000
TRISE = %00000000

T1CON = %00110001 ' 1:8 Prescale, Enables Timer1
' bit 7-6 Unimplemented: Read as ‘0’
' bit 5-4 CKPS<1:0>: Timer1 Input Clock Prescale Select bits
' ----> 11 = 1:8 Prescale value
' 10 = 1:4 Prescale value
' 01 = 1:2 Prescale value
' 00 = 1:1 Prescale value
' bit 3 Unimplemented: Read as ‘0’
' bit 2 SYNC: Timer1 Synchronization Control bit
' When TMR1CLK = FOSC or FOSC/4
' This bit is ignored. The timer uses the internal clock and no
' additional synchronization is performed.
' When TMR1CS<1:0> = (any setting other than FOSC or FOSC/4)
' 1 = Do not synchronize external clock input
' 0 = Synchronized external clock input with system clock
' bit 1 RD16: Timer1 On bit
' 1 = All 16 bits of Timer1 can be read simultaneously (TMR1H is buffered)
' 0 = 16-bit reads of Timer1 are disabled (TMR1H is not buffered)
' bit 0 ON: Timer1 On bit
' ----> 1 = Enables Timer1
' 0 = Stops Timer1 and clears Timer1 gate flip-flop

T1CLK = %00000001 ' FOSC/4 Timer1 Clock
' bit 7-4 Unimplemented: Read as ‘0’
' bit 3-0 TxCS<3:0>: Timer1/3/5 Clock Select bits
' 1111 = LC4_out
' 1110 = LC3_out
' 1101 = LC2_out
' 1100 = LC1_out
' 1011 = TMR5 overflow output(3)
' 1010 = TMR3 overflow output(2)
' 1001 = TMR1 overflow output(1)
' 1000 = TMR0 overflow output
' 0111 = CLKR output clock
' 0110 = SOSC
' 0101 = MFINTOSC ' 1.05msec @ 32MHz with no preload
' 0100 = LFINTOSC ' n/a
' 0011 = HFINTOSC ' 16.56msec @ 32MHz with no preload
' 0010 = FOSC ' 16.54msec @ 32MHz with no preload
' ----> 0001 = FOSC/4 ' 66.18msec @ 32MHz with no preload
' 0000 = TxCKIPPS

LatB.0 = 0
TMR1H = 60 : TMR1L = 176 ' 50msec interval (32MHz, 16bit, 1:8)
PIE4.0 = 1 ' Starts Timer1
LatB.0 = 1

Main:
LatB.5 = 1 ' Heartbeat
LatB.5 = 0
GOTO Main

ToggleLED1:
LatB.0 = 0
' PIE4.0 = 0 ' Stops Timer1
TMR1H = 60 : TMR1L = 176 ' 50msec interval (32MHz, 16bit, 1:8)
' PIE4.0 = 1 ' Restarts Timer1
LatB.0 = 1
@ INT_RETURN

9770


This starts it once (same defines and registers):


ToggleLED1:
LatB.0 = 0
PIE4.0 = 0 ' Stops Timer1
TMR1H = 60 : TMR1L = 176 ' 50msec interval (32MHz, 16bit, 1:8)
' PIE4.0 = 1 ' Restarts Timer1
LatB.0 = 1
@ INT_RETURN

9771


This stops it, then starts it back up again (this is what I need for my project):


ToggleLED1:
LatB.0 = 0
PIE4.0 = 0 ' Stops Timer1
TMR1H = 60 : TMR1L = 176 ' 50msec interval (32MHz, 16bit, 1:8)
PIE4.0 = 1 ' Restarts Timer1
LatB.0 = 1
@ INT_RETURN

9772

richard
- 29th September 2024, 02:23
dt ints will not enable intcon PEIE you need to

yes with the newer chips some interrupt enable bits and flags have been relocated from INTCON reg into PIEx/PIRx regs
I'm not convinced dt-ints14 will always set the PEIE bit in INTCON when needed in all cases so i do it manually.
to set PEIE WITH GIE use
INTCON=$C0



for this chip and timer1 interrupts its not necessary dt-ints will set PEIE for you but this has no relationship with PIE4.0, i have no idea how you made that inference



just how does PIE4.0 = 0 stop the timer ?

writing to the timer like this when its still running is a very bad idea
TMR1H = 60 : TMR1L = 176 ' 50msec interval (32MHz, 16bit, 1:8)

Demon
- 29th September 2024, 02:55
...for this chip and timer1 interrupts its not necessary dt-ints will set PEIE for you but this has no relationship with PIE4.0, i have no idea how you made that inference...

I think I got that originally from the datasheet:
(16F18877 p.138)


Note: Bit PEIE of the INTCON register must be set to enable any peripheral interrupt controlled by registers PIE1-PIE8.


It looks to me like INTCOM is a master breaker; shutting that down shuts all interrupts.

And individual interrupts can be managed via their PIE registers (ie: PIE4 alone manages 6 timers)

Demon
- 29th September 2024, 02:58
...just how does PIE4.0 = 0 stop the timer ?...

(also p.138)


bit 0 TMR1IE: Timer1 Overflow Interrupt Enable bit

1 = Enables the Timer1 overflow interrupt
0 = Enables the Timer1 overflow interrupt

richard
- 29th September 2024, 03:27
pic16 's have one level of interrupt , therefore an interrupt can never be interrupted

disabling the timer1 interrupt inside an interrupt is a pointless exercises that accomplishes exactly nothing
except to waste machine cycles

disabling the timer1 interrupt does not in any way shape or form stop the timer from running.

the only way to stop the timer is to either turn it off or stop its clock signal.

Demon
- 29th September 2024, 03:55
pic16 's have one level of interrupt , therefore an interrupt can never be interrupted ...

No, but any interrupt triggered while an ISR is running will be handled once the ISR finishes.

(p.129 16F18877)


Note

1: Individual interrupt flag bits are set, regardless of the state of any other enable bits.

2: All interrupts will be ignored while the GIE bit is cleared. Any interrupt occurring while the GIE bit is clear will be serviced when the GIE bit is set again.

So you can have multiple Timers running at the same time (including USART interrupts and others).

No...?

richard
- 29th September 2024, 05:37
So you can have multiple Timers running at the same time (including USART interrupts and others).
of course you can, as many enabled as you see fit

but one and only one can be serviced at a time, and it cannot be interrupted. first come first served.
additional interrupts are serviced sequentially, one and only one at a time in the order the interrupt handler runs them.
hence keep isr's short