Timer Interrupt

thunderace7

New Member
Hi,
I am trying to use the timer in a 28x2 to make a repeating interrupt every 10 seconds. The manual is not very clear on this (at least, not to me) but I think it works something like this:

The timer operates with "minor tick" which are related to the clock frequency and, at 8Mhz, occur every 32 microseconds. These minor ticks are counted in a word variable that is not user accessible. When this variable overflows from 65535 to 0, a "major tick" is produced which is counted on a variable called "timer" that is user accessible. When this "timer" variable overflows from 65535 to 0, an interrupt flag is set, causing the program to jump to the "interrupt" subroutine. It seems that this flag remains set and must be reset within the interrupt subroutine. The interrupt must also be re-enabled with the "setintflags" command within the interrupt subroutine.
The manual also states that the timer can be preloaded with a value to reduce the time until overflow. This is achieved by the command "settimer". I believe that this preloads the minor ticks counter, NOT the "timer" variable as seems logical (to me, at least). Using the constant "t1s_8" a value of 34286 is preloaded to give 1 second timing at 8Mhz. I believe that this actually gives minor tick overflow as 1 second intervals, not 1 second interrupts. To get 10 second interrupts, the major tick variable "timer" also has to be preloaded with the value 65526.

Does all this sound right or am I mistaken?

I have played around in the Editor and have come up with the following program:

code:

initialise:
#picaxe 28x2 ; define picaxe chip for compiler
setfreq m8 ; select internal resonator 8MHz
let dirsa=%11111111 ; set port a as outputs
let dirsb=%11111111 ; set port b as outputs
let dirsc=%11111111 ; set port c as outputs

settimer t1s_8 ; settimer to 1 second ticks at 8MHz
setintflags %10000000,%10000000 ; set timer 0 to interrupt
let timer=65526 ; preload timer variable for 10 second interrupt

main:
Let pinC.4=1 ; insert main program here
Pause 100 ; insert main program here
Let pinC.4=0 ; insert main program here
Pause 100 ; insert main program here
let pinsb=timer ; insert main program here
Goto main ; loop back to repeat

interrupt:
pause 2000 ; insert interrupt program here
setintflags %10000000,%10000000 ; set timer 0 to interrupt
let timer=65526 ; preload timer variable for 10 second interrupt
let toflag=0 ; clear timer overflow flag
return


code:

This seems to work but it might not be correct. I think maybe the "let toflag=0" line could be replaced by another "settimer t1s_8" line. Would this be more correct?

Thanks,
Chris.
 

PhilHornby

Senior Member
This seems to work but it might not be correct. I think maybe the "let toflag=0" line could be replaced by another "settimer t1s_8" line. Would this be more correct?
It looks plausible and if it's working then "job done" :)
(I always have to re-read the manual to get this working).

toflag = 0 resets the interrupt condition, rather than setting the timer parameters (that settimer does), so is correct.

(As a general point, you don't need let statements).
 

inglewoodpete

Senior Member
Hi,
I am trying to use the timer in a 28x2 to make a repeating interrupt every 10 seconds. The manual is not very clear on this (at least, not to me) but I think it works something like this:

The timer operates with "minor tick" which are related to the clock frequency and, at 8Mhz, occur every 32 microseconds. These minor ticks are counted in a word variable that is not user accessible. When this variable overflows from 65535 to 0, a "major tick" is produced which is counted on a variable called "timer" that is user accessible. When this "timer" variable overflows from 65535 to 0, an interrupt flag is set, causing the program to jump to the "interrupt" subroutine. It seems that this flag remains set and must be reset within the interrupt subroutine. The interrupt must also be re-enabled with the "setintflags" command within the interrupt subroutine.
The manual also states that the timer can be preloaded with a value to reduce the time until overflow. This is achieved by the command "settimer". I believe that this preloads the minor ticks counter, NOT the "timer" variable as seems logical (to me, at least). Using the constant "t1s_8" a value of 34286 is preloaded to give 1 second timing at 8Mhz. I believe that this actually gives minor tick overflow as 1 second intervals, not 1 second interrupts. To get 10 second interrupts, the major tick variable "timer" also has to be preloaded with the value 65526.

Does all this sound right or am I mistaken?

I have played around in the Editor and have come up with the following program:

Code:
initialise:
    #picaxe 28x2                    ; define picaxe chip for compiler
    setfreq m8                        ; select internal resonator 8MHz
    let dirsa=%11111111                ; set port a as outputs
    let dirsb=%11111111                ; set port b as outputs
    let dirsc=%11111111                ; set port c as outputs
       
        settimer t1s_8                ; settimer to 1 second ticks at 8MHz
        setintflags %10000000,%10000000    ; set timer 0 to interrupt
        let timer=65526                ; preload timer variable for 10 second interrupt
   
main:
        Let pinC.4=1                ; insert main program here
        Pause 100                    ; insert main program here
        Let pinC.4=0                ; insert main program here
        Pause 100                    ; insert main program here
        let pinsb=timer                ; insert main program here
    Goto main                        ; loop back to repeat
   
interrupt:
         pause 2000                    ; insert interrupt program here
        setintflags %10000000,%10000000    ; set timer 0 to interrupt
        let timer=65526                ; preload timer variable for 10 second interrupt
         let toflag=0                ; clear timer overflow flag
     return
This seems to work but it might not be correct. I think maybe the "let toflag=0" line could be replaced by another "settimer t1s_8" line. Would this be more correct?

Thanks,
Chris.
To optimise your interrupt handler, I suggest the following changes:
  1. The command to reset the TimeOut flag should be one of the FIRST commands executed in the interrupt routine
  2. The very LAST command before the Return statement should set (reset) the Interrupt flags
  3. Avoid using Pauses or loops within the interrupt routine. They defeat the purpose of interrupts.
While these suggestions may not have much impact on a 10-second interrupt in a simple program, they will help keep time-critical operations efficient.
 

Engle

Member
Seems like you have a good understanding of the minor/major ticks, I used the same understanding recently for timer to measure lap times in tenths of a second at 16MHz. For best practice I agree with Pete's points. Also resetting the flags as the last command means you can find it easily and change them in your interrupt handling too, which I was doing with some software interrupts on a game.

In some rare cases you might want to have a longish interrupt, I was playing audio messages that I didn't want re-interrupted. For that reason, I'd recommend timer=65526 also as one of the first commands. Otherwise, the timer may go to 1 or 2 and then you'd have a 12 second interval.

I believe that if you want consistent 10 second intervals, the flag reset seems the way to go. If you did another settimer I envisage it would reset the minor ticks whizzing around, so then you'd lose part of a second and you'd have a 10 point something interval, instead of ten.
 

thunderace7

New Member
Thank you all for your replies.
I have amended my program as suggested. The pause command within the interrupt was just a placeholder for me to insert exactly what I wanted the interrupt to do and so that I had time to see it in the editor simulation.
Thanks again,
Chris.
 
Top