I need to count external clock pulses for a predefined time using PIC16f877a. I don't know what to use, whether counter or timer or both. I don't know to use timer and counter modules of PIC16f877a. Please help me!!


To count how many pulses occur during a specified time interval, use two counter/timer modules. (This technique is not specific to Microchip PIC16F877A, and can be adapted to other microcontrollers with counter/timer modules.)

  1. Configure one counter/timer as counter (clock source = external pin).
  2. Configure another counter/timer as interval timer (clock source = instruction clock).
  3. Clear the counter.
  4. Enable the timer and the counter (at the same time, if possible).
  5. As soon as the timer interval completes, disable the counter and read the count.

For lowest latency, you can test for timer interval complete by polling the appropriate flag bit in the timer register -- but your firmware will not be able to do anything else while making the measurement.

For best multitasking (firmware performing other actions while timer/counters are measuring the pulses), use an interrupt handler to detect the timer interval complete. There will be some latency due to the interrupt handling system, be sure to read the interrupts section of the datasheet.

Because the pulses come from an external source, there will typically be 2-3 stages of D flip flops to synchronize the input with the CPU clock. This is required to prevent issues with metastability, but does introduce a delay of a few clock cycles. As far as I know nobody has ever come up with a better way to protect against metastable failures, so you just have to compensate for the delay if it is important in your application.

Some timer/counter modules have an 8-bit counter, some are 16-bit. And some have a prescaler. So there could be several possible ways to implement the basic technique on your microcontroller, with different performance tradeoffs. You must consult the microcontroller's datasheet to determine the details.

Often timer/counter modules support other specialized activity, such as serial communications (baud rate) or watchdog timer. If your firmware is already using timer/counter modules, be sure to account for this as these are a limited on-chip resource.

It's also possible to use external counters, but adding more ICs somewhat defeats the purpose of using a microcontroller.

Microchip PIC16F877A datasheet is here -- by the way, PIC16F877A is NRND (Not Recommended for New Designs), and Microchip is recommending PIC16F887 as replacement.


Use a timer and configure it to clock on the timer input pin. You have 3 timers, Timer0, Timer1, and Timer2. Timer1 is 16 bit and all are both timer/counters with prescalers.

From page 23 of 234 from the datasheet, you can set T0CS (bit 5 of the Option_Reg register) to 1, which transitions on the RA4/T0CKI pin. Bit 4, T0SE selects the edge the transition will occur on, bit 3 "PSA" assigns the prescaler to either the watch dog timer or Timer0 module. Select the prescale values with PS2:PS0, bits 2-0 of this register, the table defines what the frequency will be divided by.

Pin RA4 is multiplexed with Timer0, also all PORTA pins are muxed with analog inputs (so don't forget to disable the ADC peripheral.)

The timer will generate an interrupt when it overflows, so you will have a timer interrupt routine, and clear the bit.

You will generally need to do the following: 1) understand how to configure the timer with the settings you want 2) write a routine to do that 3) create an interrupt routine.

Starting on Page 54 of the datasheet will give you an idea of how to configure the timer for the settings you want, namely writing certain values to certain registers (so you will have to know how to write values to a register.) The interrupt routine will have an interrupt vector, you can also find a list of interrupt vectors buried very deep in the compiler folder that comes with MPlab 8, search for it on your computer (it installs there by default.) In general the interrupt for this device should be as follows:

void interrupt Timer0_ISR(void) { //do some code here T0IF=0;//clear the interrupt flag }

What I highly recommend is reading the Timer documents provided by Microchip; documents DS51682A and DS51702A which can be found on the Microchip website and you should be set after going through these, they aren't very long but you will understand how they work.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.