I needed a warning LED to light up when there was a problem, and I needed to indicate the nature of the problem with the number of flashes. I couldn't just let the program sit around while it flashed, I needed it to run in the background.
And since people who count flashes expect nice, even-spaced flashes, I couldn't just rely on program loops (at least in my case, where some loops take longer than others).
So here is the result. I uses Timer 1 to flash a led at a 1 Hz rate. Just give the variable "MakeFlash" a number, and it will flash ON that many times, then hold the LED ON for 5 periods, and start all over again. If you clear MakeFlash, the flashing stops.
Since it is interrupt-driven, it runs entirely in the background.
Let us hope it formats better on the forum than it does on my screen.
Warn VAR PORTD.5 MakeFlash VAR BYTE DoFlash VAR BYTE CounterF VAR WORD T1Counter VAR BYTE FlashFlag VAR BIT WaitCounter VAR BYTE InFlashRoutine VAR BIT CR CON 13 LF CON 10 ONN CON 1 OFFF CON 0 CounterF =0 T1Counter = 0 FlashFlag = 0 WaitCounter = 0 inFlashRoutine = 0 ;----------------- ---------------------------- INCLUDE "DT_INTS-18.bas" ; Base Interrupt System INCLUDE "ReEnterPBP-18.bas" ; Include if using PBP interrupts ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler TMR1_INT, _FlashLEDs, PBP, yes endm INT_CREATE ENDASM '------------------------------- GOTO OverInt FlashLEDs: PIR1.0 = 0 ; Clear INT flag IF !InFlashRoutine THEN IF MakeFlash THEN DoFlash = MakeFlash + 1 ; Transfer contents to working varible that the INT can change InFlashRoutine = 1 ; Let system know that we are actively flashing now. ; The MakeFlash "+1" is used if you don't count the HOLD time as a flash ELSE Warn = OFFF ENDIF ENDIF T1Counter = T1Counter + 1 ; Effectively divides interrupt period by 10 IF T1Counter < 10 THEN GOTO EndRoutine T1Counter = 0 ; Clear interrupt counter IF DoFlash > 0 THEN ; Should we still be flashing? FlashFlag = 1 ; Set once we enter routine so we know we were previously flashing IF Warn = OFFF THEN Warn = ONN DoFlash = DoFlash - 1 ; Keep track of the times we have flashed GOTO EndRoutine ELSE Warn = OFFF ; Turn it off ENDIF ELSE IF FlashFlag = 1 THEN ; When we are done flashing, we need to hold the LED ON for a period ; so mere mortals can determint the difference Warn = ONN WaitCounter = WaitCounter + 1 IF WaitCounter > 5 THEN FlashFlag = 0 WaitCounter = 0 InFlashRoutine = 0 ENDIF ELSE WaitCounter = 0 ; Just to make certain it gets cleared ENDIF ENDIF EndRoutine: @ INT_ENABLE TMR1_INT @ INT_RETURN ;--------------------------------------------------------- OverInt: HSEROUT ["Hello World"] TMR1H = 0 TMR1L = 0 PIR1.0 = 0 T1CON = %00110001 ; Turns it on, /8 prescaler, load 8 bits at a time @ INT_ENABLE TMR1_INT MakeFlash = 5 ; Just for test Top: PAUSE 20000 MakeFlash = 0 GOTO Top
Re: K42 and Timer Interrupts
Thanks for the explanation.
Ioannis - 28th April 2025, 19:28I misinterpreted these paragraphs. My understanding was to have ASYNC cleared and use Fosc/4.
Ioannis