Simple interrupt


Closed Thread
Results 1 to 11 of 11

Hybrid View

  1. #1
    Join Date
    Aug 2008
    Posts
    42

    Default Simple interrupt

    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.

  2. #2
    Join Date
    Aug 2003
    Posts
    985


    Did you find this post helpful? Yes | No

    Default Re: Simple interrupt

    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).

  3. #3
    Join Date
    Aug 2008
    Posts
    42


    Did you find this post helpful? Yes | No

    Default Re: Simple interrupt

    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

  4. #4
    Join Date
    May 2006
    Location
    Del Rio, TX, USA
    Posts
    343


    Did you find this post helpful? Yes | No

    Default Re: Simple interrupt

    Here is another way to do the pause:


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

  5. #5
    Join Date
    Aug 2003
    Posts
    985


    Did you find this post helpful? Yes | No

    Default Re: Simple interrupt

    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:

    Code:
    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:

    Code:
    '****************************************************************
    '*  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:

    Code:
    '*********************** 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!
    Last edited by Art; - 1st March 2012 at 23:38.

  6. #6
    Join Date
    Aug 2008
    Posts
    42


    Did you find this post helpful? Yes | No

    Default Re: Simple interrupt

    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.

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts