Using hardware capture


Closed Thread
Results 1 to 15 of 15
  1. #1
    Join Date
    Jul 2003
    Posts
    2,405

    Default Using hardware capture

    Got a PIC with hardware capture, and looking for a way to record high & low pulse widths
    with better resolution than PULSIN?

    Here's how .. with an example from the Microchip CCP & ECCP Tips & Tricks modified to
    work with PBP.
    Code:
    ' Measuring signal pulse widths with capture module
    
    ' Procedure for high-going pulse:
    ' 1. Configure CCP to capture on rising edge
    ' 2. Setup Timer1 so it will not overflow during max pulse width time
    ' 3. Enable ccp capture
    ' 4. Once capture flag bit is set, save captured value as T1
    ' 5. Reconfigure CCP to capture on falling edge
    ' 6. On 2nd capture, save 2nd value as PW
    ' 7. Subtract T1 from PW for the pulse width value
    
        DEFINE OSC 4
    
        Symbol    Capture = PIR1.2 ' CCP1 capture flag
        T1        VAR WORD         ' 1st capture value
        PW        VAR WORD         ' 2nd capture value & ultimately final pulse width
    
        TRISC.2 = 1          ' CCP1 input pin (Capture input on 18F242)
        INTCON = 0           ' Interrupts off
        
    ReLoad:
        CCP1CON = %00000101  ' Capture mode, capture on rising edge
        T1CON = 0            ' TMR1 prescale=1, clock=Fosc/4, TMR1=off
        TMR1H = 0            ' Clear high byte of TMR1 counter
        TMR1L = 0            ' Clear low byte
        T1CON.0 = 1          ' Turn TMR1 on here
    
        Capture = 0         ' Clear capture int flag bit
        While !Capture      ' Wait here until capture on rising edge
        Wend
        
        ' Rising edge detected / stuff 'captured' Timer1 value in T1
        T1.HighByte = CCPR1H
        T1.LowByte = CCPR1L
        
        CCP1CON.0 = 0       ' Configure capture for falling edge now
        Capture = 0         ' Clear capture interrupt flag bit
        
        While !Capture      ' Wait here until capture on falling edge
        Wend
        
        ' Falling edge detected / stuff 'captured' Timer1 value in PW
        PW.HighByte = CCPR1H
        PW.LowByte = CCPR1L
        
        PW = PW-T1           ' High pulse width = PW-T1
    
        HSEROUT [DEC PW,"uS High",13,10]	' Output to RS232 display
        GOTO ReLoad
        
        END
    If you need to measure the width of a low-going pulse , just change it to capture
    the falling edge first with CCP1CON = %00000100, and rising edge next with
    CCP1CON.0 = 1.

    Real simple ... real effective ... and spot-on timing. Even works on tiny little PICs
    like the 12F683 12F615, etc...;o)
    Last edited by Bruce; - 27th January 2010 at 03:13.
    Regards,

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

  2. #2
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    Bruce,

    Does posting all the examples of late mean that you are getting closer with your book?

    Thanks for all of the examples!!!
    Dave
    Always wear safety glasses while programming.

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


    Did you find this post helpful? Yes | No

    Default

    Dave,

    No. It's just a few things people have asked me for. I prefer to post if here for everyone
    rather than sending it to just a few by email. Still working on that book too. It's just slow
    with the economy in the tank, and working 12-16 hours a day to stay afloat...;o)
    Regards,

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

  4. #4
    Join Date
    May 2007
    Posts
    604


    Did you find this post helpful? Yes | No

    Default

    The newer PIC's such as the PIC16F690 and the 28/40-pin PIC18FxxJ11 families have a Timer1 module with Gate Control which is ideal for doing this sort of thing.
    6.6 Timer1 Gate

    Timer1 gate source is software configurable to be the
    T1G pin or the output of Comparator C2. This allows the
    device to directly time external events using T1G or
    analog events using Comparator C2. See the
    CM2CON1 register (Register 8-3) for selecting the
    Timer1 gate source. This feature can simplify the
    software for a Delta-Sigma A/D converter and many
    other applications.

    Timer1 gate can be inverted using the T1GINV bit of
    the T1CON register, whether it originates from the T1G
    pin or Comparator C2 output. This configures Timer1 to
    measure either the active-high or active-low time
    between events.

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


    Did you find this post helpful? Yes | No

    Default

    That'll work too ... if you have a PIC with the TMR1 gate option.
    Code:
    ' PIC12F609 using Timer1 gate input to record pulse widths
    
    @ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _IOSCFS_4MHZ & _CP_OFF
    
    CMCON0 = 0         ' comparator disabled
    CMCON1 = %00000010 ' TMR1 gate source is T1G pin
    GPIO = 0           ' outputs all low at POR
    TRISIO = %00010000 ' GPIO.4 = TMR1 gate input
    
    PVAL VAR WORD      ' holds pulse time
    
    TMR1H = 0
    TMR1L = 0
    T1CON = %11000001 ' TMR1 gate active-high, Fosc/4 clock, TMR1 on
    
    Main: ' apply a pulse < 65536uS to TMR1 gate input GPIO.4 to use
      WHILE !GPIO.4 ' wait for high signal to trigger TMR1 gate pin
      WEND
      WHILE GPIO.4  ' wait for signal to return low (stops TMR1)
      WEND
      PVAL.LowByte = TMR1L  ' get TMR1 counts into PVAL
      PVAL.HighByte = TMR1H ' from TMR1
      TMR1H = 0             ' reset TMR1
      TMR1L = 0
      GOTO Main
    
      END
    Regards,

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

  6. #6
    Join Date
    May 2007
    Posts
    604


    Did you find this post helpful? Yes | No

    Default

    Would it be possible for you to do a non-blocking version of Measuring signal pulse widths with capture module.

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


    Did you find this post helpful? Yes | No

    Default

    Definitely. Just let CCP1 generate an interrupt, and handle flipping CCP1CON.0 + grabbing
    results in T1/PW in the interrupt handler.
    Regards,

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

  8. #8
    Join Date
    May 2007
    Posts
    604


    Did you find this post helpful? Yes | No

    Default

    OK, thanks.

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


    Did you find this post helpful? Yes | No

    Default

    This should work;
    Code:
    ' Measuring signal pulse widths with capture module & interrupt
    
    ' Procedure for high-going pulse:
    ' 1. Configure CCP to capture on rising edge
    ' 2. Setup Timer1 so it will not overflow during max pulse width time
    ' 3. Enable ccp capture
    ' 4. Once capture flag bit is set, save captured value as T1
    ' 5. Reconfigure CCP to capture on falling edge
    ' 6. On 2nd capture, save 2nd value as PW
    ' 7. Subtract T1 from PW for the pulse width value
    
      DEFINE OSC 4              ' 4MHz for 1uS resolution TMR1 counts
      DEFINE INTHAND CCP_INT    ' declare high-pri interrupt handler
        
      Symbol Capture = PIR1.2   ' CCP1 capture flag
      SYMBOL CapIE = PIE1.2     ' CCP1 interrupt enable bit
      SYMBOL CapPriEn = IPR1.2  ' priority enable bit for CCP1 interrupt
      SYMBOL PriEnable = RCON.7 ' set to enable priority levels on interrupts
        
      T1 VAR WORD BANKA SYSTEM ' 1st capture value
      PW VAR WORD BANKA SYSTEM ' 2nd capture value & ultimately final pulse width
      CF VAR BYTE BANKA SYSTEM ' indicates when last capture is ready
    
      CLEAR                ' clear RAM on POR
      TRISC.2 = 1          ' CCP1 input pin (Capture input on 18F242)
      INTCON = 0           ' Interrupts off for now
    
      GOTO Init            ' jump over interrupt handler
      
    ASM
    CCP_INT
      BTFSS CCP1CON,0      ; capture from rising edge?
      BRA Fall             ; no .. goto falling edge
      MOVFF CCPR1L, T1     ; get low capture byte into T1
      MOVFF CCPR1H, T1+1   ; get high capture byte into T1
      BRA IntExit          ; outta here
    Fall
      MOVFF CCPR1L, PW     ; get low capture byte into PW
      MOVFF CCPR1H, PW+1   ; get high capture byte into PW
      BSF CF,0             ; indicate last capture
    IntExit
      BTG CCP1CON,0        ; toggle between rising/falling edge captures
      BCF PIR1,2           ; clear capture interrupt flag bit
      RETFIE FAST          ; return/restore W, STATUS and BSR
    ENDASM
        
    Init: ' initialize a few things first
      CCP1CON = %00000101  ' Capture mode, capture on rising edge
      T1CON = 0            ' TMR1 prescale=1, clock=Fosc/4, TMR1=off
      TMR1H = 0            ' Clear high byte of TMR1 counter
      TMR1L = 0            ' Clear low byte
      PriEnable = 1        ' enable priority levels on interrupts
      Capture = 0          ' clear capture flag bit
      CapPriEn = 1         ' set CCP1 int to high priority
      CapIE = 1            ' enable the CCP1 capture interrupt
      INTCON = %11000000   ' global + peripheral ints enabled
      T1CON.0 = 1          ' Turn TMR1 on here
    
    Main:
      ' do other stuff here as required
      IF CF.0 THEN         ' figure out & print result only after last capture
        PW = PW-T1         ' High pulse width = PW-T1
        CF.0 = 0           ' clear flag bit
        HSEROUT [DEC PW,"uS High",13,10]
      ENDIF
      
      GOTO Main
        
      END
    Regards,

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

  10. #10
    Join Date
    May 2007
    Posts
    604


    Did you find this post helpful? Yes | No

    Default

    Thanks. I converted it to SF.
    Code:
    Device = 18F4620       
    Clock = 4
    
    Dim Capture As PIR1.2   ' CCP1 capture flag
    Dim CapIE As PIE1.2     ' CCP1 interrupt enable bit
    Dim CapPriEn As IPR1.2  ' priority enable bit for CCP1 interrupt
    Dim PriEnable As RCON.7 ' set to enable priority levels on interrupts
    
    Dim T1 As Word          ' 1st capture value
    Dim PW As Word          ' 2nd capture value & ultimately final pulse width
    Dim CF As Boolean       ' indicates when last capture is ready
    Dim CCP1 As Word Absolute $fbe   ' Location of CCPR1H:CCPR1L
    
    Interrupt IntHigh()
       if CCP1CON.0=1 then  ' Capture from rising edge?
          t1 = ccp1         ' Move word to T1     
       else
          pw = ccp1         ' Move word to PW
          cf = true         ' Indicate last capture
       end if
       CCP1CON.0 = not CCP1CON.0  ' toggle between rising/falling edge captures
       capture = 0          ' Clear capture interrupt flag bit
    End Interrupt
    
    Sub Init()
       CCP1CON = %00000101  ' Capture mode, capture on rising edge
       T1CON = 0            ' TMR1 prescale=1, clock=Fosc/4, TMR1=off
       TMR1H = 0            ' Clear high byte of TMR1 counter
       TMR1L = 0            ' Clear low byte
       PriEnable = 1        ' enable priority levels on interrupts
       Capture = 0          ' clear capture flag bit
       CapPriEn = 1         ' set CCP1 int to high priority
       CapIE = 1            ' enable the CCP1 capture interrupt
       INTCON = %11000000   ' global + peripheral ints enabled
       T1CON.0 = 1          ' Turn TMR1 on here
    End Sub
    
    ' Main Program Entry
    Init                    ' Initialization
    TRISC.2 = 1             ' CCP1 input pin (Capture input on 18F4620)
    Enable(IntHigh)         ' Enable Interrupts
    
    While true
       ' do other stuff here as required
       If CF Then           ' figure out & print result only after last capture
          PW = PW-T1        ' High pulse width = PW-T1
          CF = false        ' Clear flag bit
          ' Send Out Data
       EndIf
    Wend
    Last edited by rmteo; - 30th January 2010 at 20:21.

  11. #11
    Join Date
    Aug 2011
    Posts
    8


    Did you find this post helpful? Yes | No

    Default Re: Using hardware capture

    Quote Originally Posted by Bruce View Post
    That'll work too ... if you have a PIC with the TMR1 gate option.
    Code:
    ' PIC12F609 using Timer1 gate input to record pulse widths
    
    @ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _IOSCFS_4MHZ & _CP_OFF
    
    CMCON0 = 0         ' comparator disabled
    CMCON1 = %00000010 ' TMR1 gate source is T1G pin
    GPIO = 0           ' outputs all low at POR
    TRISIO = %00010000 ' GPIO.4 = TMR1 gate input
    
    PVAL VAR WORD      ' holds pulse time
    
    TMR1H = 0
    TMR1L = 0
    T1CON = %11000001 ' TMR1 gate active-high, Fosc/4 clock, TMR1 on
    
    Main: ' apply a pulse < 65536uS to TMR1 gate input GPIO.4 to use
      WHILE !GPIO.4 ' wait for high signal to trigger TMR1 gate pin
      WEND
      WHILE GPIO.4  ' wait for signal to return low (stops TMR1)
      WEND
      PVAL.LowByte = TMR1L  ' get TMR1 counts into PVAL
      PVAL.HighByte = TMR1H ' from TMR1
      TMR1H = 0             ' reset TMR1
      TMR1L = 0
      GOTO Main
    
      END
    For all the NOOBS (like me) don't forget the
    Code:
    ANSEL=0
    to make your T1G pin a digital input. I spent a couple hours scratching my head trying to figure out why I couldn't get this code to run on my 12f683......that was all I needed.

    Thank you Bruce for the code snippets...can't wait for the book. I actually got started with micros about 10 years ago with the help of your website. I'm only coming back to working with them in the last few months, and your code is helping me again!

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


    Did you find this post helpful? Yes | No

    Default Re: Using hardware capture

    Hi Picone,

    Glad I could help, and welcome back.

    FYI: Darrel has a nifty include file you can use to disable all analog features by just including it in your code. See this thread http://www.picbasic.co.uk/forum/showthread.php?t=11100

    It's pretty handy when you forget to disable A/D it takes care of it for you.
    Regards,

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

  13. #13
    Join Date
    May 2004
    Location
    brighton
    Posts
    149


    Did you find this post helpful? Yes | No

    Default Re: Using hardware capture

    Hi Bruce
    i am trying to use your code on 18f452 but it seems to stop at start i must be missing something

    DEFINE LOADER_USED 1 ' uses a bootloader
    Include "Modedefs.Bas"

    Define OSC 20
    clear

    ' Setup Hardware for uart
    DEFINE HSER_BAUD 9600
    DEFINE HSER_RCSTA 90h
    DEFINE HSER_TXSTA 24h
    DEFINE HSER_CLROERR 1
    Symbol Capture = PIR1.2 ' CCP1 capture flag
    T1 VAR WORD ' 1st capture value
    PW VAR WORD ' 2nd capture value & ultimately final pulse width
    TRISC.2 = 1 ' CCP1 input pin (Capture input)
    INTCON.7 = 0 ' Interrupts off

    hserout [" Start Measure ",10,13 ]
    ReLoad:
    CCP1CON = 000101 ' Capture mode, capture on rising edge
    T1CON = 0 ' TMR1 prescale=1, clock=Fosc/4, TMR1=off (200nS per count @20MHz)
    TMR1H = 0 ' Clear high byte of TMR1 counter
    TMR1L = 0 ' Clear low byte
    T1CON.0 = 1 ' Turn TMR1 on here
    Capture = 0 ' Clear capture int flag bit
    While !Capture ' Wait here until capture on rising edge
    Wend

    ' Rising edge detected / stuff Timer1 value in T1
    T1.HighByte = CCPR1H
    T1.LowByte = CCPR1L

    CCP1CON.0 = 0 ' Configure capture for falling edge now
    Capture = 0 ' Clear capture interrupt flag bit

    While !Capture ' While here until capture on falling edge
    Wend

    ' Falling edge detected / stuff Timer1 value in PW
    PW.HighByte = CCPR1H
    PW.LowByte = CCPR1L

    PW = PW-T1 ' High pulse width = PW-T1
    ' Convert to uS for 20MHz osc with 200nS Timer1 ticks
    PW = (PW * 2)/10
    hserout ["uS High = ",dec PW,10,13 ]
    'DEBUG dec PW,"uS High",13,10 ' Output to RS232 display
    GOTO ReLoad

    END

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


    Did you find this post helpful? Yes | No

    Default Re: Using hardware capture

    Not sure what you mean by it seems to stop at start but timer1 is running a lot faster at 20MHz, and you don't mention how far it gets or what it shows as the result, so it's tough to help.

    Have you tried at 4MHz?
    Regards,

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

  15. #15
    Join Date
    May 2004
    Location
    brighton
    Posts
    149


    Did you find this post helpful? Yes | No

    Default Re: Using hardware capture

    Sorry Bruce
    But got it going now
    i meant it always displayed: start Measure on pc and no measurements but its ok now
    thanks for you support

    Isaac

Similar Threads

  1. mS Timer
    By whmeade10 in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 8th September 2020, 13:12
  2. Using CCP1 and CCP2 to measure instant fuel consumption
    By srspinho in forum mel PIC BASIC Pro
    Replies: 12
    Last Post: - 20th September 2008, 16:50
  3. Measuring change of frequency with PIC
    By Aussie in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 19th July 2007, 02:47
  4. Hardware capture on 16F876
    By MaxiBoost in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 4th April 2007, 20:19
  5. continious counting process (capture)
    By asynch in forum General
    Replies: 1
    Last Post: - 17th February 2006, 08:42

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