16F876A CCP1 Capture/Interrupt Question


Closed Thread
Results 1 to 7 of 7
  1. #1
    Join Date
    Jan 2008
    Location
    Carrollton, TX
    Posts
    6

    Question 16F876A CCP1 Capture/Interrupt Question

    Hi,
    I am experimenting with using the 16F876A to measure the turn off time of a phototransistor. I have tried two ways, just to see how much difference there would be in the time. The first way is using the RB0 input to generate an interrupt, and the 2nd is using the capture feature on pin RC2/CCP1.
    1st method:
    1. Turn off the LED that points at the phototransistor
    2. Reset the timer1 high and low bytes to zero
    3. When program jumps to ISR, read value of Timer 1. Result is 204uS

    2nd method:
    1. Turn off the LED that points at the phototransistor
    2. Reset the timer1 high and low bytes to zero
    3. Poll the CCP1IF flag in a loop until it goes high, and then read the value of the CCP1 high and low byte registers. Result is 188uS, which is almost exactly the same as I measure on an oscilloscope.

    With 2nd method, I had expected to do it the same way as the first... I thought program would jump to ISR when pin RC2 went high, but it did not work. So my question is, why doesn't the program jump to the Interrupt handler when the CCP1IF flag gets set? If it did then I would not need to poll the pin in a loop. Would I be doing something wrong or is that how it is supposed to work? Thanks for any answers.
    TDon

  2. #2
    Join Date
    Feb 2003
    Location
    Salt Lake City, Utah USA
    Posts
    517


    Did you find this post helpful? Yes | No

    Smile

    TDon,

    You leave us guessing about how you are doing everything. Show us your code or provide a crystal ball. You will get better answers with either option.
    Paul Borgmeier
    Salt Lake City, UT
    USA
    __________________

  3. #3
    Join Date
    Jan 2008
    Location
    Carrollton, TX
    Posts
    6


    Did you find this post helpful? Yes | No

    Default

    Sorry about that.
    The code directly below works...that is it displays a T_off2 reading. The program waits for the CCP1 flag to set and then it jumps to the Display2 subroutine. What I wanted to have happen though, was for the program to jump to the Interrupt Handler routine and display the T_off reading. The code just below this code shows how I tried to do that, but nothing happens. In that code the instruction to jump to the Display2 subrouting is commented out. So I'm guessing that a CCP interrupt isn't supposed to make the program jump to the interrupt routine the same way that an RB0/Interrupt does... you have to do it like the first example below.
    That is my question.
    Thanks,
    TDon

    ' PIC16F876A hardware connections
    ' PIC External
    ' ---- ---------
    ' RB1 LED Cathode
    ' RC2 Phototransistor Comparator Output to RC2/CCP1 pin
    ' ----[ Includes / Defines ]-------------------------------------------

    @ DEVICE WDT_OFF
    define OSC 4
    include "modedefs.bas" 'include serout defines

    ' -----[ Variables ]-------------------------------------------------------
    T_Off var Word ' Time in uS
    T_off = 0 'Initialize to zero
    ' -----[ Initialization ]--------------------------------------------------
    Init:
    TRISB = %00000000 'PortB -all outputs
    PORTB = %00000000 'Initialize PortB outputs low
    TRISC.2 = 1 '(Pin 13) is input for CCP1 capture mode
    CCP1CON = $05 'Capture mode, every rising edge
    ' -----[ Main Code ]-------------------------------------------------------

    ' Disable interrupts and clear interrupt flags
    INTCON = $00 'Disable unmasked global interrupts (bit 7)
    'Peripheral interrupts disabled (bit 6)
    'TMR0 Interrupt disabled (bit 5)
    'Disable RB0 interrupt (bit 4)
    'Disable RB Port change interrupt (bit 3)
    'TMR0 overflow flag cleared (bit 2)
    'RB0 interrupt flag cleared (bit 1)
    'RB port change flag cleared (bit 0)
    PIR1 = $00 'Clear Interrupt flags (bit 0 only used by TMR1)
    PIE1 = $00 'Peripheral Interrupt Enable Register ($00 is default)
    'All individual bits are disabled
    'including bit 0 TMR1 overflow interrupt

    ' Enable unmasked global interrupts and peripheral interrupts
    INTCON = $C0

    On interrupt goto IntHand
    'Reset Timer 1 and turn it on
    TMR1H = $00 'Reset timer to zero right after turning on
    TMR1L = $00
    T1CON = %00000001 'TMR1 on, prescaler=1, clock = (Fosc/4)

    High PortB.1 'Turn on LED
    Loop:
    If PIR1.2 = 1 then Display2 'wait for the CCP1 flag to set, at RC2
    goto Loop

    Disable
    IntHand:
    T_Off.HighByte = TMR1H
    T_off.Lowbyte = TMR1L
    serout 2, T2400, ["T_Off = ", #T_Off, 13,10]
    PIR1 = $00 'Clear Peripheral Interrupt Flag Register
    INTCON.1=0
    RESUME
    ENABLE

    Display2:
    T_Off.HighByte = CCPR1H
    T_Off.LowByte = CCPR1L
    serout 2, T2400, ["T_Off2 = ", #T_Off, 13,10]
    PIR1.2 = 0
    INTCON.1=0
    Return

    END

    ----------------------------------------------------------------------------------
    ' PIC16F876A hardware connections
    ' PIC External
    ' ---- ---------
    ' RB1 LED Cathode
    ' RC2 Phototransistor Comparator Output to RC2/CCP1 pin
    ' ----[ Includes / Defines ]-------------------------------------------

    @ DEVICE WDT_OFF
    define OSC 4
    include "modedefs.bas" 'include serout defines

    ' -----[ Variables ]-------------------------------------------------------
    T_Off var Word ' Time in uS
    T_off = 0 'Initialize to zero
    ' -----[ Initialization ]--------------------------------------------------
    Init:
    TRISB = %00000000 'All port b are outputs
    PORTB = %00000000 'Initialize PortB outputs low
    TRISC.2 = 1 '(Pin 13) is input for CCP1 capture mode
    CCP1CON = $05 'Capture mode, every rising edge
    ' -----[ Main Code ]-------------------------------------------------------

    ' Disable interrupts and clear interrupt flags
    INTCON = $00 'Disable unmasked global interrupts (bit 7)
    'Peripheral interrupts disabled (bit 6)
    'TMR0 Interrupt disabled (bit 5)
    'Disable RB0 interrupt (bit 4)
    'Disable RB Port change interrupt (bit 3)
    'TMR0 overflow flag cleared (bit 2)
    'RB0 interrupt flag cleared (bit 1)
    'RB port change flag cleared (bit 0)
    PIR1 = $00 'Clear Interrupt flags (bit 0 only used by TMR1)
    PIE1 = $00 'Peripheral Interrupt Enable Register ($00 is default)
    'All individual bits are disabled
    'including bit 0 TMR1 overflow interrupt

    ' Enable unmasked global interrupts and Peripheral Interrupts
    INTCON = $C0

    On interrupt goto IntHand
    'Reset Timer 1 and turn it on
    TMR1H = $00 'Reset timer to zero right after turning on
    TMR1L = $00
    T1CON = %00000001 'TMR1 on, prescaler=1, clock = (Fosc/4)

    High PortB.1 'Turn on LED
    Loop:
    'If PIR1.2 = 1 then Display2 'wait for the external interrupt on RC2
    goto Loop

    Disable
    IntHand:
    T_Off.HighByte = CCPR1H
    T_off.Lowbyte = CCPR1L
    serout 2, T2400, ["T_Off = ", #T_Off, 13,10]
    PIR1 = $00 'Clear Peripheral Interrupt Flag Register
    INTCON.1=0
    RESUME
    ENABLE

    Display2:
    T_Off.HighByte = CCPR1H
    T_Off.LowByte = CCPR1L
    serout 2, T2400, ["T_Off2 = ", #T_Off, 13,10]
    PIR1.2 = 0
    Return
    TDon

  4. #4
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default

    Hi TDon,
    without reading and understanding your code, which I didn't and don't, I will still toss out this comment: PBP interrupts are like a teenager, you ask them to do something and they will, in their own time. Have you tried Darrel's instant interrupt routines ? They offer assembly interrupts in a bolt on fashion, without the brain damage associated with using assembly.

    http://darreltaylor.com/DT_INTS-18/home.html
    http://www.picbasic.co.uk/forum/showthread.php?t=3251
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  5. #5


    Did you find this post helpful? Yes | No

    Default Oscilloscope is a better way

    If an event is slow, say many milliseconds, then software measurements such as you are trying can give reasonable results. However I would expect the turnon or turnoff time of a phototransistor with say a 4k7 load resistor to be only a few tens of microseconds. This is way too fast to easily measure in software IMHO. Unless you get deep into the assembly code produced by PBP and your assembler (PM or MPASM) you will not know how many machine code instructions lie between the event and the display of that event. That makes such a measurement in code a rather hit or miss affair.

    There are no published timings for PBP commands because many of them are variable. For example the instruction "If A > B then" takes different times for a byte compare vs a word compare.

    If at all possible, use an independent hardware device, an oscilloscope or logic analyser, to get believable and repeatable measurements.

    HTH
    BrianT
    Last edited by BrianT; - 16th January 2008 at 08:18. Reason: clarity

  6. #6
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Capture will generate the interrupt, but only if you have it enabled. PIE1 = $04 should do
    the trick. With PIE1 = 0 you have the interrupt disabled.

    Do a search here for examples using capture & code execution timing with timers for several
    good examples.

    Edit: Here's an example http://www.picbasic.co.uk/forum/showthread.php?p=23401
    Last edited by Bruce; - 16th January 2008 at 15:02. Reason: Link to thread
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  7. #7
    Join Date
    Jan 2008
    Location
    Carrollton, TX
    Posts
    6


    Did you find this post helpful? Yes | No

    Default

    Joe and Brian,
    Thanks for the comments.. I had already downloaded Darrel's instant interrupts but I haven't tried those yet... later in my learning process I will do that. The phototransistor turn off time I'm measuring with a 10K load is on the order of 100 to 200uS, and I seem to be getting very accurate measurements using the CCP1 pin (they agree with my oscilloscope), but not that accurate with the RB0/INT pin because of the things you mentioned.

    Bruce,
    You nailed it. Thanks for taking the time to read through my code and figure it out for me...I should have been able to figure that out myself, but I kept missing it. I knew it couldn't have been a bad PIC - I bought it from you!
    TDon

Similar Threads

  1. 16 bit PWM using CCP1
    By Normnet in forum mel PIC BASIC Pro
    Replies: 60
    Last Post: - 27th August 2014, 08:13
  2. Question Regarding Port A on 16F876A
    By jevert in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 26th February 2009, 14:00
  3. PIC16F819 HPWM CCP1 clariffication
    By earltyso in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 20th March 2008, 18:43
  4. Please answer my first question
    By John_001 in forum Off Topic
    Replies: 1
    Last Post: - 15th September 2006, 06:49
  5. Timer / CCP Question
    By jamie_s in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 2nd November 2005, 08:22

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