0
\$\begingroup\$

I want to count pulses using PIC16f877A. The pulses are being fed into pin RA4. I want to use timer interrupt for that so that other functions performed by the micro controller should not disturbed. The frequency is displayed on a LCD Screen.

I want to understand the programming. What happens when a pulse of frequency signal reaches at T0CK1 pin of the PIC16f877A. Will it cause an interrupt? So should I define interrupt for that? Kindly help me with Mikro C code.

Here is the code as it stands:

//Timer 0 will count and Timer 1 will measure 1 second time using interrupts ; mikro=16f877a
// OUTPUTS

#define led PORTB.F2

sbit LCD_RS at RD5_bit;
sbit LCD_EN at RD4_bit;
sbit LCD_D4 at RC4_bit;
sbit LCD_D5 at RC5_bit;
sbit LCD_D6 at RC6_bit;
sbit LCD_D7 at RC7_bit;

sbit LCD_RS_Direction at TRISD5_bit;
sbit LCD_EN_Direction at TRISD4_bit;
sbit LCD_D4_Direction at TRISC4_bit;
sbit LCD_D5_Direction at TRISC5_bit;
sbit LCD_D6_Direction at TRISC6_bit;
sbit LCD_D7_Direction at TRISC7_bit;
//=======End LCD Connections=============================================
unsigned int x=0,frq=0, cnt=0;

void interrupt()
{
 if(PIR1.TMR1IF)
 {
 T1CON.TMR1ON=0; //stop
 TMR1L=0XEE; // <------------- reload the timer
 TMR1H=0X85;


 if(cnt>=4)
 {
 led=~led;
 frq=1;
 cnt=0;
 x=tmr0;
 tmr0=0;
 }



 //frq=1;
 PIR1.TMR1IF=0; // <------------- clear the timer interrupt flag
 }



}

void main()
{
 OPTION_REG=0xA0; // for timer 0; NO presscaller; counter mode at T0CKI
 T1CON=0X60; // 1:8 prescallar, timer off
 ADCON1=0x07; // adc reg initialization ; changes port a to digital I/O
 INTCON=0x80; // globle interrupt enabled
 TMR1L=0xEE;
 TMR1H=0x85;
 T1CON.TMR1ON=1; // timer on
 PIR1.TMR1IF=0;
 TRISA.f4=1;// making ra4 as input


 x=0;
 frq=0;
 lcd_init();
 Lcd_Cmd(_LCD_CLEAR); // Clear display
 Lcd_Cmd(_LCD_CURSOR_OFF);
 Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT); //*/

 Lcd_Out(1,1,"Frequency");
 while(1)
 {
 if(frq==1)
 {
 Lcd_Out(2,2,X);
 Lcd_Out_CP("Hz");
 frq=0;
 }
 }

}
\$\endgroup\$
3
\$\begingroup\$

There are two different common methods to measure frequency with this PIC. Which one is appropriate depends on things you haven't told us, like the minimum and maximum frequency.

The conceptually simple way is to do a frequency counter. Hardware can assist here in that you can have a external signal increment timer 0 or timer 1. Then the firmware reads the timer at known intervals, and the rest is simple math. Note that you do NOT want to reset the timer after each read. Simply do a unsigned integer subtract of the new reading minus the previous and you get the counts in the last interval.

You have to keep timer overflow in mind. Timer 0 is 8 bits and timer 1 16 bits. If using timer 0, for example, you have to be sure that the sampling period is short enough so that there are less than 256 cycles per period at the highest input frequency. With timer 1 you get a lot more room since it's 16 bits wide. You can therefore allow up to 65535 cycles per sampling period.

The other way to measure frequency is to actually measure the period of individual cycles or groups of cycles. This is best done by using one of the CCP modules in capture mode. Timer 1 is set up as a free running timer, and the CCP module takes a snapshot of it every 1, 4, or 16 periods of the external signal. In the CCP interrupt, you subtract the new capture reading minus the previous to get the time duration of the external period (or 4 or 16 periods), and the rest is math.

The CCP capture method is usually more accurate and responsive, but more tricky to implement and to deal with all the corner cases. With this method you have to worry about timer overflow for low input frequencies, not high. I usually deal with this by grabbing the timer value periodically faster than it can wrap, and effectively extending the timer to a arbitrary number of bits in firmware.

\$\endgroup\$
  • \$\begingroup\$ Will the timer get reset when a capture happens? then it would be easy to measure the frequency. \$\endgroup\$ – noufal Oct 10 '13 at 11:41
  • 1
    \$\begingroup\$ @noufal: No, and there is no need for it to reset. Simply do a unsigned integer subtract of the latest reading minus the previous reading and you get the number of clock ticks in the period. This works regardless of whether the timer wrapped from 65535 to 0 during the interval. The only contraint is that there not be more than 65535 ticks in the interval. \$\endgroup\$ – Olin Lathrop Oct 10 '13 at 12:51
  • \$\begingroup\$ Yeah, that's correct... one more thing, in the PWM module the equation for the time period of the pulse is given as PWM Period(T) = (PR2 +1) * 4Tosc * TMR2 Prescale Value, where does that +1 come from ? \$\endgroup\$ – noufal Oct 11 '13 at 5:22
  • \$\begingroup\$ @noufal: The 1 is because the counter counts to the period value, then resets to 0 on the next cycle. That means there are PR2+1 counts in one interval. \$\endgroup\$ – Olin Lathrop Oct 11 '13 at 11:19
  • \$\begingroup\$ I got it. ie, if we want 256, we need to give only 255, because there are 256 counts in 0-255, isn't it? \$\endgroup\$ – noufal Oct 11 '13 at 11:34
0
\$\begingroup\$

There is a very good built-in Capture and Compare (CCP) module in 16F877A, but it uses the RC2/CCP1 pin as interrupt source. When an event occures, the Capture module, copies the current value of TIMER1 module. I think this is the better soulution for a frequency counter.

From Datasheet,

In Capture mode, CCPR1H:CCPR1L captures the 16-bit value of the TMR1 register when an event occurs on pin RC2/CCP1. An event is defined as one of the following:

• Every falling edge

• Every rising edge

Every 4th rising edge

• Every 16th rising edge

The type of event is configured by control bits, CCP1M3:CCP1M0 (CCPxCON<3:0>). When a capture is made, the interrupt request flag bit, CCP1IF (PIR1<2>), is set. The interrupt flag must be cleared in software. If another capture occurs before the value in register CCPR1 is read, the old captured value is overwritten by the new value.

Now to your question,

The T0CK1 pin is not to interrupt the program. It is used as the timer clock pulse which incriments the timer value, and the interrupt will be generated only when the timer rolls over from maximum to 0(0XFFF -> 0X0000)

\$\endgroup\$

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.