PORTB + PORTC Interrupt-On-Change


Closed Thread
Results 1 to 28 of 28

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi Barry,
    The question really is how short of an event you MUST be able to capture. If we're talking microseconds then you really NEED hardware interrupts. If we're getting up into millisconds or possibly the hundreds of microseconds range then a software aproach, in line with what I, and I think Amoque was saying, might work - YMMV.

    Here's something in the line of what I'm thinking
    Code:
    SignalLines VAR WORD                                    ' Current state of inputs
    oldSignalLines VAR WORD                                 ' Previous state of inputs
    Result VAR WORD                                         ' Result of XORing
    
    Counter VAR WORD[9]                                     ' 9 counters, one for each line
    idx VAR BYTE                                            ' Index variable
    
    ' Subroutine to poll and evalute the signal lines, GOSUB this periodically.
    Test:
        SignalLines.LowByte = PortB                         ' 8 lines on PortB and...
        SignalLines.Bit9 = PortC.0                          ' ...and one on PortC.0 for a total of 9.
    
        ' Any bit that is set in Result indicates a state change, 1->0 and 0->1.    
        Result = SignalLines XOR oldSignalLines
    
        ' Iterate thru the bits in result and increment the counter for each
        ' respective counter if the bit is set.
        For idx = 0 to 8                                    ' 9 bits, 9 counters
            Counter[idx] = Counter[idx] + Result.Bit0[idx]  ' Increment counter if bit is set
        NEXT
        
        oldSignalLines = SignalLines                        ' Clear any mismatch.
    
    RETURN
    Compiles but is not tested, meant as food for thought.

    /Henrik.

  2. #2


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Henrik

    I though this would take ten pages of code and Darrels instant interrupts etc etc
    Then you condense it into about 10 lines.

    You are a master!!!

  3. #3
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    172


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi Henrik,

    Thanks for the program suggestion and detailed explanation of how it works.
    Very nice and succinct code!

    I would like to be able to capture events in the single digit millisecond region as a worst case scenario.
    The XOR approach opens up more PIC options and I could use one with the fastest clock on offer.
    Would you have any idea how long this subroutine would take to complete with a clock speed of say 32MHz or the shortest time achievable between captured events?

    I have a bit of thinking to do before making a decision.

    Thank you all for your valuable input to this project.

    Cheers
    Barry
    VK2XBP

  4. #4
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    172


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi All,

    I found PIC16F1783 which has Interrupt-On-Change available on all I/O pins.
    This device should be able to do everything I am looking at.

    Cheers
    Barry
    VK2XBP

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi Barry,
    That's great! While you searched and found that PIC a did some test here, now they are kind of moot but since I did them I'll post the results anyway.

    The subroutine code, as written originally takes, 769 cycles (on an 18F part, don't know if it'll be any different on a 16F1x) including the GOSUB and RETURN. At 32MHz that's ~100us.

    I thought that was quite a bit to tell you the truth so I tried replacing the array indexing FOR-NEXT loop discrete lines (Counter[0] = Counter[0] + Result.BIT0 and so on) and it went down from 769 to 87(!) cycles. 87 cycles at 32MHz is only ~11us.

    The tricky part would obviosuly be to update the LCD during the duration of the test. I think you'd need to write a single character to LCD, GOSUB the test routine write another character, GOSUB the test routine and so on. Obviously not rewriting static information every time.

    Anyway, if you've found a suitable device then going the interrupt route is probably better!

    /Henrik.

  6. #6
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    172


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi Henrik,

    Thank you for the subroutine timing analysis. 11us is a pretty good result!

    I am now looking at ways to handle the interrupts and still trap subsequent events whilst the first event is being acted upon.

    With the PIC16F1783 all pins on all ports can be configured to operate as IOC pins. Individual status flags can be read and cleared individually so my approach will be to jump to the ISR on an interrupt event, check which of the nine lines were affected using IF...ELSEIF...ENDIF statements, increment the appropriate error counter, clear the individual IOC flag and then return to the main program. My concern is the method used within the ISR to determine which line generated the interrupt. Is a 9 option deep IF...ELSEIF...ENDIF faster or slower than a 9 option deep SELECT CASE...END SELECT? Or is there a more elegant way of doing this which would take less time?

    Comments and suggestions are, once again, welcomed and appreciated.

    Cheers
    Barry
    VK2XBP

  7. #7
    Join Date
    Apr 2011
    Location
    Welches, Oregon
    Posts
    198


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    I'm a little confused by your requirements.

    You state it is a mechanical system - suggesting some debounce might be necessary(?), or is this part of the fault condition to be counted? You worry for the speed of the system and capturing every event, but then state the count need not be too accurate... The requirements are likely very clear in your mind, but reading... it leaves me wondering, just how fast an event you wish to capture and what constitutes an event?

    Here we go into areas I'm not qualified to speak with much expertise...

    I had imagined some level of filtering to eliminate the tiniest of glitches - capacitors, as used on power supply, to eliminate noise and other such tiny perturbances and measuring events in the range of a few milliseconds - maybe less, I hadn't really thought of minimal times possible, only to make a stable system that reacts reliably and consistently rather than to every stray passing gamma ray . Henrik's suggestion to use ORs is much better... I thought to use latching flip-flops to maintain state until the PIC could read and reset in a tight loop/ interrupt. My idea being that mechanical systems are typically pretty slow and messy, and accuracy at the level I work is typically limited to what I can see and measure. This seems not to be the case for your requirements.

    Well, in any case it has been an interesting read - and you have determined an answer suitable... back to the bench for me!

    Oh, as to your question... I'd likely stack all the flags into a bit array and then loop through as:

    For LOOP = 0 to 8 'For each flag
    If BIT[LOOP] Then 'If bit is set
    CounterWord[LOOP] = CounterWord[LOOP] + 1 'Add one to count
    EndIf
    Next


    ...unless, as I was typing, Henrik posted a more artful method in the post following.
    Last edited by Amoque; - 18th March 2014 at 12:46.

  8. #8
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi Barry,
    I don't see the need for all the IF/ENDIF stuff, care to explain?

    Instead, why not do like I did in the previous example:
    Code:
    Counter[0] = Counter[0] + IOCBP.0  ' Positive edge on RB0
    Counter[1] = Counter[1] + IOCBP.1  ' Positive edge on RB1
    ' ....and so on.
    
    IOCBP = 0   ' Clear the interrupt flag registers
    
    ' Possibly clear the IOC flag as well IF DT-INTS doesn't do it (I don't know for sure).
    If an IOC flag bit IS set the counter will get incremented, if it's not set the counter will not get incremented. If you want to capture negative edges as well then just add a similar block for IOCBN etc. The ISR will take the same amount of time every time which is good and it should be about as quick as my subroutine so you'll probably spend way more time getting in and out of the ISR than actually IN the ISR.

    It might be better to read the complete IOCxP register into a temporary register and using that instead. The datasheet does discuss the correct way of doing this ensuring no events gets missed but I haven't really looked into it properly.

    /Henrik.

Similar Threads

  1. PortB Change Interrupts
    By backstabber in forum mel PIC BASIC Pro
    Replies: 17
    Last Post: - 8th October 2011, 03:52
  2. Replies: 10
    Last Post: - 24th September 2011, 18:09
  3. Replies: 6
    Last Post: - 12th March 2011, 13:11
  4. Returning from Int on PortB change
    By sheryl in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 11th December 2008, 18:09
  5. Interrupt portb
    By tazntex in forum mel PIC BASIC Pro
    Replies: 8
    Last Post: - 18th August 2008, 21:05

Members who have read this thread : 0

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