Difficulty toggling LED with TMR1 overflow interrupt
Hello all. I cannot persuade TMR1 interrupt to toggle an LED. I tried the "ON INTERRUPT...." method and that works fine, toggling the LED 3 or 4 times a second. But I cannot work out how to do this manually by polling the TMR1IF (PIR1.0) flag. I wonder if anyone has any ideas? I have spend hours reading through threads (including the Olympic Timer example thread) but to no avail. Presumably the solution is simple, but I can't work out what it is.
Many thanks in advance.
Jonathan.
Code:
define OSC 20
TRISB = %11101111 ' PORTB.4 output
led var PORTB.4
led = 0
INTCON = 0
PIR1 = $00 ' clear interupt flags
TMR1H = 0
TMR1L = 0
T1CON = %00110001 ' TMR1 on, prescaler=1:8, clock=(Fosc/4)
INTCON = $C0 ' Enable global and peripheral interupts
PIE1 = $01 ' Enable TMR1 overflow interrupt
main:
if PIR1.0 then
led = not led
TMR1H = 0 ' reset timer1
TMR1L = 0
PIR1 = $00 ' clear interrupt flags
endif
goto main
end
Re: Difficulty toggling LED with TMR1 overflow interrupt
After a few more hours of sifting through forums, I found the answer in this very forum, in Bruce's post (#2): http://www.picbasic.co.uk/forum/show...2824#post42824
Quote:
If you enable interrupts, then you need an interrupt handler. If you prefer just to monitor the
timer1 overflow flag, then disable global interrupts.
I'm not sure why this would be the case, but I'll work it out!
Re: Difficulty toggling LED with TMR1 overflow interrupt - SOLUTION
For reference, here is the solution. The LED is toggled once every second by monitoring the TMR1 interrupt flag. 16F88.
Jonathan.
Code:
define OSC 20
' SET UP PORTS
TRISB = 101111 ' PORTB.4 output
' SET UP TMR1
T1CON = 0 ' prescaler=1:1, clock=(Fosc/4)
PIE1.0 = 1 ' Enable TMR1 overflow interrupt
INTCON.6 = 0 ' Disable peripheral interrupts
INTCON.7 = 0 ' Disable global interrupts (disable GIE and PEIE because there
' is no ISR, polling PIR1.0 (TMR1IF) manually instead)
' DECLARE VARIABLES
led var PORTB.4
overflow_counter var word
tmr1_preload var word
' INIT PROGRAMME
init:
led = 0
overflow_counter = 0
tmr1_preload = 15536 ' 15536 for overflow every 10 ms
TMR1H = tmr1_preload.highbyte
TMR1L = tmr1_preload.lowbyte
T1CON.0 = 1 ' Start TMR1
main:
if PIR1.0 = 1 then ' if TMR1IF is set
overflow_counter = overflow_counter + 1
if overflow_counter = 100 then ' 100 overflows = 1 second
led = not led ' toggle led
overflow_counter = 0 ' reset overflow counter
endif
TMR1H = tmr1_preload.highbyte ' reset TMR1 with preload value
TMR1L = tmr1_preload.lowbyte
PIR1.0 = 0 ' clear TMR1IF
endif
goto main
end
Re: Difficulty toggling LED with TMR1 overflow interrupt
If you enable interrupts the code will jump to the interrupt vector whenenver an interrupt occurs. If you don't have a interrupt service routine at that location (or a jump TO an interrupt service routine) it won't work properly. The interrupt flags (like the TMR1IF) will get set whenever the cause of the particular interrupt happens/occurs but an actual jump to the interrupt vector will only occur if interrupts are enabled.
So, if you're actually going to use interrupts you need them enabled AND have an interrupt service routine. If you're just going to poll the interrupt flag then you can't have that particullar interrupt enabled.
Re: Difficulty toggling LED with TMR1 overflow interrupt
Thank you for the explanation. Now I understand. From the 16F88 datasheet: "If the global interrupt is enabled, the program will branch to the interrupt vector (0004h)."