PORTB + PORTC Interrupt-On-Change


Closed Thread
Results 1 to 28 of 28
  1. #1
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166

    Default PORTB + PORTC Interrupt-On-Change

    Hi All,

    I am working on a new project which requires monitoring 9 data lines for an interrupt on change (IOC).
    All the program really needs to do is count the number of interrupts on each line, increment individual counters for each occurrence and display the results to a 4x20 LCD display.
    PIC16F1829 has ten IOC lines but doesn't have enough I/O ports for the rest of the project.
    I could find no search criteria on the Microchip web site for IOC and PIC16F1829 is the best option I have been able to find thus far.

    Can anyone suggest an alternate PIC that would handle at least 9 IOC channels PLUS an additional 6 I/O's for 4x20 LCD and 3 I/O's for switches?

    I understand a serial LCD display would free up a number of I/O's on the PIC16F1829 for switch functions but I am trying to avoid going down that path unless absolutely necessary.

    All suggestions, or alternate recommendations on how to perform the same task, would be greatly appreciated.

    Cheers
    Barry
    VK2XBP

    P.S. I also need two ADC lines - just to make it interesting...
    Last edited by Aussie Barry; - 17th March 2014 at 09:58. Reason: Additional requirement

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi Barry,
    So how often do you expect the inputs to change state? Thosands of times per second, once every week or perhaps somewhere in between?
    Do you need to detect BOTH edges of the signal or is either the rising or falling edge?
    Are the inputs asynchronous in nature or do they change "in sync" with each other?

    I'm asking because perhaps it can be done without interrupts, if a suitable chip isn't available.

    Another option to look into is one of the "port expander chips". I've never used them but I think some of them have IOC capabillity but then again it depends on the timing requirements etc.

    /Henrik.

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


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    There may also be the possibility that one might "snapshot" all the lines on an interrupt and then compare to the previous "snapshot" to determine which is the different state?

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


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi Guys,

    Henrik:
    I am checking for break in continuity due to physical movement. My idea is to use weak pull-ups on one side of the data line and ground the other side. Any break in the line would cause a leading edge interrupt.
    Due to the mechanical nature of the test, any line could fail irrespective of the other lines. The test period is around 1 minute.
    The failure mode could be intermittent (ie momentary break in continuity) or permanent.
    The tests are more indicative than quantitative in that I want to know if one (or more) data lines are broken more often than others - the actual count does not need to be specifically accurate.
    Ideally there would be no failures during the test but hey, who lives in an ideal world? I has assigned WORD variables to all nine counters - just in case!

    Amoque:
    I am not sure how a snapshot would work considering any one of the nine data lines can generate the interrupt. What are you proposing?

    Cheers
    Barry
    VK2XBP

  5. #5
    Join Date
    Dec 2010
    Posts
    409


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Use an external "OR" gate to generate the interrupt, then read the state of all the pins and increment the counter for the pin that has changed.
    Or you could use PIC16(L)F1526/7 but that's a lot of pins and a difficult package to deal with.

    FYI I found it using the part chooser on the Microchip site - I've never actually used the device.

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


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi Charlie,

    I had thought about the "OR" gate option but I am not sure if the intermittent fault would last long enough to read the state of all the pins after the interrupt was triggered.
    The PIC16(L)F1526/7 still only has PORTB IOC as an option so all those other pins don't really help my cause.

    Thanks for taking the time to research other option though - greatly appreciated.

    Cheers
    Barry
    VK2XBP

  7. #7
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    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.

  8. #8


    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!!!

  9. #9
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    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

  10. #10
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    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

  11. #11
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    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.

  12. #12
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    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

  13. #13
    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.

  14. #14
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    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.

  15. #15
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi Amoque,

    Please let me clarify my requirements.

    I am trying to capture fault conditions so I definitely do not want to de-bounce any of the lines. A fault in this test is defined as an intermittent open circuit and I need to determine not only which lines exhibit fault conditions but also how frequently the faults occur during the test period. The accuracy of an individual line's error count does not have to be to absolute; it is more important to capture a fault condition occurring on any of the other lines whilst processing an fault on an individual line.

    For example:
    1/. Initial state is set and there are no fault conditions.
    2/. Under test conditions, line 1 exhibits a fault condition
    3/. Whilst recording line 1 fault condition, line 2 also exhibits a fault condition

    In this example I do not want to miss recording the line 2 fault whilst recording the line 1 fault.
    If a subsequent fault condition occur on line 1 whilst the initial line 1 fault is being recorded, and some of these slip through, then that is acceptable - not ideal but acceptable. This is what I meant when I stated that "the count need not be too accurate."

    So, extreme accuracy in counting individual line faults is not as important as the ability to capture fault events that may occur in quick succession across all nine lines.

    An interesting challenge - yes?

    I trust this clears up the confusion caused by me not explaining the how's and why's in my previous posts.

    Cheers
    Barry
    VK2XBP

  16. #16
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,166


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Barry, What is the time between fault conditions? I think I would propose using a couple of port expanders like the PCF8574 with the interrupt lines tied together going to 1 PIC interrupt line. When interrupted just read the port expanders and clear?
    Dave Purola,
    N8NTA
    EN82fn

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


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Yes, quite the "sticky wicket". As I see it, your device must be prepared to capture 9 errors simultaneously- and constantly.

    I was mistaken in my first assumptions by imagining something like a frame rate where you would have some measure of time between [machine] cycles to do something. I refer to 3/ above - since there is no measure of time allowed to record the event and no lower limit for the event timing (which, in itself provides some opportunity)... it seems impossible to me. The only hope I see is in "If a subsequent fault condition occur on line 1 whilst the initial line 1 fault is being recorded, and some of these slip through, then that is acceptable - not ideal but acceptable."

    The closest "solution" I imagine is 9 processors on a common clock, each recording the status of its input on each tick. This will only work to the limits of the clock speed, but it is a start... Or, you might just use a DSO (of the best speed available) as, in the end, this is the function you describe, is it not?

    I have had another thought - what of a decade counter on each line? You would not get specific timing, but at regular intervals you could record the number of faults by reading the counter values.
    Last edited by Amoque; - 19th March 2014 at 12:09.

  18. #18
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Ah, come on guys, I think you are overcomplicating this.
    From what I understand it's basically a test rig for flexible cable moving back and forth and the goal is to capture any glitches in the cable as it moves.

    Using a PIC with IOC will probably work fine as long as the code for it is written properly. The only thing it will NOT catch is a second (and third and forth and....) fault condition on the very same line that initially caused the interrupt. But then again the absolute fault count per line wasn't that critical and I think that the interrupt latency etc will provide the "perfect" amount debounce (even though the specification said no debounce) for this to work perfectly fine. But again, make sure to read up on how to handle the IOC events in order to not miss events on lines any of the lines that didn't actually cause the interrupt currently being serviced.

    Using a port expander, which I also suggested in my first reply, will work but in this case I don't see the benefits, only drawbacks, considering Barry did find a PIC with the needed number of IOC pins.

    /Henrik.

  19. #19


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Have I missed something? Why not use a logic analyzer? If it's data presentation that precludes then write a plug-in (both of the obvious candidates provide for them) which will print out the results or give you a go/no go.

  20. #20
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi Guys,

    Thanks for all the fabulous responses.

    1/. Towlerg: "Why not use a logic analyser?" - simply because I don't have one. I also need to replicate this test in other parts of the world so I don't think purchasing multiple logic analysers is a cost effective approach to solving the problem.

    2/. Henrik: Great comment! Yes, I do not want to over-complicate the problem. I hope to send my ISR code to the group soon for comment on my approach to handle the IOC event and minimise loss of subsequent events on other lines.

    3/. Amoque: Your multiple decade counter suggestion was quite inspirational! I had not thought of it like that but essentially I am trying to replicate the same concept with the PIC16F1783.

    4/. Dave: Much of this testing is exploratory so I can't accurately predict what the time between events will be. Ideally there should be no faults at all (obviously) but if there are faults then I want to capture as many events on as many data lines as possible.

    I am making good progress on the software side of the project but can't verify anything until the PICs arrive late next week/early the week after. As mentioned above, I will post my ISR code for comment soon. Fingers crossed my methods will not be shot down in flames

    I am now concentrating on the hardware side of the project: machining enclosures, mounting LCD displays, push buttons etc but the most trying part will be building jigs to accept the device under test (DUT). Lots of fun ahead for me this weekend!

    Cheers
    Barry
    VK2XBP

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


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    "the most trying part will be building jigs to accept the device under test (DUT)."

    I trust that you are looking for every opportunity to use those little Pogo Pin test probes. Those thing seem so cool that I just don't see how any project featuring them can't work.

  22. #22
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change


  23. #23
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Interrupts can be very useful for many different purposes ... this isn't one of them.
    In fact, interrupts will only slow things down and reduce the resolution of your readings.

    A variation of what Henrik was describing might look like this ...
    The resolution with WORD variables for the counts is 9uS (16F1783 running at 32Mhz internal OSC).
    If the counters are BYTEs, the resolution is 3.5 uS, as measured in the simulator.

    With interrupts, using a BASIC language ISR, that resolution will suffer greatly.
    Code:
    DEFINE OSC 32
    
    ANSELA = 0
    ANSELB = 0
    
    Results   VAR BYTE[9]
    Res0      VAR Results[0]
    Res1      VAR Results[1]
    Res2      VAR Results[2]
    Res3      VAR Results[3]
    Res4      VAR Results[4]
    Res5      VAR Results[5]
    Res6      VAR Results[6]
    Res7      VAR Results[7]
    Res8      VAR Results[8]
    IOCA      VAR BYTE
    IOCB      VAR BYTE
    Testing   VAR PORTC.0
    
    IOCBP = $FF
    IOCBF = 0
    
    CLEAR
    WHILE !Testing : WEND
    PAUSE 20
    
    WHILE Testing
        IOCA = IOCAF
        IOCAF = 0
        IOCB = IOCBF
        IOCBF = 0
        Res0 = Res0 + IOCA.0
        Res1 = Res1 + IOCA.1
        Res2 = Res2 + IOCA.2
        Res3 = Res3 + IOCA.3
        Res4 = Res4 + IOCA.4
        Res5 = Res5 + IOCA.5
        Res6 = Res6 + IOCB.0
        Res7 = Res7 + IOCB.1
        Res8 = Res8 + IOCB.2
    WEND
    DT

  24. #24
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    HI All,

    I am so glad I didn't show any of you my ISR code...it is embarrassing compared to what Darrel has just shared!

    I also need to display results as they occur on a 4x20 LCD. There are two different display screens, one that gives a visual representation if a fault has occurred on any particular data line and another that displays actual fault counts for all nine lines. I don't know the timing requirements for LCDOUT statements but I am sure they will add considerably to the 9uS resolution with WORD variables. I could control the LCDOUT routine such that it only updates the LCD screen if a new fault has occurred. Is it possible to do a comparison using this pseudo-code:

    Results VAR WORD[9]
    OldResults VAR WORD[9]

    IF Results <> OldResults THEN
    Goto Display Routine ' break to the routine that updates the LCD screen
    OldResults = Results ' Reset OldResults
    ENDIF

    Cheers
    Barry
    VK2XBP

  25. #25


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi Barry
    1/. Towlerg: "Why not use a logic analyser?" - simply because I don't have one. I also need to replicate this test in other parts of the world so I don't think purchasing multiple logic analysers is a cost effective approach to solving the problem.
    You can buy a Saleae for 119Euros. Accepted that you'll need an old laptop for display. It'll store billions of samples @ 24Mhz, thats at least a decade better that Darrel is suggesting, and he writes great code. How many samples before the PIC runs out of memory?

    Anyways, good luck with the project.

    George

  26. #26
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi George,

    Yes, there are always a number of different ways to "skin a cat" but if I went with the logic analyser route then I would have nothing to design and build using a PIC

    If we end up with more than a byte's worth of fault counts on any of the nine data lines within a one minute test period then we have more problems to worry about than a PIC running out of memory!

    Cheers
    Barry
    VK2XBP

  27. #27
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi All,

    I am still waiting for my PIC16F1783 chips to arrive so I have been doing some testing with a PIC16F1829.
    I am getting good results but unsure if my code can be improved. Here is the stripped down version for comment.

    Code:
    ' Connect LCD D4 to RC4 (Pin 6)
    ' Connect LCD D5 to RC5 (Pin 5)
    ' Connect LCD D6 to RC6 (Pin 8) 
    ' Connect LCD D7 to RC7 (Pin 9)
    ' Connect LCD RS to RC3 (Pin 7)
    ' Connect LCD E  to RC2 (Pin 14)
    ' Connect Data Line 1 to RA0 (Pin 19)
    ' Connect Data Line 2 to RA1 (Pin 18)
    ' Connect Data Line 3 to RA2 (Pin 17)
    ' Connect Data Line 4 to RA3 (Pin 4)
    ' Connect Data Line 5 to RA4 (Pin 3)
    ' Connect Data Line 6 to RA5 (Pin 2)
    ' Connect Data Line 7 to RB4 (Pin 13)
    ' Connect Data Line 8 to RB5 (Pin 12)
    ' Connect Data Line 9 to RB6 (Pin 11)
    
    #CONFIG
            __config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _MCLRE_OFF & _BOREN_OFF
            __config _CONFIG2, _PLLEN_ON & _LVP_OFF & _WRT_HALF
    #ENDCONFIG
    
    OSCCON = %11110000              ; Fosc = 32MHz
                                    ; Clock determined by Fosc<1:0> Config Word
    DEFINE OSC 32                   ; Define socillator as 32MHz
    
    ' Define LCD registers and bits
    Define	LCD_DREG	PORTC
    Define	LCD_DBIT	4
    Define	LCD_RSREG	PORTC
    Define	LCD_RSBIT	3
    Define	LCD_EREG	PORTC
    Define	LCD_EBIT	2
    Define	LCD_BITS	4
    Define	LCD_LINES	4
    PAUSE 500               ' Pause to initialise LCD Display
    
    
    ' Define program variables
    DisplayFlag var BIT
    DisplayFlag = 0
    
    Counter1    var BYTE
    Counter2    var BYTE
    Counter3    var BYTE
    Counter4    var BYTE
    Counter5    var BYTE
    Counter6    var BYTE
    Counter7    var BYTE
    Counter8    var BYTE
    Counter9    var BYTE
    IOCA        var BYTE
    IOCB        var BYTE
    
    Counter1 = 0
    Counter2 = 0
    Counter3 = 0
    Counter4 = 0
    Counter5 = 0
    Counter6 = 0
    Counter7 = 0
    Counter8 = 0
    Counter9 = 0
    
    
    ANSELA = 0                      ' Disable PORTA ADC
    ANSELB = 0                      ' Disable PORTB ADC
    ANSELC = 0                      ' Disable PORTC ADC
    DACCON0.7 = 0                   ' Disable DAC
    CM1CON0.7 = 0                   ' Disable comparator 1
    CM2CON0.7 = 0                   ' Disable comparator 2
    TRISC = %00000001               ' Set PORTC.0 and PORTC.1 as digital input
    TRISA = %00111111               ' Set PORTA as digital inputs
    TRISB = %01110000               ' Set PORTB.4-6 as digital inputs
    OPTION_REG.7 = 0                ' Enable Weak Pull-ups
    WPUA = %00111111                ' Pull-ups enabled on PORTA.0 - 5
    WPUB = %01110000                ' Pull-ups enabled on PORTB.4 - 6
    WPUC = %00000001                ' Enable PORTC.0 pull-ups
    
    IOCAP = %00111111               ' Enable IOC rising edge on PORTA.0-5
    IOCBP = %01110000               ' Enable IOC rising edge on PORTB.4-6
    IOCAN = 0                       ' Disable IOC falling edge on PORTA
    IOCBN = 0                       ' Disable IOC falling edge on PORTB
    
    
    Main:
        IOCA = IOCAF                ' Save IOCAF to IOCA
        IOCB = IOCBF                ' Save IOCBF to IOCB
        IOCAF = 0                   ' Reset IOCAF
        IOCBF = 0                   ' Reset IOCBF
        IF IOCA > 0 OR IOCB > 0 THEN    ' Test if IOC Flags have changed
            DisplayFlag = 1             ' If so, set Display flag
        ENDIF
        Counter1 = Counter1 + IOCA.0
        Counter2 = Counter2 + IOCA.1
        Counter3 = Counter3 + IOCA.2
        Counter4 = Counter4 + IOCA.3
        Counter5 = Counter5 + IOCA.4
        Counter6 = Counter6 + IOCA.5
        Counter7 = Counter7 + IOCB.4
        Counter8 = Counter8 + IOCB.5
        Counter9 = Counter9 + IOCB.6
        IF DisplayFlag = 1 THEN         ' Go to Display subroutine if DisplayFlag set
            Gosub Display
            DisplayFlag = 0             ' Reset DisplayFlag
        ENDIF
    GOTO Main
    
    Display:
        LCDOUT $FE, $80, "    Fault Status    "
        LCDOUT $FE, $C0, "1. ", DEC3 Counter1, " 2. ", DEC3 Counter2, " 3. ", DEC3 Counter3
        LCDOUT $FE, $94, "4. ", DEC3 Counter4, " 5. ", DEC3 Counter5, " 6. ", DEC3 Counter6
        LCDOUT $FE, $D4, "7. ", DEC3 Counter7, " 8. ", DEC3 Counter8, " E. ", DEC3 Counter9
    Return
    Any suggested improvements would be greatly appreciated.

    Cheers
    Barry
    VK2XBP

  28. #28
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: PORTB + PORTC Interrupt-On-Change

    Hi Barry,
    First suggestion is very minor but still, clear IOCAF immediately after reading it, ie
    Code:
    IOCA = IOCAF                ' Save IOCAF to IOCA
    IOCAF = 0                   ' Reset IOCAF
    IOCB = IOCBF                ' Save IOCBF to IOCB
    IOCBF = 0                   ' Reset IOCBF
    The longer the time is between reading it and clearing it is the bigger the risk of missing an "event" is. In this case, as I said, very minor but still.

    Next suggestion is to really try to tweak the display routine. Measure how long it takes now, then tweak it and compare. You want to make it as quick as you possibly can.
    With tweaking I mean things like not rewriting static information each update. Instead, write the static information ONCE and then only update/overwrite what's actually needs to be updated.

    You could, for example, use the bits in IOCA and IOCB to determine which counters content actually needs updating on the display. A possible drawback of doing this is that the execution time of the routine isn't constant so it's hard to tell exactly how fast the system will be able to detects consecutive events on the same "line". At the very least, don't rewrite that [ Fault Status ] - waste of time ;-)

    As the code is currently written, I think you can skip the DisplayFlag semaphore and just do
    Code:
    IF IOCA > 0 OR IOCB > 0 THEN    ' Test if IOC Flags have changed
        GOSUB Display
    ENDIF
    But you may have something else in there preventing you from doing that, I don't know.

    Another possible option to flip it around and have the Display routine as part of your main code (with the flag indicating it needs updating) and then GOSUB the code that checks the interrupt flags. That way can insert a GOSUB at various places WITHIN the Display routine (and the rest of the main loop) in an effort to really catch multiple events on the same line.

    /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 : 2

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