Counting Timer0 and Timer1 overflows without any interrupt handler


Closed Thread
Results 1 to 33 of 33

Hybrid View

  1. #1
    Join Date
    Jan 2007
    Posts
    78

    Default Counting Timer0 and Timer1 overflows without any interrupt handler

    Hi Gang,
    Today, I played around and got a couple of programs running on a 16F877A. One program monitors internal Timer1 overflows and flips a port bit every 210 counts, to produce a 1 second clock pulse. And this without an interrupt handling routine.

    (snippet)
    'setup option register for TMR0
    option_reg = %01010111 ' interrupt w/max

    mainloop:
    if TMR0 = 255 THEN
    counting = counting + 1
    if counting = 210 then
    counting = 0
    PORTD = PORTD ^ %00000001 'flip bit 0 for a clock
    endif
    endif
    goto mainloop


    The other program sets Timer1 up with pin-15 as its clock source, with prescaler=8. The main-loop starts Timer1, pauses for 1 second then turns off Timer1. Then displays the max count held within TMR1, which is offcourse <= 65535 with a max frequency input of 500khz. And this without an interrupt handling routine.

    So here is what I'm wondering:
    What I think I should be able to do is count in the main-loop, both Timer0 and Timer1 overflows. Timer0 clocking from internal source. Timer1 clocking from pin 15.
    When timer0 overflow count = 210, then exit out of the loop, turn off Timer1 and process Timer1's overflow count.

    The number of Timer1 overflows will act as a multiplier value.
    An overflow count of 2, for example would represent an clock input frequency of a little over 1mhz.

    Wondering how realistic you think my plan might be?
    I hoping to code a frequency counter that will count up to 30mhz without having to use an external ripple counter.

    Big thanks!!
    dw

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


    Did you find this post helpful? Yes | No

    Default Re: Counting Timer0 and Timer1 overflows without any interrupt handler

    Hi,
    Just a couple of random notes:

    Doing IF TMR0=255 may not be the best. The reason for that is that your program may be off doing something else while TMR0 "transitions thru" 255, ie the program checks it and it's 254 next time it checks it's 0. TMR0 has overflowed but your program missed it. In THIS particular case your program is fairly "tight" so it likely runs faster than the increment rate of TMR0 but if/when you add stuff to the loop it may not work so well. Instead, check the TMR0IF, it'll get set when the timer overflows (even if you're not actually using interrupts) - just remember to clear it again.

    I'm not sure TMR1 can cope with a frequency as high as 30MHz, check the electrical specifications in the datasheet.

    /Henrik.

  3. #3
    Join Date
    Jan 2007
    Posts
    78


    Did you find this post helpful? Yes | No

    Default Re: Counting Timer0 and Timer1 overflows without any interrupt handler

    Thank you Henrik!
    Much appreciate your knowledge of the devices!
    I just read in MicroChips DS33023A section 8 on interrupts that the interrupt flag bit gets set regardless of the corresponding enable bit setting. So yes, I can see that monitoring the flag bit allows for processing that condition while the timer is still running towards its next overflow. Just "as you mentioned" zero the flag bit until the next one.
    I'm hoping I can track both timer overflows without having to code the main loop in asm.
    I'll try it :-]
    Check Timer0 with TMR0IF status and Timer1 with PIR1.0 status.
    Thanks!!!! :-]

  4. #4
    Join Date
    Jan 2007
    Posts
    78


    Did you find this post helpful? Yes | No

    Default Re: Counting Timer0 and Timer1 overflows without any interrupt handler

    The following PBP3 code is my first attempt at coding for a frequency counter that can read above 500khz. The goal was to see if it could accurately capture frequency below 30mhz without using a frequency-prescaler, or ripple-counter. It does work, but its not accurate enough to be considered anything but educational or a fun project.
    Code:
    '  Code for 16F877A to count frequency
    '  Uses TMR0 and prescaler to gate 1 second counting time, internally clocked.
    '  Uses Timer1, external clock, from PIN 15  
    '  WDT, Analog, Comparitors OFF
    
    clear
    define loader_used 1
    define osc 4
    
    ' Define LCD registers and bits
    Define LCD_DREG PORTD
    Define LCD_RSREG PORTE
    Define LCD_RSBIT 0
    Define LCD_EREG PORTE
    Define LCD_EBIT 1
    define LCD_RWREG PORTE
    define LCD_RWBIT 2
    define LCD_BITS 8
    define LCD_LINES 2
    define LCD_COMMANDUS 2500
    define LCD_DATAUS 100
    
    TRISC = %11110001    'using pin 15 as input for frequency
    TRISD = 0            'PORTD all outputs
    PORTD = 0
    CMCON = 7            'disable comparators
    ADCON1 = 7           'PORTA and E digital
    
    
    'setup option register for TMR0
    option_reg.7 = 0
    option_reg.6 = 1     '1 for interrupts active
    option_reg.5 = 0
    option_reg.4 = 1     '1 for interrupts active 
    option_reg.3 = 0     'Assign prescaller to TMR0
    option_reg.2 = 1     'prescaler 0-15
    option_reg.1 = 1     'with this setting TMRO-Rate = 1:256
    option_reg.0 = 1
    
    'Prescaller settings for option_reg
    'option_reg 01011000 = 1:1 prescaler TMR0 roles over every 1mSec 
    'option_reg 01010000 = 1:2 prescaler TMR0 roles over every 152 uSec
    'option_reg 01010001 = 1:4 prescaler TMR0 roles over every 1mSec
    'option_reg 01010010 = 1:8 prescaler TMR0 roles over every 2mSec
    'option_reg 01010011 = 1:16 prescaler TMR0 roles over every 4mSec
    'option_reg 01010100 = 1:32 prescaler TMR0 roles over every 8mSec
    'option_reg 01010101 = 1:64 prescaler TMR0 roles over every 16mSec
    'option_reg 01010110 = 1:128 prescaler TMR0 roles over every 32mSec
    'option_reg 01010111 = 1:256 prescaler TMR0 roles over ever 64mSec
    
    INTCON.7 = 0   'disable interrupt routine on overflow
    INTCON.5 = 0   'disable interrupt routine on Timer0 overflow
    INTCON.4 = 0   'disable RB0 external interrupt function
    INTCON.3 = 0   'disable port change interrupt function
    INTCON.1 = 0   'not really needed, but clear possible pin change flag
    
    T1CON = %00110010 'Timer1 prescaler = 8 - osc off- sync on, external source
    
    lcdout $fe,1 'clear the display
    lcdout "Frequency Counter"
    pause 1000
    
    Tmr1flg var word
    counting var byte
    calc var byte
    mhz var byte
    khz var word
    hz var word
    
    PORTD = 0     'We will be setting PORTD.0 high through the 1 second
                  'gate-period to monitor it with Oscope
    INTCON.2 = 0  'Clear Timer0 interrupt flag
    TMR1 = 0      'Reset Timer0 counting value
    
    ' Main program loop
    mainloop:
    Tmr1flg = 0   'Clear variable which counts Timer1 overflows
    TMR1H = 0     'clear Timer1 high register 
    TMR1L = 0     'clear Timer1 low register
    PIR1.0 = 0    'clear Timer1 overflow flag bit
    INTCON.2 = 0  'Clear Timer0 interrupt flag
    TMR1 = 0      'Reset Timer0 value
    counting = 0
    
    PORTD.0 = 1       'raise the 1 second timer flag
    T1CON.0 = 1       'start Timer1
    
    while counting < 15   'Timer0 has to overflow this many times for 1 second gate period
    while INTCON.2 = 0    'watch for Timer1 overflow and count if it occurs.
    if PIR1.0 = 1 then     'if Timer1 overflow flag is up then 
    Tmr1flg = Tmr1flg + 1   'increment overflow count by 1. Each count represents value of 524280
    PIR1.0 = 0              'Now reset the Timer1 overflow flag bit
    endif
    wend                    'end of inner while loop
    INTCON.2 = 0            'Now reset the Timer0 overflow flag bit
    counting = counting + 1  'increment counting for gate time
    wend                     'end of outer while loop
    
    T1CON.0 = 0 'stop Timer1
    PORTD.0 = 0 'lower the 1 second timer flag representing the gate period
    
    
    ' calculations to get the numbers captured to the display
    ' we have to feed the number of Timer1 overflows into Mhz, Khz, hz
    ' Then we feed the Timer1 remaining count * 8 in as well
    ' and parse it out to mhz khz hz
    hz = 0
    khz = 0
    mhz = 0
    
    ' Add Timer1 overflow values into Mhz, Khz, hz
    if Tmr1flg > 0 then
    for calc = 0 to Tmr1flg
    khz = khz + 524
    hz = hz + 280
    
    while hz > 999
    khz = khz + 1
    hz = hz -1000
    wend
    while khz > 999
    mhz = mhz + 1
    khz = khz - 1000
    wend
    next
    endif
    
    ' Add remaining Timer1 count * 8 into Mhz, Khz, hz
    for calc = 0 to 7
    hz = hz + TMR1
    
    while hz > 999
    khz = khz + 1
    hz = hz -1000
    wend
    
    while khz > 999
    mhz = mhz + 1
    khz = khz - 1000
    wend
    next
    
    'Display results
    if mhz > 0 then 
    lcdout $FE,1,#mhz,".",#khz,".",#hz
    else
    lcdout $FE,1,#khz,".",#hz
    endif
    
    pause 2000
    goto mainloop   ' Go get another reading
    End
    
    Last edited by Archangel; - 4th February 2014 at 00:06.

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


    Did you find this post helpful? Yes | No

    Default Re: Counting Timer0 and Timer1 overflows without any interrupt handler

    Quote Originally Posted by dw_picbasic View Post
    The following PBP3 code is my first attempt at coding for a frequency counter that can read above 500khz...
    It does work, but its not accurate enough to be considered anything but educational or a fun project.
    Since it's not a problem for the PIC chip, or for PBP ...
    Will there be a Second Attempt?

    I'd hate to interfere with the learning process.

    But I would suggest using the Timer0 input (T0CKI) for the frequency to be measured.
    The Timer0 prescaler has a minimum period of 20nS, which means it can take up to 50Mhz.
    Timer1 (T1CKI) can only take up to 1Mhz with a 4Mhz OSC, or 5Mhz with a 20Mhz OSC.

    Any frequency measurement requires an accurate "Time Base".
    And the easiest way to get that is to use a 32768 Hz crystal on the Timer1 oscillator.
    This way, Timer1 generates the 1 sec window, and Timer0 (and it's overflows) counts the frequency.

    It is a little tricky to read the Timer0 prescaler to get the lowest byte of the count though.
    The prescaler should be 1:256 (the default).

    Oh, and the PICs oscillator should be as fast as possible, so that the program can respond to the hardware flags, which have to be polled.
    The fastest oscillator for the 16F877A is 20 Mhz.

    A simulation works good up to 600Kz. Reading the exact Hz. (actual results will depend on the 32768 crystal tolerance)
    A real chip should go much higher, but the SIM crashes with the higher frequency.

    Name:  FREQy.jpg
Views: 8899
Size:  106.5 KB

    Sometimes you just need to know it can be done ... so you can figure it out on your own.
    DT

  6. #6
    Join Date
    Jan 2007
    Posts
    78


    Did you find this post helpful? Yes | No

    Default Re: Counting Timer0 and Timer1 overflows without any interrupt handler

    Darrel,
    That's an ***AWESOME*** post!!
    It hadn't occurred to me to flip the timers around that way.
    Also, I need to go back to the data sheet and look at the electrical characteristics again for timer0 clock minimum pulse width.
    Per your info about the 20nSec I need to read through that again.
    I definitely want to try it!!
    This will be the first time, for me learning to setup Timer1 with external crystal for time base.
    Perhaps I would do well reading up on how that functionality is used for a standard 12hour clock.

    Also, what simulator are you using?
    It looks totally awesome!!
    Many thanks
    Duane :-]

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


    Did you find this post helpful? Yes | No

    Default Re: Counting Timer0 and Timer1 overflows without any interrupt handler

    The simulator is Proteus VSM from Labcenter in the UK.
    It's a bit pricey, but does an amazing job. Couldn't do my job without it.

    And I just want to point out how I have RA3 and RA4 tied together in the above schematic.
    It's a very important part of making the freq. counter work.
    DT

Similar Threads

  1. Expanding Timer1 counting range
    By sycluap in forum mel PIC BASIC Pro
    Replies: 14
    Last Post: - 3rd February 2014, 22:00
  2. PIC18 timer0 interrupt handler, still not getting it
    By ImAnEE in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 30th April 2011, 00:25
  3. DT-INTs Interrupt handler question
    By circuitpro in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 8th January 2010, 00:06
  4. Synchronising Timer0 and Timer1
    By manxman in forum mel PIC BASIC Pro
    Replies: 8
    Last Post: - 9th April 2008, 23:12
  5. 16F690 TIMER0 and TIMER1
    By nickdaprick in forum mel PIC BASIC
    Replies: 2
    Last Post: - 18th April 2007, 14:49

Members who have read this thread : 3

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