mS Timer


+ Reply to Thread
Results 1 to 7 of 7

Thread: mS Timer

  1. #1
    whmeade10's Avatar
    whmeade10 Guest

    Red face mS Timer

    I need to time an incoming pulse that can be anywhere from 35 to 1000 mS long. I am not sure weather to use the external interrupt B0 or the CCP1. I am using a 18F242 pic chip. Is it possible to set up T1 to overflow every 1mS and load the number of times it overflows between the Low to High pulse into a word variable. Will this work

    Set CCP1 to interrupt on low to high
    Set CCP2 to interrupt on high to low

    When CCP1 interrupts start T1
    When CCP2 interrupts place the number of times (every 1mS) that T1 overflows into a word variable then reset variable to 0 after use.

    Any sugestions....

  2. #2
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898

    Default

    it's up to you to decide... but my vote will go to the ccp method.

    Download the DS41214a app note from microchip. you'll find some good stuff in it.
    http://ww1.microchip.com/downloads/e...Doc/41214a.pdf
    Last edited by mister_e; - 20th July 2006 at 02:10.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

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

    Default

    Grab that app note Steve linked to. It's got some pretty cool stuff in it.

    This will save you a little time deciphering it;

    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
    
    ' Test signal:
    ' 12.04kHz pulse with 41uS high / 42uS low
    ' Input signal connected to RC2/CCP1 pin
    
        ' PIC18F242 @20MHz
        DEFINE OSC 20
        DEFINE DEBUG_REG PORTC
        DEFINE DEBUG_BIT 6 
        DEFINE DEBUG_BAUD 115200
        DEFINE DEBUG_MODE 0 ' 1 = inverted, 0 = true
    
        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 = 0           ' Interrupts off
        
    ReLoad:
        CCP1CON = %00000101  ' 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
    
        DEBUG dec PW,"uS High",13,10	' Output to RS232 display
        GOTO ReLoad
        
        END
    I ran it with a 2nd PIC delivering a 12.04kHz signal: HPWM 1,127,12000 to the
    18F242 CCP1 pin. 41uS high, 42uS low.

    It's spot-on. Returns 41uS High on MCS serial terminal. Fluke ScopeMeter 123
    shows precisely the same timing.

    Much nicer than pulsin, count, etc..

    Darrel Taylors' instant interupts works perfect for this.
    Code:
    ' PIC18F242 @20MHz
    DEFINE OSC 20
    DEFINE DEBUG_REG PORTC
    DEFINE DEBUG_BIT 6 
    DEFINE DEBUG_BAUD 115200
    DEFINE DEBUG_MODE 0 ' 1 = inverted, 0 = true
    
    OverFlows  VAR BYTE ' Timer1 overflow total
    Remainder  VAR WORD ' Remaining Timer1 ticks after falling edge capture
    
    INCLUDE "DT_INTS-18.bas"       ; Base Interrupt System
    INCLUDE "ReEnterPBP-18.bas"    ; Include if using PBP interrupts
    
    ;----[High Priority Interrupts]----------------------------------------
    ASM
    INT_LIST  macro    ; IntSource,   Label,   Type, ResetFlag?
            INT_Handler   CCP1_INT,  _Capture,  PBP,  yes
            INT_Handler   TMR1_INT,  _Timer1,   PBP,  yes
        endm
        INT_CREATE               ; Creates the High Priority interrupt processor
    ENDASM
    
    CCP1CON = %00000101  ' Capture mode, capture on rising edge
    T1CON = 0            ' TMR1 prescale=1, clock=Fosc/4, TMR1=off (200nS per count @20MHz)
    @    INT_ENABLE  CCP1_INT    ; enable Capture interrupts
    
    Main:    
        IF T1CON.0 = 0 THEN ' If done, show result
          DEBUG "Timer Overflows = ",DEC OverFlows
          DEBUG " Remaining ticks = ",dec Remainder,13,10
        ENDIF
        PAUSE 2000
        @    INT_ENABLE  CCP1_INT     ; Start new capture
        GOTO Main
    
    '---[CCP1 - interrupt handler]------------------------------------------
    Capture:
       IF CCP1CON = %00000101 THEN     ' If rising edge capture then
         TMR1L = 0                     ' Clear Timer1 counts
         TMR1H = 0
         T1CON.0 = 1                   ' Turn Timer1 on at rising edge capture
         OverFlows = 0                 ' Clear over flow counts
         Remainder = 0                 ' Clear remainder
         CCP1CON = %00000100           ; Switch to falling edge capture
         PIR1.0 = 0                    ; Clear Timer1 overflow flag before enable
         @    INT_ENABLE  TMR1_INT     ; Enable Timer 1 Interrupts 
         GOTO OVER_CCP                 ; Done, exit
       ENDIF
       
       IF CCP1CON = %00000100 THEN     ; If falling edge capture then
         T1CON.0 = 0                   ; Stop Timer1
         CCP1CON = %00000101           ; Switch back to rising edge capture
         @    INT_DISABLE  TMR1_INT    ; Disable Timer 1 Interrupts
         @    INT_DISABLE  CCP1_INT    ; Disable CCP1 Interrupts
         Remainder.LowByte = TMR1L     ; Get remaining Timer1 counts on falling edge
         Remainder.HighByte = TMR1H
       ENDIF
    OVER_CCP:
    @ INT_RETURN
    
    '---[TMR1 - interrupt handler]---------------------------------------------
    Timer1:
        OverFlows = OverFlows + 1
    @ INT_RETURN
    
         END
    Input for testing was a 2nd PIC providing a 30mS pulse followed by a 1000mS
    pulse with a 5 second delay between each.

    For the 30mS pulse it displays: Timer Overflows = 2 Remaining ticks = 19048

    The total pulse width: (2 * 65536 * 200nS) + (19048 * 200nS) = 30.0242mS

    For the 1000mS pulse: Timer Overflows = 76 Remaining ticks = 19480
    So: (76 * 65536 * 200nS) + (19480 * 200nS) = 1.0000432 S

    Darrels interrupt routines are pretty handy.
    Last edited by Bruce; - 20th July 2006 at 15:47.
    Regards,

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

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

    Default

    And then there's the old fashioned way..;o}
    Code:
    ' PIC18F242 @20MHz
    DEFINE OSC 20
    DEFINE INTHAND Capture   ' Context saving for High Priority Ints
    DEFINE DEBUG_REG PORTC
    DEFINE DEBUG_BIT 6 
    DEFINE DEBUG_BAUD 115200
    DEFINE DEBUG_MODE 0      ' 1 = inverted, 0 = true
    
    OverFlows  VAR BYTE BANKA SYSTEM ' Timer1 overflow total
    Remainder  VAR WORD BANKA SYSTEM ' Remaining Timer1 ticks after falling edge capture
    Ready      VAR BYTE BANKA SYSTEM ' Indicates pulse width measurement is complete when 1
    Ready = 0
    
    ReStart:
        CCP1CON = %00000101  ' Capture mode, capture on rising edge
        T1CON = 0            ' TMR1 prescale=1, clock=Fosc/4, TMR1=off (200nS per count @20MHz)
        RCON.7 = 1           ' Enable priority interrupts
        PIE1.0 = 0           ' Disable Timer1 over flow interrupt
        PIE1.2 = 1           ' Enable CCP1 interrupt
        PIR1 = 0             ' Clear any pending interrupt flags
        PIR2 = 0             ' before enabling global
        INTCON.7 = 1         ' Enable all unmasked interrupts
    
    Main:    
        WHILE !Ready         ' While not ready, wait
        ' Do other stuff here if needed
        WEND
        
        ' Result is ready
        DEBUG "Timer Overflows = ",DEC OverFlows
        DEBUG "Remaining ticks = ",DEC Remainder,13,10
        Ready = 0
        
        PAUSE 2000
        GOTO ReStart
    
    '---[CCP1 & Timer1 - interrupt handler]------------------------------------------
    ASM
    Capture
        btfsc PIR1,TMR1IF         ; Timer1 interrupt?
        bra   T1_Int              ; Yes. Goto T1_Int
        bcf   PIR1,CCP1IF         ; No it's a capture int so clear capture int flag
        btfss CCP1CON,0           ; Rising edge capture?
        bra   FallingEdge         ; No. Skip to falling edge capture
        clrf  TMR1H               ; Yes. Clear high count
        clrf  TMR1L               ; Clear low count
        bsf   T1CON,0             ; Turn Timer1 on at rising edge capture
        clrf  OverFlows           ; Clear over flow count
        clrf  Remainder           ; Clear remainder count
        bcf   PIE1,CCP1IE         ; Disable capture interrupt before switching
        bcf   CCP1CON,0           ; Switch to falling edge capture
        bcf   PIR1,0              ; Clear Timer1 overflow flag before enable
        bsf   PIE1,TMR1IE         ; Enable Timer1 Interrupt
        bsf   PIE1,CCP1IE         ; Re-enable capture interrupt
        bra   OVER_CCP            ; Done, exit
        
    T1_Int
        bcf   PIR1,TMR1IF         ; Clear Timer1 overflow flag
        incf  OverFlows,f         ; Increment over flow count
        bra   OVER_CCP            ; Done, exit
           
    FallingEdge
        bcf   T1CON,0             ; Stop Timer1
        bcf   PIE1,CCP1IE         ; Disable CCP1 interrupt
        bcf   PIE1,TMR1IE         ; Disable Timer1 interrupt
        bsf   CCP1CON,0           ; Switch back to rising edge capture
        movff TMR1L, Remainder    ; Get low byte on falling edge
        movff TMR1H, Remainder+1  ; Get high byte
        bsf   Ready,0             ; Indicate process is complete
     
    OVER_CCP
        retfie fast               ; Done, return
    ENDASM
    
         END
    Last edited by Bruce; - 20th July 2006 at 18:10.
    Regards,

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

  5. #5
    Join Date
    Feb 2008
    Location
    Michigan, USA
    Posts
    227

    Default Re: mS Timer

    Hi All,

    Working through a similar issue trying to time a couple of events and looking for some clarification.
    In this explanation, and in the tips and tricks there is this line:

    "2. Setup Timer1 so it will not overflow during max pulse width time".

    Yet the amount of overflows is how you're measuring the pulse. What am I overlooking here, and why mention that?

    I'm on a 12F683 and have been trying to use GPC_INT (Interupt on change) to do this, while keeping within one cycle of TMR1 and it has limitations. Using the overflow count and remainder looks like a much better idea. I'm going to crank through it that way and see if it solves my problem, I am just confused about that line.

    Thanks
    bo

  6. #6
    Join Date
    May 2013
    Location
    australia
    Posts
    1,731

    Default Re: mS Timer

    that post has two separate methods , one measures the pulse width with timer counts the other by timer overflows
    This is more entertaining than Free to Air TV

  7. #7
    Join Date
    Feb 2008
    Location
    Michigan, USA
    Posts
    227

    Default Re: mS Timer

    Thank you Richard, I have few arenas that bring out self doubt as quickly as trying to muscle one of these little buggers.
    I almost have it rewritten using this scheme. I hope to test it when I get back to the shop.
    bo

Similar Threads

  1. Elapsed Timer Demo
    By Darrel Taylor in forum Code Examples
    Replies: 111
    Last Post: - 29th October 2012, 17:39
  2. High Resolution Timer & Speed Calculator
    By WOZZY-2010 in forum Code Examples
    Replies: 4
    Last Post: - 7th February 2010, 16:45
  3. Timer + rc5
    By naga in forum mel PIC BASIC Pro
    Replies: 8
    Last Post: - 19th November 2009, 07:56
  4. Timer interrupt frequency
    By Samoele in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 17th January 2009, 23:49
  5. timer interupt help 16f73
    By EDWARD in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 3rd July 2005, 08:41

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts