PDA

View Full Version : asm interrupts



Macgman2000
- 16th September 2008, 23:01
Ok,
I have been trying this for the last 2hrs. I think I am so frustrated that I am missing the obvious.

I just want a free running 30ms interrupt using timer1. For whatever reason I have tried loading the timer with everything under the sun and no interrupt.....ggggrrrr. Someone please shed some light!

' chipbody: PIC16F877A

INCLUDE "Modedefs.Bas"
@ device HS_OSC, LVP_OFF, WDT_OFF
; @ Device pic16F877A, HS_OSC, BOD_OFF, PWRT_ON, WDT_ON, PROTECT_OFF

DEFINE OSC 20
' Set Debugin pin port
DEFINE DEBUGIN_REG PORTC
DEFINE DEBUG_BAUD 4800
' Set Debugin pin bit
DEFINE DEBUGIN_BIT 7
' Set Debugin mode: 0 = true, 1 = inverted
DEFINE DEBUGIN_MODE 1

DEFINE INTHAND myint

' Configure internal registers


TRISD = %00000000
TRISC = %00000000


' Initialize Interrupts
TMR1L = $FE
TMR1H = $FE
T1CON = %00000001 ' $01 Turn on Timer1, prescaler = 1
INTCON = %10000000 ' Enable global interrupts,
PIE1 = %00000001 ' Enable TMR1 overflow interrupt

BrianT
- 17th September 2008, 00:04
I use a 'soft' interrupt by clearing the PIR1.0 register and preloading TMR1 to a value that gives me 24 mSecs. I start the timer routine and in my software I frequently check if PIR1.0 has been set by the TMR1 overflow. Being a code based 'check it when you can' the timing is a little flakey but it works fine in my application. I wanted to eliminate interrupt based code as far as possible since the overall timing can then get very hard to manage if interrupts get nested.

I do run SWDTEN with a 58 mSec hard reset to keep things in line if the soft check of PIR1.0 should not work as expected.

This is a snip from PIC16F88 code.




MainLoop:
'Housekeeping
clearwdt
WDTCON = %00001001 ' invoke s/w WDT, 58 mSec timeout,
' WDTCON = %00001010 ' has a recovery time about 110 mSec.
OPTION_REG = %10001010 ' No wpu, prescaler assigned to WDT & /4
INTCON = %00000000 ' disable all interrupts
ANSEL = %00000000 ' all digital
CMCON = %00000111 ' Comparators OFF to allow inputs on pins
ADCON0 = %00000000
ADCON1 = %00000000
PIE1 = %00000001 ' enable TMR1 overflow interrupt
PIE2 = %00000000
PIR2 = %00000000
TRISB = %11001111

T1CON = %00100000 ' stop TMR1
PIR1.0 = 0 ' clear bit 0 TMR1 interrupt flag
TMR1H = $8C
TMR1L = $A0 ' loads 36000 - gives 24 mS on CRO
T1CON = %00100001 ' start TMR1

FindSync:
'high txd
' The exits from this loop are via TimeOut or 850 loops of steady '1'
' Noise should keep the program stuck in this block until timeout
' but it still finds occasional sync pattterns in pure noise

if pir1.0 = 1 then timeout
if radioppm = 0 then findsync

' RadioPPM has gone high here - check that it stays high
' A byte variable gives a loop time about 2.7 uSecs.
' A word variable loops in about 9.2 uS so there are less chances
' to detect a low spike during the sync period.

for a = 0 to 255 ' measured at 2300 uS
if radioppm = 0 then findsync ' noise or channel pulse
if pir1.0 = 1 then timeout ' been here too long
next a
for a = 0 to 255
if radioppm = 0 then findsync ' noise or channel pulse
if pir1.0 = 1 then timeout ' been here too long
next a
for a = 0 to 255
if radioppm = 0 then findsync ' noise or channel pulse
if pir1.0 = 1 then timeout ' been here too long
next a
for a = 0 to 200 '100
if radioppm = 0 then findsync ' noise or channel pulse
if pir1.0 = 1 then timeout ' been here too long
next a
if badch > 2 then timeout
goto sendpacket ' 250 contiguous 1's - sync or stuck high

TimeOut: ' arrive here if TMR1 overflow is detected
' OR we were sent here by bad receive frame
high txd 'low txd
if pir1.0 = 0 then timeout ' wait until timer overflows
'Strategy
' The failsafe values are predetermined by the FailCh[n] array.
' When a failsafe state is detected, the system slowly migrates from
' LastCh[n] count to the FailCh[n] count over a number of frames
' using FailLimit as the maximum increment or decrement
high p1led
failch[0] = 0 ' throttle - cut to zero
failch[1] = 125 ' aileron - centralise
failch[2] = 125 ' elevator - centralise
failch[3] = 165 ' rudder - a small left rudder
failch[4] = 125 ' gear - normally 30 or 220. 125 = failsafe
failch[5] = 125 ' Aux 1
failch[6] = 125 ' Aux 2
failch[7] = 125 ' Aux 3



HTH
BrianT

Macgman2000
- 17th September 2008, 01:58
I dropped in a segment of your configuration setup and still not even a simple toggle of an I/O port. I don't see the problem


@ device HS_OSC, LVP_OFF, WDT_OFF
; @ Device pic16F877A, HS_OSC, BOD_OFF, PWRT_ON, WDT_ON, PROTECT_OFF

DEFINE OSC 20
' Set Debugin pin port
DEFINE DEBUGIN_REG PORTC
DEFINE DEBUG_BAUD 4800
' Set Debugin pin bit
DEFINE DEBUGIN_BIT 7
' Set Debugin mode: 0 = true, 1 = inverted
DEFINE DEBUGIN_MODE 1

DEFINE INTHAND myint

' Configure internal registers


TRISD = %00000000
TRISC = %00000000
CMCON = %00000111 ' Comparators OFF to allow inputs on pins
PIE1 = %00000001 ' enable TMR1 overflow interrupt
PIE2 = %00000000
PIR2 = %00000000


T1CON = %00100000 ' stop TMR1
PIR1.0 = 0 ' clear bit 0 TMR1 interrupt flag
TMR1H = $8C
TMR1L = $A0 ' loads 36000 - gives 24 mS on CRO
T1CON = %00100001 ' start TMR1



wsave VAR BYTE $70 system ' Saves W
ssave VAR BYTE bank0 system ' Saves STATUS
psave VAR BYTE bank0 system ' Saves PCLATH
fsave VAR BYTE bank0 system ' Saves FSR


servo1 VAR byte bank0
servo2 VAR byte bank0
servo3 VAR byte bank0
servo4 VAR byte bank0

chksum1 var byte bank0
chksum var byte bank0

sv01 var byte bank0
sv02 var byte bank0
sv03 var byte bank0
sv04 var byte bank0

portc.0=0
goto mainloop


asm

; Save W, STATUS and PCLATH registers, if not done previously
myint movwf wsave
swapf STATUS, W
clrf STATUS
movwf ssave
movf PCLATH, W
movwf psave



; Save and restore FSR and any other registers used

bCf portc.0

movf 127,w
movwf _servo1
movwf _servo2
movwf _servo3
movwf _servo4

; Restore saved registers
movf psave, W
movwf PCLATH
swapf ssave, W
movwf STATUS
swapf wsave, F
swapf wsave, W

retfie ; Return from interrupt

endasm



mainloop:
pause 100
portc.0=1
goto mainloop

skimask
- 17th September 2008, 03:43
I don't see anything clearing interrupt flag!

Macgman2000
- 17th September 2008, 04:21
I do clear it at the top. Do I have to clear it while inside the interrupt routine?

skimask
- 17th September 2008, 04:24
I do clear it at the top. Do I have to clear it while inside the interrupt routine?

Where do you clear the Timer 1 interrupt flag at the top?

Refer to the PIC16F877A datasheet, DS39582B-page 26

Archangel
- 17th September 2008, 04:25
I do clear it at the top. Do I have to clear it while inside the interrupt routine?
When interrupt fires it sets a flag bit and will not fire again until reset in ISR, that's The word according to my 3 bottles of Miller High Life anyway :D

Macgman2000
- 17th September 2008, 04:29
I clear it here

T1CON = %00100000 ' stop TMR1
PIR1.0 = 0 ' clear bit 0 TMR1 interrupt flag
TMR1H = $8C
TMR1L = $A0 ' loads 36000 - gives 24 mS on CRO
T1CON = %00100001 ' start TMR1

joe, I think you answered my question. It does have to be in the ISR.
So syntax..... bcf PIR1.0m will this work?

skimask
- 17th September 2008, 04:29
When interrupt fires it sets a flag bit and will not fire again until reset in ISR, that's The word according to my 3 bottles of Miller High Life anyway :D
Almost, but I think the wording should be 'will continuously fire'...in other words, if the flag stays set (or clear as the case might be), the program returns to the main loop and gets interrupted again straight away.
But then again...I would never doubt the word of a select beverage...:D

skimask
- 17th September 2008, 04:30
You clear it at the beginning, find...but it's likely not set at the beginning...
What happens when the flag gets set during program execution?
Refer to the datasheet!

Macgman2000
- 18th September 2008, 04:45
Got it working...I kept forgetting PIR1.0 and I was not re-loading tmr1H and tmr1L where needed in the code.

Thanks all for the help!

skimask
- 18th September 2008, 05:00
Got it working...I kept forgetting PIR1.0 and I was not re-loading tmr1H and tmr1L where needed in the code.

Thanks all for the help!

You got it!

Check this:

http://www.picbasic.co.uk/forum/showthread.php?t=3251&highlight=instant+interrupts

A bit of a steep learning curve, but once you get the hang of it, they're one of the better things since sliced bread... Makes dealing with 'true' interrupts a LOT easier...