Menu

Interrupt on PORTBCHANGE

Help
Terry L
2009-10-15
2013-05-30
  • Terry L

    Terry L - 2009-10-15

    I need to monitor five pins simultaniosly for counting purposes. I would like to use interrupts.  I'm using a 16F876A which has five pins on PORTB which can be used as interrrupts.  I'm not sure how to implement this.  Any help on the synyax would be appreciated

     
  • Frank

    Frank - 2009-10-17

    Here's one possible way of writing it - depends a lot on your application though.

        'Chip settings
        #chip 16F876A, 4
        #config OSC = XT, PWRT = ON, WDT = OFF
       
        ' Setup interrupt service routines
        PortB_Last = 0xF0
        CounterFlags = 0
        on interrupt ExtInt0 call ISRPin0
        on interrupt PORTBChange call ISRPin4_7
       
        #define CountChangeFlag CounterFlags.0
        #define ClearCountFlag set CounterFlags.0 off
        #define SetCountFlag set CounterFlags.0 on
        #define CountersChanged CounterFlags.0 on
       
        ' Uncomment the next line if you want to enable weak pullups on PortB
        'set not_rbpu off
       
        ' Counters from 0 to 255 then rollover back to 0
        Count0 = 0
        Count4 = 0
        Count5 = 0
        Count6 = 0
        Count7 = 0
       
        ' You're main loop code
        do
        if CountersChanged then
        ClearCountFlag
        'do something with the counts
        end if
        ' Do other stuff
        loop
       
        ' Interrupt service routine for External Int0
        sub ISRPin0
        Count0 ++ ' Increase Count0 by 1 on every rising edge of INT0
        SetCountFlag
        end sub
       
        ' Interrupt service routine for PORTB Interrupt on Change
        ' Don't read Port B or use Read/Modify/Write instructions on PortB anywhere else
        ' in the program
        sub ISRPin4_7
        PortB_Now = PORTB & 0xF0 ' Read PortB and mask off unwanted bits
        PortB_Last = (!PortB_Last) & PortB_Now ' Bit change from 0 to 1 will produce a 1 output
        if PortB_Last <> 0 then SetCountFlag ' Any 1's indicate a rising edge so flag it
        if PortB_Last.4 on then Count4 ++ ' Test for rising edges between current and last -
        if PortB_Last.5 on then Count5 ++ ' PORTB reads and increment counters that need it
        if PortB_Last.6 on then Count6 ++
        if PortB_Last.7 on then Count7 ++
        PortB_Last = PortB_Now ' Save Port B pins for next change
        end sub

    The five counters are incremented on every rising edge of the respective pin.

    I've set a flag in the interrupt service routines to indicate to the main loop when the count has changed - you may not need that or you might want a flag for each counter. You could in that case have the counters incremented in your main loop and just set flags in the interrupts.

    You might also want to increase the size of the counters to words by using -

        dim Count0 as word

    Hope that gives you some ideas to work with.

    Frank

     
  • Terry L

    Terry L - 2009-10-19

    Thnaks,

    This gives me a lot to work with. Though I might have a problem in using the interrupts in my real world setting. 

    I'm monitoring a window with several laser emitters and detectors wired in series to count items as they pass through the window.  I'm finding the irregular shapes of the items are causing multiple input signals which are in turn giving me two, sometimes three signals on one item going through the window.

    I might have to abandon the interrrupt idea in order to smooth out the false signals by delaying the  reading of the inputs somehow.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.