PDA

View Full Version : Simple interrupt



Picstar
- 1st March 2012, 09:28
Hello All,
I know this subject has been covered many times but I just don't understand how to setup a simple external interrupt.
I am using portA on my 16f88 for outputs to a stepper motor. Port B is for my inputs. Can someone show me how to set portb.2 as the interrupt? I wish to push a button and apply 5v to this pin and have the program restart. Please show the handler code and where it should be placed in a program. Many thanks to anyone that can help.

Art
- 1st March 2012, 15:34
Much easier to use portb.0 interrupt for a single button.

Your program only has to restart and take no special action or remember nothing?
Then why an interrupt at all?

Why not check the button in your main routine and then reset variables and restart the main loop on the button push?

Better still, enable MCLR in config settings and use a reset button to reset the chip at hardware level.
Then all of your variables are cleared, and your program restarted for free (no code space used).

Picstar
- 1st March 2012, 18:58
Thanks for responding Art, the program that I am running goes into several long pauses, PAUSE 20000 for example. You have a simple solution that normally would work, I can insert a button on MCLR instead of having it permanently tied to 5v, but this is an automotive application and I need a reduced signal from the brake switch to restart the program. Here is my program, it is an attempt at a simple cruise control for an automobile. Please forgive my old style way of programming, but the program works, at least on the bench, I just need a way of restarting the program even when it is in those long pauses. Portb.0 can be changed so that it can be an interrupt, but I don't know how to code it. This simple program counts pulses from the Vehicle Speed Sensor, (VSS), stores it in B1, then counts again and stores the result in B2. Then it compares the two signals and makes adjustment to the throttle via a stepper motor. Any further help or ideals would very much be appreciated.

' Cruise Control Program
' Microcontroller used: 16F88
' 20 MHZ CRYSTAL fuse at hs
' Porta.0 - Porta.3 are stepper motor outputs
' Portb.0 is signal in from VSS (Vehicle Speed Sensor)
' Portb.1 is the signal to engage when 5v is applied. 10K tied to ground
' Portb.2 is tied to the brake switch. 10 k tied to ground
' Fine tuning may need to the "ti" and "ts" variables for vehicle,
' they also may need to be a "byte" instead of "word".


:START
clear
C var byte
ti var byte
ts var word
B1 var word
B2 VAR word
TRISa = %00000000
trisb = %00000111
portb = 0
porta = 0
c = 0
ti = 50 ' this is the pause between motor turns
ts = 2500 ' this changes how long of a count in milliseconds

INIT:
IF PORTb.1 = 1 THEN COUNTER1 'Press sw1 to engage
pause 100
GOTO INIT


COUNTER1:
if portb.0 = 1 then counter1 ' Wait till end of pulse
count portb.0 ,ts, B1 ' read pulses from vss for ? second
pause 500


CRUISE:
if portb.0 = 1 then Cruise ' Wait till end of pulse
count portb.0 ,ts, B2 ' get a second reading and store in B2
IF PORTb.2 = 1 THEN porta = 0:goto START ' BRAKE LIGHT SIGNAL, kill NOW
IF B2 > B1 THEN REVR
IF B2 < B1 THEN FORW
pause 20000 ' If B2 = B1 then pause
goto cruise


FORW:
PORTa = %00000011
PAUSe ti
PORTa = %00000110
PAUSE ti
PORTa = %00001100
PAUSE ti
PORTa = %00001001
PAUSE ti
C = C + 1
if c = 10 then portb = 0:goto start ' if no response after 10 sweeps then restart
pause 20000
GOTO cruise


REVR:
PORTa = %00001001
PAUSE ti
PORTa = %00001100
PAUSE ti
PORTa = %00000110
PAUSE ti
PORTa = %00000011
PAUSE ti
C = C - 1
pause 20000
GOTO cruise

SteveB
- 1st March 2012, 19:31
Here is another way to do the pause:


FOR I = 1 to 200
PAUSE 100
'Check for button press here
NEXT I

Art
- 1st March 2012, 23:36
I would normally use Steve's solution above, but you won't be able to check button pushes in the
2.5 second COUNT command that way.

Let's hope I remember everything, and I'm assuming registers for 16F877A are the same for your chip.

Near the start of your program, after any defines:



Define INTHAND _Brake ' Tell PBP Where the code starts on an interrupt
INTCON.4 = 1 'enable portb.0 interrupt
intoccured var byte


Then straight after that:



'************************************************* ***************
'* Name : ASM_INTS.PBP *
'* Author : Darrel Taylor *
'* Notice : Copyright (c) 2003 *
'* Date : JAN 4, 2003 *
'************************************************* ***************

wsave var byte $20 SYSTEM ' location for W if in bank0

' --- IF any of these three lines cause an error ?? Simply Comment them out to fix the problem ----
wsave1 var byte $A0 SYSTEM ' location for W if in bank1
wsave2 var byte $120 SYSTEM ' location for W if in bank2
wsave3 var byte $1A0 SYSTEM ' location for W if in bank3
' ------------------------------------------------------------------------------

ssave var byte BANK0 SYSTEM ' location for STATUS register
psave var byte BANK0 SYSTEM ' location for PCLATH register
fsave var byte BANK0 SYSTEM ' location for FSR register

Asm
INT_START macro
IF (CODE_SIZE <= 2)
movwf wsave ; copy W to wsave register
swapf STATUS,W ; swap status reg to be saved into W
clrf STATUS ; change to bank 0 regardless of current bank
movwf ssave ; save status reg to a bank 0 register
movf PCLATH,w ; move PCLATH reg to be saved into W reg
movwf psave ; save PCLATH reg to a bank 0 register
EndIF
movf FSR,W ; move FSR reg to be saved into W reg
movwf fsave ; save FSR reg to a bank 0 register
endm
EndAsm

Asm
INT_RETURN macro
MOVF fsave,W ; Restore the FSR reg
MOVWF FSR
Movf psave,w ; Restore the PCLATH reg
Movwf PCLATH
swapf ssave,w ; Restore the STATUS reg
movwf STATUS
swapf wsave,f
swapf wsave,w ; Restore W reg
Retfie ; Exit the interrupt routine
endm
EndAsm



Then this:



'*********************** ISR *****************************
Brake:
@ INT_START
'
R0save = R0 ; Save 2 PBP system vars that are used during
R1save = R1 ; the interrupt
'
IF INTCON.1 = 1 THEN 'handle portb.0 interrupt
INTCON.1 = 0 'clear portb.0 interrupt flag
goto overextint 'skip over timer interrupt handler
ENDIF '
'
overextint:
'
R1 = R1save ; Restore the PBP system vars
R0 = R0save
@ INT_RETURN ; Restore context and return from interrupt
'
'************************************************* ********


Now this would usually jump back to the point of execution it left from,
but you want to reset, and need not bother with resoring context,
so I'd create a routine that resets all vars and goes to the start of your program,
name it overextint: and delete the overextint label from this code.

If this works, thank Darrel, if it's broken, blame me!

Picstar
- 1st March 2012, 23:58
Wow, all of that for an interrupt huh. Maybe I should try some other way, all that code looks like Greek to me. Is all that crap really necessary?
I do appreciate any help but I hate assembly language , mainly because I don't know it. This all really leaves me scratching my head.

Art
- 2nd March 2012, 00:37
You don't have to know it.
You only need to change one label and never look at it again
(assuming I've got it right which is an assumption :P

Picstar
- 2nd March 2012, 01:36
I think Steve is on to something, most of the time program execution works great. It is when it goes into the long pauses, necessarily so, that I can't stop the program. Wait........Just tried it and it seems to work !!!
I put Steve's code in where there was the pause 20000 and it I pleased thus far in my tests on the bench. I noticed the other day while driving that unless your going uphill your are really giving your car very little throttle and therefore the stepper motor must do the same thing and make slow adjustsments and await the result and either adjust or continue to hold the throttle right where it is. This program will hopefully do that. I'm sure that it will need further tweaking. I just mounted my stepper motor and made an arm that is mechanically connected to my throttle valve. Next I am going to build the hardware for the project, (an enclosure for my electronics, mounting switches etc). My Kudos to Steve and Art. I will post my results in few days.

Thank You Thank You
Thank You Thank You

Art
- 2nd March 2012, 02:06
That method will work unless you brake while program execution is being held up by the COUNT command.
If you decided to brake while that command was starting out it's time duration, it would take 2.5 seconds
for your program to know you hit the brakes, and if you brake for less than 2.5 seconds at that time,
your program will never register it. Sub standard for an auto application.

Picstar
- 2nd March 2012, 02:27
True but at 20 mhz that 2.5 seconds seems more like 1 second, Also I can lower this to say 1000 and it still works well. A less than elegant solution, I know, but I am not a programmer. If I am unsatisfied with it on the road then I may try a relay attached to the brake switch that controls mclr. I just thought that in PicBasicPro you could enter a few simple lines of code like ON INTERRUPT GOTO START and it was as easy as pie, I guess not. Everyone says read the spec sheet on the chip, well I have downloaded them and I am still lost. I guess I am just to damn old to understand it.

Art
- 2nd March 2012, 02:52
At 20 Mhz, that 2.5 second delay is only going to be half a second... much more acceptable.
Didn't see that in your comments before.