PDA

View Full Version : Interrupt/timer not really interrupting...



Tom Gonser
- 10th May 2005, 15:28
PIC 18F2525

I have my first interrupt and timer routine working as part of a menu system, and it feels over my head.. The system loop has several subroutines, and it chooses which to do based on some flags set in the menu interrupt.

The problem is two fold:

1. When I hit the button (b0) to interrupt to my menu handler, it jumps to the menu handler fine. However, when selecting a new menu, the code returns back whatever routine it WAS just in to finish that BEFORE it will jump to the next one. I need it to really INTERRUPT -- ie if I start a download routine, and then click the button to choose a different menu, I want it NOT to then download, but to just skip to the next routine. (Below)

2. Timeout - if I click a menu select button (bo), then never click the menu submit button (b1), I want it to 'time out' and keep doing what it was doing before. I have a timout routine I got from this forum, but I don't think it is working right as it never does this. (Below)

3. Crashing - this code watches a modem line for activity, and if it sees it, it starts reading. If it does NOT see it, it just loops thorugh a routine that says 'No data'.. and then returns to the top of the code.

basically :

getdata:
Serin2 Cpinin,84,1000,nodata,[wait($02,$47), STR SSMAX\34]
return

'*******[No Data from modem] ***********
nodata:
Pause 30
LCDout $fe, L2, " Searching"
LCDout $fe, L3, " No TracIDs Found"
LCDout $fe, L4, " Check Tranmsitters"
pause 50
goto main

Then main ends up calling 'get data' again. This is supposed to loop, but eventually, the code hangs and has to be power cycled to come back to life..

I am thinking this might have something to do with my timer..

TG

-- some of the code follows ----

ADCON0 = %00110000 ' turn off - select port AN12 (nothing)
ADCON1 = %00001111 ' turn portA to digital I/O (same as dec 15)

CMCON = $07 ' turn off
HLVDCON = %00000000 ' turn off
CVRCON = $00000000 ' turn off

SSPCON1 = %11011100 ' supposed to be turning on I2C
SSPCON2 = %01111000 ' supposed to be turning on I2C

INTCON = %11110000 ' TG guess at 2525 interrups for all INT pins
INTCON2= %01110100 ' rising edge of INT0,1,2 RB0,1,2
RCON = %10000000 ' no priority interrups

T1CON = %11000000 'Timer1 1:1 prescale.
T0CON = 1


----------------------------------------------------
On Interrupt Goto INT_handle

Smenu = 0

ReStart:
TMR1H = 0 ' Clear time counts before Timer1 re-start
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:
Main program stuff happens here

' --------- Interrupt Handler in main loop---------------
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 >= 20 and Mnu = 1 THEN NextStage
ENDIF
goto Main
-----------------------------------------------------

NextStage: ' timer routine
Mnu = 0
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
LCDout $fe, 1
LCDout $fe, 2
LCDout $fe, L2, "Timer Ran Out"
pause 1000
GOTO ReStart ' When you're ready to start all over

' Interrupt handler stuff here

Disable ' Disable interrupts in handler
INT_handle:
Timer = 0 ' Clear Timer var on entry here
TMR1H = 0
TMR1L = 0 ' CLear timer count registers as required
Selectit=0
While selectit = 0
Mnu=1 ' we are in the menu system
If Mmenu = 0 then
While Mmenu = 0 ' waiting until
wend ' push-button is release
pause 100 ' debounce time
Bmenu=Bmenu+1
endif ' bo pressed – go to next menu

Select Case Bmenu
Case 0
LCDout $fe, 1
LCDout $fe, 2
LCDout $fe, L2, " Menu 0: Cycle Menu"
pause 10
Case 1
LCDout $fe, 1
LCDout $fe, 2
LCDout $fe, L2, " Menu 1: Sensors"
pause 10
... etc ...


If Smenu = 0 then ' select button is pressed
While MMenu = 0 ' waiting until
wend ' push-button is release
pause 100 ' debounce time
selectit = 1 ' b1 pressed get out of the loop!
endif
Wend

Mnu=0 ' turn off menu flag

Here:
While MMenu = 0 ' waiting until
wend ' push-button is release
pause 100 ' debounce time
If MMenu = 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
----------------------------------------------------------------------

Tom Gonser
- 22nd May 2005, 22:05
Well with 54 reads over the past few weeks, and no replies, there must be some interest in a menu system! My code has a weak interrupt system I am trying to improve, and NOW I need to add something else -- a sub-menu.. Well, it does not work.

I have two buttons - I want to use button 0 as the interrupt from running to go to the menu system. Keep pushing it and cycle through the menus. Find the one you want, and hit Button 1. This works at a high level now. Problem is one of the menus I need to display some options and use these buttons to select THEM too.. In this case, I don't need an interrupt, just to read 0 or 1 from those pins. The following code displays OK, but the buttons do nothing..

I could use a pointer to a template about how folks use buttons for menus.. This is not working..

LCDsetting:
' make the LCD able to program the unit without the PC
I2Cread DPIN, CPIN, Chip1, wpt_loc, [set_wpt] ' waypoint flag storage 0 or 1
I2Cread DPIN, CPIN, Chip1, Pass_loc, [passthru] ' waypoint flag storage 0 ir 1
I2Cread DPIN, CPIN, Chip1, D_baud_loc, [D_baud] ' store address pointer 84 for 9600, 6 for 38400
I2Cread DPIN, CPIN, Chip1, W_baud_loc, [wptbd] ' store address pointer 84 for 9600, 188 for 4800
I2Cread DPIN, CPIN, Chip1, wpt_loc,[set_wpt] ' waypoint flag storage 0 or 1

LCDout $fe, 1
LCDout $fe, 2
LCDout $fe, L1, " Unit Set-up "
LCDout $fe, L2+2,"Waypoint:"
Select case Set_wpt
Case 0
LCDout $fe, L2+13,"off"
Case else
LCDout $fe, L2+13,"Err"
end select
Select Case Wptbd
Case 188
LCDout $fe, L2+13,"4800"
Case 84
LCDout $fe, L2+13,"9600"
Case else
LCDout $fe, L2+13,"Err"
end select
LCDout $fe, L3+2,"Passthru:"
Select case passthru
Case 0
LCDout $fe, L3+13,"off"
Case 1
LCDout $fe, L3+13,"9600"
Case else
LCDout $fe, L3+13,"Err"
end select

LCDout $fe, L4+2,"Download:"
Select Case D_Baud
Case 84
LCDout $fe, L4+13,"9600"
Case 6
LCDout $fe, L4+13,"38,400"
Case else
LCDout $fe, L4+13,"Err"
end select

' menu changes
tempb = 1 ' start with 1
If PORTB.0 = 0 then 'first button is pressed - select category
tempb=tempb+1
if tempb > 3 then tempb = 1
endif
Select case tempb
case 1 ' gpsbaudrate item
LCDout $fe, L2, "X" ' indicate selected item on lcd
LCDout $fe, L3, " " ' indicate selected item
LCDout $fe, L4, " " ' indicate selected item
Case 2 ' passthru mode item
LCDout $fe, L2, " " ' indicate selected item
LCDout $fe, L3, "X" ' indicate selected item
LCDout $fe, L4, " " ' indicate selected item
Case 3 ' download baudrate item
LCDout $fe, L2, " " ' indicate selected item
LCDout $fe, L3, " " ' indicate selected item
LCDout $fe, L4, "X" ' indicate selected item
end select

while PORTB.0 = 1 ' as long as B0 is not pressed to make us move to another line item above:
If tempb = 1 then
select case wptbd 'translate default baudrate
case 188
tempc = 1
case 84
tempc = 2
case 0
tempc = 3
end select
select case tempc
case 1
LCDout $fe, L2+13, "4800" ' display setting
wptbd=188
Set_wpt=1
passthru=0
Case 2
LCDout $fe, L2+13, "9600" ' display setting
wptbd=84
set_wpt=1
passthru=0
Case 0
LCDout $fe, L2+13, "off" ' display setting
wptbd=84
set_wpt=0
Case else
LCDout $fe, L2+13, "Err" ' display setting
end select

If PORTB.1 = 0 then ' second button is pressed - increment options at this level
tempc=tempc+1
if tempc > 3 then tempc = 1
endif
endif

If tempb = 2 then ' passthru mode
select case passthru 'translate default passthru
case 0
tempc = 1
case 1
tempc = 2
end select

select case tempc
case 1
LCDout $fe, L2+13, "On 9600" ' display setting
wptbd=188
passthru=1
set_wpt=0
Case 2
LCDout $fe, L2+13, "off" ' display setting
passthru=0
end select


If PORTB.1 = 0 then ' second button is pressed - increment options at this level
tempc=tempc+1
if tempc > 2 then tempc = 1
endif

endif

If tempb = 3 then ' download baudrate

select case D_baud 'translate default dnlspeed
case 84
tempc = 1
case 6
tempc = 2
end select

select case tempc
case 1
LCDout $fe, L1+13, "9600" ' display setting
D_Baud=84

Case 2
LCDout $fe, L1+13, "38400" ' display setting
D_Baud=6

end select
If PORTB.1 = 0 then ' second button is pressed - increment options at this level
tempc=tempc+1
if tempc > 2 then tempc = 1
endif
endif
wend
Return