PDA

View Full Version : Interrupt and Time Out



Tissy
- 15th March 2005, 01:40
I have a piece of working code using an Interrupt, whereby each time the button is pushed a variable is increased. This routine is going to be the first when the PIC is powered up and the rest of the code, relies on what the variable is set at.

I have also included an LED routine using PWM to visually indicate which stage the Variable is currently at (Variable is between 1 and 9).

How can i add a routine, where if the button is not pushed for 5 seconds, the code continues to the main routines etc. However, during this initial stage, if the button is pushed, the variable counts up (as already catered for) and 5 seconds starts all over again.

I'm sure it has to be added using a WHILE routine within the Interrupt Handlet routine, but i have tried to do it and failed.

Can anyone help please.

Here is the code:



' I/O definition
'
TRISB = %10000001 ' Set PORTB (0)INPUT (1-5)OUTPUTS


' Variable Definition
'
Switch VAR PORTB.0
Red VAR PORTB.1
Green VAR PORTB.2
Blue VAR PORTB.3



PushHowManyTimes VAR Byte
PWMVariable VAR Byte ' PWM Variable 1-9
PWMVariableTimeOut VAR Byte ' 5 second Timeout (100 loops of 50mS)
storedloop VAR Byte
onled VAR Byte


' register and interrupt definition
'
CMCON = 7 ' Disable analog comparator on PORTA... not needed as now
OPTION_REG=0 ' enable pull-up resistor on PORTb
' Interrupt on falling edge of RB0
INTCON = %10010000 ' Enable RB0 interrupt


On Interrupt Goto ProcedureSwitcher


' Variable initialisation
'
'PORTB = 0 ' Reset all outputs on PORTB
PushHowManyTimes = 0

'Main Procedure
'
MainProcedure:
Select Case PushHowManyTimes
case 1
Gosub resetleds
PWMVariable = 1
PWM BLue,1,100
Case 2
Gosub resetleds
PWMVariable = 2
PWM blue,25,100
Case 3
Gosub resetleds
PWMVariable = 3
PWM blue,255,100
Case 4
Gosub resetleds
PWMVariable = 4
PWM green,1,100
Case 5
Gosub resetleds
PWMVariable = 5
PWM green,25,100
Case 6
Gosub resetleds
PWMVariable = 6
PWM green,255,100
Case 7
Gosub resetleds
PWMVariable = 7
PWM red,1,100
Case 8
Gosub resetleds
PWMVariable = 8
PWM red,25,100
Case 9
Gosub resetleds
PWMVariable = 9
PWM red,255,100
End Select
Goto Mainprocedure


ResetLEDs:
Low PortB.1 ' reset output to PORTB
Low PortB.2
Low PortB.3
Low PortB.4
Low PortB.5
Return


' Interrupt handler stuff here
'
Disable ' Disable interrupts in handler
ProcedureSwitcher:
PushHowManytimes = PushHowManytimes + 1 ' Changing task
If PushHowManytimes = 10 Then PushHowManytimes=1

Here:
While SWITCH = 0 ' waiting until
wend ' push-button is release
pause 100 ' debounce time
If switch = 0 then here
INTCON.1=0 ' reset RB0 interrupt flag
Resume ' Return to main program

Enable ' Enable interrupts after
' handler


If anyone can also suggest a better way of visually representing at which stage the variable is set at (1-9) using 3 LEDs, then please do.

Many thanks,

Steve

mister_e
- 15th March 2005, 22:23
try this


' I/O definition
'
TRISB = %10000001 ' Set PORTB (0)INPUT (1-5)OUTPUTS


' Variable Definition
'
Switch VAR PORTB.0
Red VAR PORTB.1
Green VAR PORTB.2
Blue VAR PORTB.3



PushHowManyTimes VAR Byte
PWMVariable VAR Byte ' PWM Variable 1-9
PWMVariableTimeOut VAR Byte ' 5 second Timeout (100 loops of 50mS)
storedloop VAR Byte
onled VAR Byte
DelayVar VAR WORD

' register and interrupt definition
'
CMCON = 7 ' Disable analog comparator on PORTA... not needed as now
OPTION_REG=0 ' enable pull-up resistor on PORTb
' Interrupt on falling edge of RB0
INTCON = %10010000 ' Enable RB0 interrupt


On Interrupt Goto ProcedureSwitcher


' Variable initialisation
'
'PORTB = 0 ' Reset all outputs on PORTB
PushHowManyTimes = 0
DelayVar = 0

'Main Procedure
'
MainProcedure:
Select Case PushHowManyTimes
case 1
Gosub resetleds
PWMVariable = 1
PWM BLue,1,100
Case 2
Gosub resetleds
PWMVariable = 2
PWM blue,25,100
Case 3
Gosub resetleds
PWMVariable = 3
PWM blue,255,100
Case 4
Gosub resetleds
PWMVariable = 4
PWM green,1,100
Case 5
Gosub resetleds
PWMVariable = 5
PWM green,25,100
Case 6
Gosub resetleds
PWMVariable = 6
PWM green,255,100
Case 7
Gosub resetleds
PWMVariable = 7
PWM red,1,100
Case 8
Gosub resetleds
PWMVariable = 8
PWM red,25,100
Case 9
Gosub resetleds
PWMVariable = 9
PWM red,255,100
End Select
pauseus 100
delayvar=delayvar + 1
if delayvar = 50000 then
delayvar=0
PushHowManyTimes=PushHowManytimes+1
If PushHowManyTimes=10 then PushHowManytimes=1
endif
Goto Mainprocedure


ResetLEDs:
Low PortB.1 ' reset output to PORTB
Low PortB.2
Low PortB.3
Low PortB.4
Low PortB.5
Return


' Interrupt handler stuff here
'
Disable ' Disable interrupts in handler
ProcedureSwitcher:
PushHowManytimes = PushHowManytimes + 1 ' Changing task
If PushHowManytimes = 10 Then PushHowManytimes=1

Here:
While SWITCH = 0 ' waiting until
wend ' push-button is release
pause 100 ' debounce time
If switch = 0 then here
INTCON.1=0 ' reset RB0 interrupt flag
DelayVar= 0
Resume ' Return to main program

Enable ' Enable interrupts after
' handler

Tissy
- 15th March 2005, 22:48
Affraid not Steve, tried this and still no luck.

It still keeps with the main routine of watching the switch input and steps the LED accordingly. There seems to be no 5 second time-out.

I need it so that if no Interrupt is detected within 5 seconds of the last switch input it goes to the next stage of the code, whatever that might be ! So when the 5 seconds has been reached for the purposes of this code, it might be worth representing this as HIGH RED. That way i know the code works. If an Interrupt is received during the 5 seconds, then the 5 second timer starts again, and so on.

Any other ideas?

Cheers,

Steve

Bruce
- 16th March 2005, 01:10
Just setup Timer1 with a variable to count Timer1 over-flows.
No need for interrupts on the timer, just monitor TMR1IF overflow
interrupt flag bit, and let Timer1 do everything for you in the
background.

This gives you roughly 5 seconds at 20MHz.


DEFINE OSC 20

' I/O definition
'
TRISB = %10000001 ' Set PORTB (0)INPUT (1-5)OUTPUTS
T1CON = %00110000 ' Timer1 1:8 prescale. Timer1 off

' Variable Definition
'
Switch VAR PORTB.0
Red VAR PORTB.1
Green VAR PORTB.2
Blue VAR PORTB.3



PushHowManyTimes VAR Byte
PWMVariable VAR Byte ' PWM Variable 1-9
PWMVariableTimeOut VAR Byte ' 5 second Timeout (100 loops of 50mS)
storedloop VAR Byte
onled VAR Byte

Timer VAR BYTE ' Holds timer ticks. 1 tick = 65,536*Tosc*prescale
Timer = 0 ' Clear on start

' register and interrupt definition
'
CMCON = 7 ' Disable analog comparator on PORTA... not needed as now
OPTION_REG=0 ' enable pull-up resistor on PORTb
' Interrupt on falling edge of RB0
INTCON = %10010000 ' Enable RB0 interrupt

PORTC.0=1 ' NOTE: Just for visual test | LED blinking every 5 S
TRISC.0 = 0

On Interrupt Goto ProcedureSwitcher

' Variable initialisation
'
'PORTB = 0 ' Reset all outputs on PORTB
PushHowManyTimes = 0

ReStart:
TMR1H = 0
TMR1L = 0 ' Clear time counts before Timer1 re-start
PIR1.0 = 0 ' CLear over-flow flag before enable
T1CON.0 = 1 ' Turn Timer1 back on before entry into MainProcedure

'Main Procedure

MainProcedure:
Select Case PushHowManyTimes
case 1
Gosub resetleds
PWMVariable = 1
PWM BLue,1,100
Case 2
Gosub resetleds
PWMVariable = 2
PWM blue,25,100
Case 3
Gosub resetleds
PWMVariable = 3
PWM blue,255,100
Case 4
Gosub resetleds
PWMVariable = 4
PWM green,1,100
Case 5
Gosub resetleds
PWMVariable = 5
PWM green,25,100
Case 6
Gosub resetleds
PWMVariable = 6
PWM green,255,100
Case 7
Gosub resetleds
PWMVariable = 7
PWM red,1,100
Case 8
Gosub resetleds
PWMVariable = 8
PWM red,25,100
Case 9
Gosub resetleds
PWMVariable = 9
PWM red,255,100
End Select

' IF PIR1.0 = 1 TMR1 register overflowed (must be cleared in software)
IF PIR1.0 THEN ' IF Timer1 has over-flowed then
Timer = Timer + 1 ' Increment Timer variable
PIR1.0 = 0 ' Clear over-flow/int flag
' @20MHz 200nS * 65,536 * 8 = 0.1048576 seconds per over-flow
' 0.1048576 * 48 = ~5.033 seconds before jump to NextStage
IF Timer >= 48 THEN NextStage
ENDIF
Goto Mainprocedure


ResetLEDs:
Low PortB.1 ' reset output to PORTB
Low PortB.2
Low PortB.3
Low PortB.4
Low PortB.5
Return

NextStage: ' Dont really know what you need here. Just a visual test
' T1CON.0 = 0 ' Turn off Timer1 if you need to here
Timer = 0 ' Clear Timer var on entry here
' TMR1H = 0
' TMR1L = 0 ' CLear timer count registers as required
PORTC.0 = PORTC.0 ^ 1 ' Toggle LED for test
' Do something here, etc,,
GOTO ReStart ' When you're ready to start all over

' Interrupt handler stuff here
'
Disable ' Disable interrupts in handler
ProcedureSwitcher:
PushHowManytimes = PushHowManytimes + 1 ' Changing task
If PushHowManytimes = 10 Then PushHowManytimes=1

Here:
While SWITCH = 0 ' waiting until
wend ' push-button is release
pause 100 ' debounce time
If switch = 0 then here
PIR1.0 = 0 ' Clear Timer1 over-flow flag
Timer = 0 ' Clear Timer counts before return
INTCON.1=0 ' reset RB0 interrupt flag
Resume ' Return to main program

Enable ' Enable interrupts after
' handler

END