1 second interrupt on 20X2?

RSanger

New Member
just can't figure out why this 1 second interrupt doesn't work on my 20X2. And neither can Chat GPT.
Help GREATLY appreciated - I'm an interrupt newbie....

#picaxe 20x2
#no_table
#no_data
symbol seconds = b0 ; Variable to hold elapsed seconds

setfreq m4 ; Set operating frequency to 4 MHz
settimer t1s_4 ; Configure timer for 1-second intervals

setintflags %10000000, %10000000 ; Enable interrupt on timer overflow

main:
do
sertxd(#seconds, 13, 10) ; Send elapsed time to terminal
pause 1000 ; Prevent terminal flooding

loop

interrupt:
inc seconds ; Increment seconds counter directly
toflag = 0 ; Clear the timer overflow flag

setintflags %10000000, %10000000 ; Re-enable interrupt
return
 
Try the following

Cheers
Mike

Code:
#picaxe 20x2
#no_table
#no_data
symbol seconds = b0 ; Variable to hold elapsed seconds

setfreq m4 ; Set operating frequency to 4 MHz
settimer t1s_4 ; Configure timer for 1-second intervals

;turn on interrupt
Call interrupt_Enable

main:
do
sertxd(#seconds, 13, 10) ; Send elapsed time to terminal
pause 1000 ; Prevent terminal flooding

loop



interrupt:
;do interrupt stuff here


'turn interrupts back on
interrupt_Enable:
Setintflags %10000000, %10000000
timer = $FFFF    ;minor tick causes major tick in timer, ie it overflows to 0
toflag = 0         ;clears interrupt flag
Return
 
A couple of points when using X2 chips and on configuring interrupts.

Due to the larger token size and additional complexity of the X2 chips' firmware (20X2, 28X2 & 40X2), it is best to let them run at their default speed of 8Mhz. (Unless of course, your want them to execute faster.) This allows them to complete overhead tasks like handling interrupts promptly. It also lets pauses to have increments of 1mS. In an X2, 4MHz the pause will have increments of 2mS, so Pause 1000 will cause a 2 second delay in execution.

When writing an interrupt routine, it is best practice to clear interrupt flags immediately on entering the interrupt routine. While it may not matter too much with a 1-second timer interrupt, when using the interrupt routine to handle communications interrupts (Eg i2c or hSerial), it will clear a flag promptly giving a better chance of recording subsequent interrupts that can occur in quick succession. Best practice also dictates that the SetIntFlags command should be the last command before the Return statement, which enables interrupts again.
 
THANK YOU! my mistake was in thinking that toflag is set to 1 when subticks overflowed and timer was incremented, but it is clearly stated in the documentation that toflag is set when timer overflows....
so inglewoodpete, does this code conform to best practices? (aside from working like a charm)
#picaxe 20x2
#no_table
#no_data
symbol seconds = b0 ; Variable to hold elapsed seconds
setfreq m16 ; Set operating frequency to 4 MHz
settimer t1s_16 ; Configure timer for 1-second intervals

gosub start_interrupt
main:
do
sertxd(#seconds, 13, 10) ; Send elapsed time to terminal
pause 100

loop

interrupt:
toflag=0
inc seconds ; Increment seconds counter directly

start_interrupt:
timer=$ffff
setintflags %10000000, %10000000 ; Re-enable interrupt
return
 
Yes, your code is spot on for checking the timer. Forgive me nit-picking but the comment against the "setfreq" command should be changed too.

Personally, I have an aversion to using pause statements if they are not absolutely necessary - often they can delay reading external events from input pins. This can result in a short input pulse being missed. Note that interrupts actually interrupt (and cancel) the pause timer, so it would not be a problem with your program here.

The following code eliminates the need for a pause statement.

Add another symbol:
Rich (BB code):
symbol prevseconds = b1 ; Used to indicate that the current second has been logged

Replace the original main loop:
Rich (BB code):
do
   If seconds <> prevseconds Then   ;If another second has ticked by
      sertxd(#seconds, 13, 10) ; Send elapsed time to terminal
      prevseconds = seconds ; Keep a record of the last logged second
   EndIf
loop
 
Last edited:
IP,
It seems we think alike. I definitely prefer tracking that the seconds have changed over using pauses.
 
Got it... the MAIN routine was really just a placeholder, I've got a rather full featured program that this will be part of. But good to know regarding pause... Are you saying the PAUSE is abandoned if there is a timer interrupt? I had the impression from the documentation that the PAUSE picks up where it left off, as if the time away never happened.

I appreciate the concise re-write of my sample code Mike, It shows off your skill and experience.
same for the code insights and refinements, Pete. I've learned a heck of a lot more from you all than I did from AI.

ALSO, although my first post was in 2011, I'm listed as a "New Member". Feeling kinda self-conscious about that!
-Rick
 
Got it... the MAIN routine was really just a placeholder, I've got a rather full featured program that this will be part of. But good to know regarding pause... Are you saying the PAUSE is abandoned if there is a timer interrupt? I had the impression from the documentation that the PAUSE picks up where it left off, as if the time away never happened.

I appreciate the concise re-write of my sample code Mike, It shows off your skill and experience.
same for the code insights and refinements, Pete. I've learned a heck of a lot more from you all than I did from AI.

ALSO, although my first post was in 2011, I'm listed as a "New Member". Feeling kinda self-conscious about that!
-Rick
The Main: label is really a leftover from the early days of PICAXE, before the Do/Loop commands were introduced. You can omit this label if it is not referenced by a GoTo statement.

Yes, if a Pause is interrupted, execution returns to the command immediately following the pause statement.

I think you need to crack the 100 posts threshhold before you lose your training wheels New Member Status.
Edit: Perhaps that is not true - I see there are "Well-known members" with as few as 51 posts.
 
And I have 418 (now 419) posts, and I am still a "New Member" - after ten years. I remember raising this many years ago and Hippy said at the time that there was a problem with updating status - was it ever resolved, I wonder.
 
how create delays, for example for debouncing button presses, without using "pause"? i.e. that are compatible with interrupts....
my interrupts happen every .02 seconds....
would this work?
sub_delay: counter = delay_time
do while counter > 0
pause 1 ; Short 1 ms delay
dec counter ; Decrement counter
loop
return

-Rick
 
Last edited:
Hi,
... you may not need the "Pause 1" command.
Indeed. The basic loop may take significantly more than 1 ms, even without the Pause.

I've only tested M2 chips, but a simple delay: DEC counter : IF counter > 0 THEN delay loop should take close to 1 ms per iteration, because I have measured that the Conditional Jump (IF ... THEN {GOTO} ... ) executes in about 0.6 ms (at 8 MHz) and the DECrement around 0.3 ms. A problem with the Structured versions of the loop is that it's difficult to predict where or if the compiler will insert addition "GOTO"s. However, an indication can be obtained from the (additional) number of bytes reported by a Syntax Check:
Code:
#picaxe 20x2
#no_end
symbol counter = b1

do while counter > 0
    dec counter
loop                          ; ~11 bytes

delay:
   dec counter
   if counter > 0 then delay  ; ~8 bytes
And if you like surprises, try doing that with the SWAP and PWMDUTY instructions (or the special IF .. BIT .. instructions in X2s). :)

Cheers, Alan.
 
Last edited:
Back
Top