-
2 Attachment(s)
Elapsed timer not working as expected at 64MHz
Has anyone else had problems using DT's Elapsed Timer at 64MHz?
When I run a 18F44K22 at 64MHz, 99 TICKS = .247 second.
Attachment 7538
When I run at 16MHz, 99 TICKS = .988 second.
Attachment 7539
It's as if the timer runs at a default 16MHz when the PIC is at 64MHz (exactly 1/4 speed).
-
Re: Elapsed timer not working at 64MHz
When I look at Elapsed Timer include, Darryl has adjusted it to run at any oscillator frequency.
Code:
'***************************************************************************
'* Name : Elapsed_INT-18.bas *
'* Author : Darrel Taylor *
'* Date : JUL 11, 2006 : 7/11/2010 *
'* Version : 1.2 *
'* Notes : Must have DT_INTS-18.bas loaded first *
'* ver 1.2: Now works at any OSC frequency without using the prescaler *
'***************************************************************************
DISABLE DEBUG
; syntax = Handler IntSource, Label, Type, ResetFlag?
DEFINE Elapsed_Handler TMR1_INT, _ClockCount, asm, yes
; the above define can be used in the INT_LIST macro, if desired (optional)
Ticks VAR BYTE ; Counts timer Overflows
T1Post VAR BYTE ; Timer1 postscaler
Seconds VAR BYTE
Minutes VAR BYTE
Hours VAR BYTE
Days VAR WORD
SecondsChanged VAR BIT ; idicates that the value has changed
MinutesChanged VAR BIT
HoursChanged VAR BIT
DaysChanged VAR BIT
GOSUB ResetTime ; initialize the Elapsed Timer
Goto OverElapsed ; skip over the routines
' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value
; ----------------- ADD TimerConst to TMR1H:TMR1L -------------------------
ADD2_TIMER macro
BCF T1CON,TMR1ON, 0 ; 1 Turn off timer
MOVLW LOW(TimerConst) ; 1
ADDWF TMR1L,F, 0 ; 1
BTFSC STATUS,C ; 1/2
INCF TMR1H,F, 0 ; 1
MOVLW HIGH(TimerConst) ; 1
ADDWF TMR1H,F, 0 ; 1
endm
; ----------------- ADD TimerConst to TMR1H:TMR1L and restart TIMER1 ------
RELOAD_TIMER macro
ADD2_TIMER
BSF T1CON,TMR1ON, 0 ; 1 Turn TIMER1 back on (8 cycles)
endm
; ----------------- Load TimerConst into TMR1H:TMR1L ----------------------
LOAD_TIMER macro
MOVE?CT 0, T1CON,TMR1ON
MOVE?CB 0, TMR1L
MOVE?CB 0, TMR1H
ADD2_TIMER
endm
ENDASM
' ------[ This is the Interrupt Handler ]-----------------------------------
T1PS CON EXT
ClockCount:
@ RELOAD_TIMER ; Reload TIMER1
Ticks = Ticks + 1
IF Ticks = 100 THEN
Ticks = 0
T1Post = T1Post + 1
IF T1Post = T1PS THEN
T1Post = 0
Seconds = Seconds + 1
SecondsChanged = 1
IF Seconds = 60 THEN
Seconds = 0
Minutes = Minutes + 1
MinutesChanged = 1
ENDIF
IF Minutes = 60 THEN
Minutes = 0
Hours = Hours + 1
HoursChanged = 1
ENDIF
IF Hours = 24 THEN
Days = Days + 1
DaysChanged = 1
Hours = 0
ENDIF
ENDIF
ENDIF
@ INT_RETURN ; Restore context and return from interrupt
'-----====[ END OF TMR1 Interrupt Handler ]====-----------------------------
StartTimer:
T1CON = 1 ; 1:1, FOSC4, TMR1ON
RETURN
; --------------------------------------------------------------------------
StopTimer:
T1CON.0 = 0 ; Turn OFF Timer1
RETURN
; --------------------------------------------------------------------------
BitSave VAR BIT
ResetTime:
BitSave = T1CON.0 ; Save TMR1ON bit
@ LOAD_TIMER ; Load TimerConst
T1CON.0 = BitSave ; Restore TMR1ON bit
T1Post = 0 ; clear the postscaler
Ticks = 0
Seconds = 0
Minutes = 0
Hours = 0
Days = 0
SecondsChanged = 1 ; indicate everything has changed
MinutesChanged = 1 ; so that 00:00:00 is processed
HoursChanged = 1
DaysChanged = 1
RETURN
OverElapsed:
ENABLE DEBUG
The only thing that caught my eye was the TimerConst calculation. At 64MHz it is 160,000 on the first loop, well beyond the range of a WORD variable.
I don't have LONGs enabled right now. I can't seem to find the definition for TimerConst to see if it's a WORD or LONG.
It should be a WORD 'cause he ends up moving the high and low bytes.
-
Re: Elapsed timer not working at 64MHz
Hi Robert,
The first piece of code is executed by the assembler at the time the code is built. It doesn't execute when the PIC actually runs so there's no WORD size limit at play as far as I know.
The second piece you've marked in red is of course run time code but by the TimerConst should be less than 65400 so no problem.
With that said something is apparently not working as expected. Darrels code, relies on you having DEFINE OSC xx correctly. It's easy enough to have a 16MHz clock with the corresponding DEFINE and then enable the PLL to get 64MHz but forget to change to DEFINE OSC 64.
/Henrik.
-
1 Attachment(s)
Re: Elapsed timer not working at 64MHz
I bet this is my Saleae probe biting me in the nose again; not being able to run it fast enough.
The interrupt is working faster, I'm probably missing signals.
Attachment 7540
EDIT: And I notice I didn't align the marker the same way on Probe 1 - Port = 1 / 0, but it's the same interval as described in the WIDTH; 0.250uS, I just rechecked.
Code:
asm
; __CONFIG _CONFIG1H, _FOSC_INTIO67_1H & _PLLCFG_OFF_1H & _PRICLKEN_OFF_1H & _FCMEN_ON_1H & _IESO_OFF_1H
__CONFIG _CONFIG1H, _FOSC_INTIO67_1H & _PLLCFG_ON_1H & _PRICLKEN_OFF_1H & _FCMEN_ON_1H & _IESO_OFF_1H
__CONFIG _CONFIG2L, _PWRTEN_ON_2L & _BOREN_SBORDIS_2L & _BORV_285_2L
__CONFIG _CONFIG2H, _WDTEN_OFF_2H
__CONFIG _CONFIG3H, _CCP2MX_PORTC1_3H & _PBADEN_OFF_3H & _CCP3MX_PORTE0_3H & _HFOFST_OFF_3H & _T3CMX_PORTB5_3H & _P2BMX_PORTC0_3H & _MCLRE_EXTMCLR_3H
__CONFIG _CONFIG4L, _STVREN_OFF_4L & _LVP_OFF_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
endasm
;DEFINE OSC 16
;OSCTUNE = %10000000
DEFINE OSC 64
OSCTUNE = %11000000
OSCCON = %01110000
OSCCON2 = %00000100
INCLUDE "DT_INTS-18.bas"
INCLUDE "ReEnterPBP-18.bas"
INCLUDE "ReEnterPBP-18LP.bas"
INCLUDE "Elapsed_INT-18.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
; INT_Handler RX1_INT, _RX1Interrupt, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
INT_LIST_L macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _ClockCount, PBP, yes
endm
INT_CREATE_L ; Creates the Low Priority interrupt processor
ENDASM
ANSELA = %00000000
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00000000
ANSELE = %00000000
ADCON0 = %00000000
PMD0 = %10111110
PMD1 = %11011111
PMD2 = %00001111
DEFINE USE_LOWPRIORITY 1
TRISA = %00000000
TRISB = %00000000
TRISC = %00000000
TRISD = %00000000
TRISE = %00000000
PORTA = %00000000
PORTB = %00000000
PORTC = %00000000
PORTD = %00000000
PORTE = %00000000
pause 100
@ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts
GOSUB ResetTime ' Reset Time to 0d-00:00:00.00
MainProgram:
PortD.2 = 1
if T1CON.0 = 0 then
GOSUB StartTimer ' Start the Elapsed Timer
PortD.3 = 1
endif
PortD.2 = 0
if ticks = 25 then
PortD.3 = 0
GOSUB StopTimer ' Stop the Elapsed Timer
GOSUB ResetTime ' Reset Time to 0d-00:00:00.00
endif
goto MainProgram
end
Switch bouncing becomes much more pronounced at 64MHz. I think I'm going to change approach and go the long way and use just a 0.1uF ceramic cap on each pin (I remember that helped somewhat on previous tests).
Master PIC @ 64MHz
LED Slave PIC @ 64MHz
Keypad Slave PIC at 16MHz
I start DT Timer on a keypress and ignore inputs during that interval. I just have to make tests to see how fast I can press the same button and tweak the delay.
I wanted to handle both the LEDs and Keypad on the same PIC, but it'll be a lot easier and reliable to just split them up.
-
Re: Elapsed timer not working at 64MHz
So I minimized the code:
Code:
asm
__CONFIG _CONFIG1H, _FOSC_INTIO67_1H & _PLLCFG_ON_1H & _PRICLKEN_OFF_1H & _FCMEN_ON_1H & _IESO_OFF_1H
__CONFIG _CONFIG2L, _PWRTEN_ON_2L & _BOREN_SBORDIS_2L & _BORV_285_2L
__CONFIG _CONFIG2H, _WDTEN_OFF_2H
__CONFIG _CONFIG3H, _CCP2MX_PORTC1_3H & _PBADEN_OFF_3H & _CCP3MX_PORTE0_3H & _HFOFST_OFF_3H & _T3CMX_PORTB5_3H & _P2BMX_PORTC0_3H & _MCLRE_EXTMCLR_3H
__CONFIG _CONFIG4L, _STVREN_OFF_4L & _LVP_OFF_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
endasm
DEFINE OSC 16
OSCCON = %01010000
' R/W 111 = HFINTOSC – (16 MHz)
' 110 = HFINTOSC/2 – (8 MHz)
' 101 = HFINTOSC/4 – (4 MHz)
OSCTUNE = %11000000
OSCCON2 = %00000100
INCLUDE "DT_INTS-18.bas"
INCLUDE "ReEnterPBP-18.bas"
INCLUDE "Elapsed_INT-18.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _ClockCount, PBP, yes
endm
INT_CREATE
ENDASM
ANSELA = %00000000
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00000000
ANSELE = %00000000
ADCON0 = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %00000000
TRISD = %00000000
TRISE = %00000000
PORTA = %00000000
PORTB = %00000000
PORTC = %00000000
PORTD = %00000000
PORTE = %00000000
pause 100
@ INT_ENABLE TMR1_INT
GOSUB ResetTime
MainProgram:
if T1CON.0 = 0 then
PortD.3 = 1
GOSUB StartTimer
endif
if ticks = 5 then
PortD.3 = 0
GOSUB StopTimer ' Stop the Elapsed Timer
GOSUB ResetTime ' Reset Time to 0d-00:00:00.00
endif
goto MainProgram
end
5 TICK Timer
OSC 16MHz (4MHz+PLL) 50ms
OSC 32MHz (8MHz+PLL) 25ms
OSC 64MHz (16MHz+PLL) 12.5ms
I can't help but feel I'm doing something wrong, it's just too proportional a variance. If the Saleae probe would miss pulses, there wouldn't be a regular pattern.
-
Re: Elapsed timer not working as expected at 64MHz
debug T1PS and TimerConst to see what's going on would be a good start
-
Re: Elapsed timer not working as expected at 64MHz
-
Re: Elapsed timer not working as expected at 64MHz
tips value will be 4 at 64mhz , i played a lot with this elasped timer code , for up down timer
-
Re: Elapsed timer not working as expected at 64MHz
for 64mhz
each tick should be 2.5ms , to confirm the internal osc trim i enable a i/o pin to check its pulse per tick rate , it not the best way but it showed me that the most the time the internal osc needed some adj to ensure that it was as close as possable to 2.5ms
here is a snip of modifed code for the timer, i left the asm as it stands, but cos i wanted the 100th sec reading and the same structure of code , i changed / removed the t1post varable and used the MOD
Code:
EL_Ticks = EL_Ticks + 1 ; each tick is 2.5ms
' IF LATG.0 = 0 THEN ' debug
' LATG.0 = 1
' ELSE
' LATG.0 = 0
' ENDIF
if EL_ticks // T1PS = 0 THEN ' if modulas of tips (4) = 0
' IF LATG.0 = 0 THEN ' debug
' LATG.0 = 1
' ELSE
' LATG.0 = 0
' ENDIF
EL_100th = EL_100th + 1
EL_100thChanged = 1
IF EL_100TH = 100 THEN
EL_100TH = 0
EL_Seconds = EL_Seconds + 1
EL_SecondsChanged = 1
IF EL_Seconds = 60 THEN
EL_Seconds = 0
EL_Minutes = EL_Minutes + 1
EL_MinutesChanged = 1
eNDIF
IF EL_Minutes = 60 THEN
EL_Minutes = 0
EL_Hours = EL_Hours + 1
EL_HoursChanged = 1
ENDIF
IF EL_Hours = 24 THEN
EL_Hours = 0
EL_Days = EL_Days + 1
EL_DaysChanged = 1
ENDIF
eNDIF
endif
-
Re: Elapsed timer not working as expected at 64MHz
each 100th is 10ms on the i/o debug section btw
-
Re: Elapsed timer not working as expected at 64MHz
Code:
OSCTUNE = %01000111 ' Bit 7 - INTSRC - internal LF Source Select 1 = 31.25 from 16Mhz Internal /512 HF-INTOSC ) 0 = Internal 31khz OSC
' Bit 6 - PLLEN - 1 PLL enabled , 0 = PLL disabled
' Bits 5-0 Frequancy callibaration 00000 = centre Frq - FREQ ADJ = 5-7 ( the higher the number the slower the osc timing )
-
Re: Elapsed timer not working as expected at 64MHz
Quote:
Originally Posted by
richard
debug T1PS and TimerConst to see what's going on would be a good start
I started by making my version of the Elapsed include and adding 2 variables at the end of the timer calc:
Code:
...
' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value
; ---------------------------- DEBUG SCALER --------------------------------
DebugT1PS = T1PS
DebugTC = TimerConst
; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
...
Before Main of my program I added:
Code:
DebugT1PS CON EXT
DebugTC CON EXT
Right now I'm wiring up a LCD to display the 2 variables.
Am I on the right track to look at them?
I've never tried to display something from inside Darryl's includes before. My plan was to copy them into 2 words and then displaying the lower and upper bytes on the LCD.
-
Re: Elapsed timer not working as expected at 64MHz
Quote:
Am I on the right track to look at them?
probably not if yours fails try this
Code:
DISABLE DEBUG
; syntax = Handler IntSource, Label, Type, ResetFlag?
DEFINE Elapsed_Handler TMR1_INT, _ClockCount, asm, yes
; the above define can be used in the INT_LIST macro, if desired (optional)
Ticks VAR BYTE ; Counts timer Overflows
T1Post VAR BYTE ; Timer1 postscaler
Seconds VAR BYTE
Minutes VAR BYTE
Hours VAR BYTE
Days VAR WORD
DebugT1PS var byte
DebugTCL var byte
DebugTCh var byte
SecondsChanged VAR BIT ; idicates that the value has changed
MinutesChanged VAR BIT
HoursChanged VAR BIT
DaysChanged VAR BIT
GOSUB ResetTime ; initialize the Elapsed Timer
Goto OverElapsed ; skip over the routines
' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value
_DebugT1PS =T1PS
_DebugTCH=TimerConst /256
_DebugTCL = TimerConst - _DebugTCH*256
; ----------------- ADD TimerConst to TMR1H:TMR1L -------------------------
ADD2_TIMER macro
-
Re: Elapsed timer not working as expected at 64MHz
Actually, it worked. :D
I deleted my debug include 'cause I can work without it.
Code:
...
;T1PS CON EXT ' Already defined in include
TimerConst CON EXT
varT1PS var word
varTC var word
varT1PS = T1PS
varTC = TimerConst
Lcdout $fe, 1, "Timer 1"
Lcdout $fe, $94, "PS:", BIN8 varT1PS.byte1, " ", BIN8 varT1PS.byte0
Lcdout $fe, $D4, "TC:", BIN8 varTC.byte1, " ", BIN8 varTC.byte0
MainProgram:
And I get:
PS:00000000 00000001
TC:01100011 11001000 <--- Dec=25544
EDIT: Woooops, still using OSC 16, BRB.
-
Re: Elapsed timer not working as expected at 64MHz
OSC 64 (16 + PLL)
PS:00000000 00000100 <--- Dec=4
TC:01100011 11001000 <--- Dec=25544
I had same results manually this afternoon.
Robert
-
Re: Elapsed timer not working as expected at 64MHz
-
Re: Elapsed timer not working as expected at 64MHz
Looking at the datasheet for 18F44K22, timer 1 has a 2 bit prescaler.
4 (100) takes 3 bits.
Gonna try timer 2.
Quote:
...
13.0 TIMER2/4/6 MODULE p.175
...
• 8-bit Timer and Period registers (TMRx and PRx,
respectively)
• Readable and writable (both registers)
• Software programmable prescaler (1:1, 1:4, 1:16)
• Software programmable postscaler (1:1 to 1:16)
...
EDIT: Darn, DT Elapsed include only has Timer1...
Robert
-
Re: Elapsed timer not working as expected at 64MHz
Was looking at T1CON register and noticed this:
Quote:
TxCKPS<1:0>: Timer1/3/5 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
So that is 2 bits.
Code:
bit 7-6 TMRxCS<1:0>: Timer1/3/5 Clock Source Select bits
11 =Reserved. Do not use.
10 =Timer1/3/5 clock source is pin or oscillator:
If TxSOSCEN = 0:
External clock from TxCKI pin (on the rising edge)
If TxSOSCEN = 1:
Crystal oscillator on SOSCI/SOSCO pins
01 =Timer1/3/5 clock source is system clock (FOSC)
00 =Timer1/3/5 clock source is instruction clock (FOSC/4)
bit 5-4 TxCKPS<1:0>: Timer1/3/5 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 TxSOSCEN: Secondary Oscillator Enable Control bit
1 = Dedicated Secondary oscillator circuit enabled
0 = Dedicated Secondary oscillator circuit disabled
bit 2 TxSYNC: Timer1/3/5 External Clock Input Synchronization Control bit
TMRxCS<1:0> = 1X
1 = Do not synchronize external clock input
0 = Synchronize external clock input with system clock (FOSC)
TMRxCS<1:0> = 0X
This bit is ignored. Timer1/3/5 uses the internal clock when TMRxCS<1:0> = 1X.
bit 1 TxRD16: 16-Bit Read/Write Mode Enable bit
1 = Enables register read/write of Timer1/3/5 in one 16-bit operation
0 = Enables register read/write of Timer1/3/5 in two 8-bit operation
bit 0 TMRxON: Timer1/3/5 On bit
1 = Enables Timer1/3/5
0 = Stops Timer1/3/5
Clears Timer1/3/5 Gate flip-flop
T1CON=00000000
Robert
-
Re: Elapsed timer not working as expected at 64MHz
ITS NOT using the prescaler those bits need to be 00 ie 1:1
@64mhz with a preload of 25544 you get a tmr1 int every 2.5mS dt's int routine inc's the tips counter till its 4 then inc's the elapsed time clock I count ie once every 10mS
next step after confirming t1con is ok is to toggle a pin in the int routine as per what Sheldon suggested and verify 2.5mS ints are occurring
-
Re: Elapsed timer not working as expected at 64MHz
In the Elapsed include:
Code:
...
' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value
...
Darryl talks about a post-scaler. Timers 1, 3 and 5 have none for a 18F44K22?
Neither does Timer 0, only Timers 2,4 and 6 have pre and post-scalers.
Robert
-
Re: Elapsed timer not working as expected at 64MHz
t1con looks good should be 0 or 1 (on or off) depending on what the int routine is up to
-
Re: Elapsed timer not working as expected at 64MHz
Quote:
Darryl talks about a post-scaler. Timers 1, 3 and 5 have none for a 18F44K22?
Neither does Timer 0, only Timers 2,4 and 6 have pre and post-scalers
hence the T1PS VAR
-
Re: Elapsed timer not working as expected at 64MHz
for DT's elasped timer , i dont setup timer 1 at all
Code:
'Note: Programming the T1GCON prior to T1CON is recommended
T1GCON = %00000000 ' Timer 1 Gate Control bit7 0= counts regardless of gate 1 = gates in use , bit6 gate active when 1= High ,0=low
' bit5 0= toggle mode diabled 1= enabled bit4 single pulse mode 1- en 0= dis, bit 2 -status bit,1-0 - gate source sel
' 1
T1CON = %00000000 ' Timer 1 ,bit7-6 = TMR1 CLK source 00 = Instuction Clk(Fosc/4),01 =sys clk,10=ext clk,11=cap sense osc
' bit5-4 = TMR1 prescale 00= 1:1 ,bit3=0 LP off,bit2=1 no sync ext CLK ,bit1= 0 n/a,Bit0=0 Timer 1 on/off
TMR1H = 0 ' CLEAR TMR1H MODULE REGISTER
TMR1L = 0 ' CLEAR TMR1L MODULE REGISTER
-
Re: Elapsed timer not working as expected at 64MHz
I just noticed dt's ass code makes it impossible to stuff the t1con up it sets it to 0 anyway no matter what you may try to set it to . but worth checking anyway I suppose
-
Re: Elapsed timer not working as expected at 64MHz
Quote:
Originally Posted by
longpole001
each 100th is 10ms on the i/o debug section btw
My output pin changes state every 2.5ms at 64MHz.
Code:
'***************************************************************************
'* Name : Elapsed_INT-18.bas *
'* Author : Darrel Taylor *
'* Date : JUL 11, 2006 : 7/11/2010 *
'* Version : 1.2 *
'* Notes : Must have DT_INTS-18.bas loaded first *
'* ver 1.2: Now works at any OSC frequency without using the prescaler *
'***************************************************************************
DISABLE DEBUG
; syntax = Handler IntSource, Label, Type, ResetFlag?
DEFINE Elapsed_Handler TMR1_INT, _ClockCount, asm, yes
; the above define can be used in the INT_LIST macro, if desired (optional)
EL_Ticks VAR BYTE ; Counts timer Overflows
EL_100th VAR BYTE
;T1Post VAR BYTE ; Timer1 postscaler
EL_Seconds VAR BYTE
EL_Minutes VAR BYTE
EL_Hours VAR BYTE
EL_Days VAR WORD
EL_100thChanged VAR BIT
EL_SecondsChanged VAR BIT ; idicates that the value has changed
EL_MinutesChanged VAR BIT
EL_HoursChanged VAR BIT
EL_DaysChanged VAR BIT
GOSUB ResetTime ; initialize the Elapsed Timer
Goto OverElapsed ; skip over the routines
' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value
; ----------------- ADD TimerConst to TMR1H:TMR1L -------------------------
ADD2_TIMER macro
BCF T1CON,TMR1ON, 0 ; 1 Turn off timer
MOVLW LOW(TimerConst) ; 1
ADDWF TMR1L,F, 0 ; 1
BTFSC STATUS,C ; 1/2
INCF TMR1H,F, 0 ; 1
MOVLW HIGH(TimerConst) ; 1
ADDWF TMR1H,F, 0 ; 1
endm
; ----------------- ADD TimerConst to TMR1H:TMR1L and restart TIMER1 ------
RELOAD_TIMER macro
ADD2_TIMER
BSF T1CON,TMR1ON, 0 ; 1 Turn TIMER1 back on (8 cycles)
endm
; ----------------- Load TimerConst into TMR1H:TMR1L ----------------------
LOAD_TIMER macro
MOVE?CT 0, T1CON,TMR1ON
MOVE?CB 0, TMR1L
MOVE?CB 0, TMR1H
ADD2_TIMER
endm
ENDASM
' ------[ This is the Interrupt Handler ]-----------------------------------
T1PS CON EXT
ClockCount:
@ RELOAD_TIMER ; Reload TIMER1
EL_Ticks = EL_Ticks + 1 ; each tick is 2.5ms
IF LATD.3 = 0 THEN ' debug
LATD.3 = 1
ELSE
LATD.3 = 0
ENDIF
if EL_ticks // T1PS = 0 THEN ' if modulas of tips (4) = 0
IF LATD.3 = 0 THEN ' debug
LATD.3 = 1
ELSE
LATD.3 = 0
ENDIF
EL_100th = EL_100th + 1
EL_100thChanged = 1
IF EL_100TH = 100 THEN
EL_100TH = 0
EL_Seconds = EL_Seconds + 1
EL_SecondsChanged = 1
IF EL_Seconds = 60 THEN
EL_Seconds = 0
EL_Minutes = EL_Minutes + 1
EL_MinutesChanged = 1
eNDIF
IF EL_Minutes = 60 THEN
EL_Minutes = 0
EL_Hours = EL_Hours + 1
EL_HoursChanged = 1
ENDIF
IF EL_Hours = 24 THEN
EL_Hours = 0
EL_Days = EL_Days + 1
EL_DaysChanged = 1
ENDIF
eNDIF
endif
' Ticks = Ticks + 1
' IF Ticks = 100 THEN
' Ticks = 0
' T1Post = T1Post + 1
' IF T1Post = T1PS THEN
' T1Post = 0
' Seconds = Seconds + 1
' SecondsChanged = 1
' IF Seconds = 60 THEN
' Seconds = 0
' Minutes = Minutes + 1
' MinutesChanged = 1
' ENDIF
' IF Minutes = 60 THEN
' Minutes = 0
' Hours = Hours + 1
' HoursChanged = 1
' ENDIF
' IF Hours = 24 THEN
' Days = Days + 1
' DaysChanged = 1
' Hours = 0
' ENDIF
' ENDIF
' ENDIF
@ INT_RETURN ; Restore context and return from interrupt
'-----====[ END OF TMR1 Interrupt Handler ]====-----------------------------
StartTimer:
T1CON = 1 ; 1:1, FOSC4, TMR1ON
RETURN
; --------------------------------------------------------------------------
StopTimer:
T1CON.0 = 0 ; Turn OFF Timer1
RETURN
; --------------------------------------------------------------------------
BitSave VAR BIT
ResetTime:
BitSave = T1CON.0 ; Save TMR1ON bit
@ LOAD_TIMER ; Load TimerConst
T1CON.0 = BitSave ; Restore TMR1ON bit
; T1Post = 0 ; clear the postscaler
EL_Ticks = 0
EL_100th = 0
EL_Seconds = 0
EL_Minutes = 0
EL_Hours = 0
EL_Days = 0
EL_100thChanged = 1
EL_SecondsChanged = 1 ; indicate everything has changed
EL_MinutesChanged = 1 ; so that 00:00:00 is processed
EL_HoursChanged = 1
EL_DaysChanged = 1
RETURN
OverElapsed:
ENABLE DEBUG
-
Re: Elapsed timer not working as expected at 64MHz
Quote:
Originally Posted by
longpole001
each 100th is 10ms on the i/o debug section btw
My output pin changes state every 2.5ms at 64MHz.
Code:
'***************************************************************************
'* Name : Elapsed_INT-18.bas *
'* Author : Darrel Taylor *
'* Date : JUL 11, 2006 : 7/11/2010 *
'* Version : 1.2 *
'* Notes : Must have DT_INTS-18.bas loaded first *
'* ver 1.2: Now works at any OSC frequency without using the prescaler *
'***************************************************************************
DISABLE DEBUG
; syntax = Handler IntSource, Label, Type, ResetFlag?
DEFINE Elapsed_Handler TMR1_INT, _ClockCount, asm, yes
; the above define can be used in the INT_LIST macro, if desired (optional)
EL_Ticks VAR BYTE ; Counts timer Overflows
EL_100th VAR BYTE
;T1Post VAR BYTE ; Timer1 postscaler
EL_Seconds VAR BYTE
EL_Minutes VAR BYTE
EL_Hours VAR BYTE
EL_Days VAR WORD
EL_100thChanged VAR BIT
EL_SecondsChanged VAR BIT ; idicates that the value has changed
EL_MinutesChanged VAR BIT
EL_HoursChanged VAR BIT
EL_DaysChanged VAR BIT
GOSUB ResetTime ; initialize the Elapsed Timer
Goto OverElapsed ; skip over the routines
' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value
; ----------------- ADD TimerConst to TMR1H:TMR1L -------------------------
ADD2_TIMER macro
BCF T1CON,TMR1ON, 0 ; 1 Turn off timer
MOVLW LOW(TimerConst) ; 1
ADDWF TMR1L,F, 0 ; 1
BTFSC STATUS,C ; 1/2
INCF TMR1H,F, 0 ; 1
MOVLW HIGH(TimerConst) ; 1
ADDWF TMR1H,F, 0 ; 1
endm
; ----------------- ADD TimerConst to TMR1H:TMR1L and restart TIMER1 ------
RELOAD_TIMER macro
ADD2_TIMER
BSF T1CON,TMR1ON, 0 ; 1 Turn TIMER1 back on (8 cycles)
endm
; ----------------- Load TimerConst into TMR1H:TMR1L ----------------------
LOAD_TIMER macro
MOVE?CT 0, T1CON,TMR1ON
MOVE?CB 0, TMR1L
MOVE?CB 0, TMR1H
ADD2_TIMER
endm
ENDASM
' ------[ This is the Interrupt Handler ]-----------------------------------
T1PS CON EXT
ClockCount:
@ RELOAD_TIMER ; Reload TIMER1
EL_Ticks = EL_Ticks + 1 ; each tick is 2.5ms
IF LATD.3 = 0 THEN ' debug
LATD.3 = 1
ELSE
LATD.3 = 0
ENDIF
if EL_ticks // T1PS = 0 THEN ' if modulas of tips (4) = 0
IF LATD.3 = 0 THEN ' debug
LATD.3 = 1
ELSE
LATD.3 = 0
ENDIF
EL_100th = EL_100th + 1
EL_100thChanged = 1
IF EL_100TH = 100 THEN
EL_100TH = 0
EL_Seconds = EL_Seconds + 1
EL_SecondsChanged = 1
IF EL_Seconds = 60 THEN
EL_Seconds = 0
EL_Minutes = EL_Minutes + 1
EL_MinutesChanged = 1
eNDIF
IF EL_Minutes = 60 THEN
EL_Minutes = 0
EL_Hours = EL_Hours + 1
EL_HoursChanged = 1
ENDIF
IF EL_Hours = 24 THEN
EL_Hours = 0
EL_Days = EL_Days + 1
EL_DaysChanged = 1
ENDIF
eNDIF
endif
' Ticks = Ticks + 1
' IF Ticks = 100 THEN
' Ticks = 0
' T1Post = T1Post + 1
' IF T1Post = T1PS THEN
' T1Post = 0
' Seconds = Seconds + 1
' SecondsChanged = 1
' IF Seconds = 60 THEN
' Seconds = 0
' Minutes = Minutes + 1
' MinutesChanged = 1
' ENDIF
' IF Minutes = 60 THEN
' Minutes = 0
' Hours = Hours + 1
' HoursChanged = 1
' ENDIF
' IF Hours = 24 THEN
' Days = Days + 1
' DaysChanged = 1
' Hours = 0
' ENDIF
' ENDIF
' ENDIF
@ INT_RETURN ; Restore context and return from interrupt
'-----====[ END OF TMR1 Interrupt Handler ]====-----------------------------
StartTimer:
T1CON = 1 ; 1:1, FOSC4, TMR1ON
RETURN
; --------------------------------------------------------------------------
StopTimer:
T1CON.0 = 0 ; Turn OFF Timer1
RETURN
; --------------------------------------------------------------------------
BitSave VAR BIT
ResetTime:
BitSave = T1CON.0 ; Save TMR1ON bit
@ LOAD_TIMER ; Load TimerConst
T1CON.0 = BitSave ; Restore TMR1ON bit
; T1Post = 0 ; clear the postscaler
EL_Ticks = 0
EL_100th = 0
EL_Seconds = 0
EL_Minutes = 0
EL_Hours = 0
EL_Days = 0
EL_100thChanged = 1
EL_SecondsChanged = 1 ; indicate everything has changed
EL_MinutesChanged = 1 ; so that 00:00:00 is processed
EL_HoursChanged = 1
EL_DaysChanged = 1
RETURN
OverElapsed:
ENABLE DEBUG
-
Re: Elapsed timer not working as expected at 64MHz
Yes, I'm an idiot.
T1CON becomes 00000001 once it is STARTED! D'OH!
-
1 Attachment(s)
Re: Elapsed timer not working as expected at 64MHz
Sheldon,
It's not perfect, I'm missing some pulses on the Saleae probe, but it's sticking to a 2.5ms tick as you describe in your Elapsed include comment.
Attachment 7541
EDIT: I just noticed that the skipped pulse happens at every 4 ticks.
And that skipped pulse is between 20-21uS.
EDIT SOME MORE: Got it, it's that 2nd LED toggle. I commented it out and now I have a regular 2.5ms pulse.
Robert
-
Re: Elapsed timer not working as expected at 64MHz
Quote:
Originally Posted by
longpole001
each 100th is 10ms on the i/o debug section btw
Yup, I get 10ms if I comment out the 1st LED toggle.
Attachment 7542
I understand quickly as long as you explain 10 times.
Robert
-
Re: Elapsed timer not working as expected at 64MHz
Well that toggle from Sheldon confirms DT's is not working perfectly at 64MHz.
I get 2.5ms on each LED toggle.
Code:
T1PS CON EXT
ClockCount:
@ RELOAD_TIMER ; Reload TIMER1
Ticks = Ticks + 1
IF LATD.3 = 0 THEN ' debug
LATD.3 = 1
ELSE
LATD.3 = 0
ENDIF
IF Ticks = 100 THEN
Ticks = 0
T1Post = T1Post + 1
IF T1Post = T1PS THEN
T1Post = 0
Seconds = Seconds + 1
SecondsChanged = 1
IF Seconds = 60 THEN
Seconds = 0
Minutes = Minutes + 1
MinutesChanged = 1
ENDIF
IF Minutes = 60 THEN
Minutes = 0
Hours = Hours + 1
HoursChanged = 1
ENDIF
IF Hours = 24 THEN
Days = Days + 1
DaysChanged = 1
Hours = 0
ENDIF
ENDIF
ENDIF
@ INT_RETURN ; Restore context and return from interrupt
Thanks a lot Sheldon for having figured this one out.
Robert
GAAAAA must not click on MeProg PROGRAM icon when I want to click on POST, it won't work.
-
Re: Elapsed timer not working as expected at 64MHz
now I'm confused
Quote:
Well that toggle from Sheldon confirms DT's is not working perfectly at 64MHz.
or
Well that toggle from Sheldon confirms DT's is working perfectly at 64MHz.
ps
Quote:
IF LATD.3 = 0 THEN ' debug
LATD.3 = 1
ELSE
LATD.3 = 0
ENDIF
can be replaced with
lets not have too much unnecessary overhead in the interrupt
-
Re: Elapsed timer not working as expected at 64MHz
Quote:
Originally Posted by
richard
now I'm confused
or
Well that toggle from Sheldon confirms DT's is working perfectly at 64MHz.
DT's Elapsed include doesn't work perfectly at 64MHz (1 tick = 2.5ms), Sheldon's modified version does (1/100th = 10ms). Sheldon has added a new variable. I'm cleaning up the new include now to put it on the forum, somewhere.
Robert
-
2 Attachment(s)
Re: Elapsed timer not working as expected at 64MHz
New version of Darrel Taylor's Elapsed include for 64MHz:
Code:
'***************************************************************************
'* Name : Elapsed_INT-18.bas *
'* Author : Darrel Taylor *
'* Date : JUL 11, 2006 : 7/11/2010 : Dec 23, 2014 *
'* Version : 1.3 *
'* Notes : Must have DT_INTS-18.bas loaded first *
'* ver 1.2: Now works at any OSC frequency without using the prescaler *
'* ver 1.3: will work with 64MHz thanks to Sheldon *
'* New field ONEHUNDRETH is now used instead of TICKS *
'***************************************************************************
DISABLE DEBUG
; syntax = Handler IntSource, Label, Type, ResetFlag?
DEFINE Elapsed_Handler TMR1_INT, _ClockCount, asm, yes
; the above define can be used in the INT_LIST macro, if desired (optional)
Ticks VAR BYTE ; Counts timer Overflows
OneHundreth VAR BYTE ; New field for 64MHz
;T1Post VAR BYTE ; Timer1 postscaler
Seconds VAR BYTE
Minutes VAR BYTE
Hours VAR BYTE
Days VAR WORD
OneHundrethChanged VAR BIT ; New field for 64MHz
SecondsChanged VAR BIT ; idicates that the value has changed
MinutesChanged VAR BIT
HoursChanged VAR BIT
DaysChanged VAR BIT
GOSUB ResetTime ; initialize the Elapsed Timer
Goto OverElapsed ; skip over the routines
' -------------- calc timer reload Constants -------------------------------
ASM
T1PS = 1 ; start with 1:1 postscaler
TimerConst = ((OSC*1000000)/4/100) ; how many timer ticks will it take
while TimerConst > 65400 ; if it's more than the timer can count
T1PS = T1PS * 2 ; double the postscaler
TimerConst = TimerConst / 2 ; halve the count
endw
TimerConst = 65536 - TimerConst + 8 ; final reload value
; ----------------- ADD TimerConst to TMR1H:TMR1L -------------------------
ADD2_TIMER macro
BCF T1CON,TMR1ON, 0 ; 1 Turn off timer
MOVLW LOW(TimerConst) ; 1
ADDWF TMR1L,F, 0 ; 1
BTFSC STATUS,C ; 1/2
INCF TMR1H,F, 0 ; 1
MOVLW HIGH(TimerConst) ; 1
ADDWF TMR1H,F, 0 ; 1
endm
; ----------------- ADD TimerConst to TMR1H:TMR1L and restart TIMER1 ------
RELOAD_TIMER macro
ADD2_TIMER
BSF T1CON,TMR1ON, 0 ; 1 Turn TIMER1 back on (8 cycles)
endm
; ----------------- Load TimerConst into TMR1H:TMR1L ----------------------
LOAD_TIMER macro
MOVE?CT 0, T1CON,TMR1ON
MOVE?CB 0, TMR1L
MOVE?CB 0, TMR1H
ADD2_TIMER
endm
ENDASM
' ------[ This is the Interrupt Handler ]-----------------------------------
T1PS CON EXT
ClockCount:
@ RELOAD_TIMER ; Reload TIMER1
Ticks = Ticks + 1 ; each tick is 2.5ms
' IF LATD.3 = 0 THEN ' used to debug to confirm 2.5ms
' LATD.3 = 1
' ELSE
' LATD.3 = 0
' ENDIF
if ticks // T1PS = 0 THEN ' if modulas of tips (4) = 0
' IF LATD.3 = 0 THEN ' used to debug to confirm 10ms
' LATD.3 = 1
' ELSE
' LATD.3 = 0
' ENDIF
OneHundreth = OneHundreth + 1 ; each 1/100th is 10ms
OneHundrethChanged = 1
IF OneHundreth = 100 THEN
OneHundreth = 0
' Ticks = Ticks + 1
' IF Ticks = 100 THEN
' Ticks = 0
' T1Post = T1Post + 1
' IF T1Post = T1PS THEN
' T1Post = 0
Seconds = Seconds + 1
SecondsChanged = 1
IF Seconds = 60 THEN
Seconds = 0
Minutes = Minutes + 1
MinutesChanged = 1
ENDIF
IF Minutes = 60 THEN
Minutes = 0
Hours = Hours + 1
HoursChanged = 1
ENDIF
IF Hours = 24 THEN
Days = Days + 1
DaysChanged = 1
Hours = 0
ENDIF
ENDIF
ENDIF
@ INT_RETURN ; Restore context and return from interrupt
'-----====[ END OF TMR1 Interrupt Handler ]====-----------------------------
StartTimer:
T1CON = 1 ; 1:1, FOSC4, TMR1ON
RETURN
; --------------------------------------------------------------------------
StopTimer:
T1CON.0 = 0 ; Turn OFF Timer1
RETURN
; --------------------------------------------------------------------------
BitSave VAR BIT
ResetTime:
BitSave = T1CON.0 ; Save TMR1ON bit
@ LOAD_TIMER ; Load TimerConst
T1CON.0 = BitSave ; Restore TMR1ON bit
; T1Post = 0 ; clear the postscaler
Ticks = 0
OneHundreth = 0
Seconds = 0
Minutes = 0
Hours = 0
Days = 0
OneHundrethChanged = 1
SecondsChanged = 1 ; indicate everything has changed
MinutesChanged = 1 ; so that 00:00:00 is processed
HoursChanged = 1
DaysChanged = 1
RETURN
OverElapsed:
ENABLE DEBUG
New field OneHundreth (10ms) replaces Tick (2.5ms at 64MHz).
Attachment 7543
(Remove .TXT suffix)
Attachment 7544
Robert
-
Re: Elapsed timer not working as expected at 64MHz
you may like to re-examine that I just tried it on a pic1845k20 @64 MHz and the int is @2.5mS as expected , sheldons mod just adds 100th capability doesn't it ?
the seconds inc on every 400th interrupt the ticks are not meant to be 10mS
-
Re: Elapsed timer not working as expected at 64MHz
From http://web.archive.org/web/201206151...8/elapsed.html
Quote:
The time is kept in the variables:
--------------------------------------------------------------------------------
Ticks var byte ' 1/100th of a second
Seconds var byte ' 0-59
Minutes var byte ' 0-59
Hours var byte ' 0-23
Days var word ' 0-65535
But a tick is not 2.5ms.
Robert
-
1 Attachment(s)
Re: Elapsed timer not working as expected at 64MHz
Quote:
Originally Posted by
richard
you may like to re-examine that I just tried it on a pic1845k20 @64 MHz and the int is 2.5mS as expected , sheldons mod just adds 100th doesn't it
the ticks only inc on every 4th interrupt
What happens when you start/stop the timer after 5 ticks using the original include?
I get this using the new include:
Attachment 7546
Code:
MainProgram:
if T1CON.0 = 0 then
PortD.3 = 1
GOSUB StartTimer
endif
if OneHundreth = 5 then
PortD.3 = 0
GOSUB StopTimer ' Stop the Elapsed Timer
GOSUB ResetTime ' Reset Time to 0d-00:00:00.00
endif
goto MainProgram
Robert
-
Re: Elapsed timer not working as expected at 64MHz
its a clock not a stopwatch , if you really need to measure wee small times like that there are better ways.
to get the fractional part of the seconds multiply t1post with ticks and / 4
-
Re: Elapsed timer not working as expected at 64MHz
ticks should be 2.5ms , 1/100 is 4 x tick = 10ms , 1 sec should be 100 x 1/100th or 400 tick = 1sec
-
Re: Elapsed timer not working as expected at 64MHz
i did version of DTs elapsed timer that shown at 1/1000 , assuming it does nothing else in life and you got a good xtl , it work ok up to 12 hours , when i tested it
also DT had a thing about showing code doing a countdown timer , so i never posted it as per his request
-
Re: Elapsed timer not working as expected at 64MHz
Code:
EL_Ticks VAR BYTE ; Ticks Up Counter -timer Overflows
EL_100th VAR BYTE ; value for 1/100s
EL_Seconds VAR BYTE ; value for seconds
EL_Minutes VAR byte
EL_Hours VAR BYTE
EL_Days VAR BYTE