Continue to Site

Pic16f877a timer interrupt

Status
Not open for further replies.

imranahmed

Advanced Member level 3
Please let me know that i want to make RPM meter or Tachometer but I successfully programmed external interrupt but problem in timer interrupt how to generate interrupt on our desire time like i want generate timer every 1 sec.Can anyone interested to tell me?

Timer is related to the internal frequency which is always Fosc/4.

Clock source frequency (Crystal)
if, Fosc = 12 MHz = 12000000 Hz

Therefore, Timer frequency :

FTimer = Fosc / 4 = 12000000 / 4 = 3000000 Hz = 3 MHz

If Prescaler = 1:256, then

FTimer = 3000000 / 256 = 11718.75 Hz

So, the time interval :

TTimer = 1 / FTimer = 1 / 11718.75 = 85 us (microseconds)

This means that when Timer runs, it will take 85 usecs to increment its value at every count.
To calculate the value to be filled in Timer rolling over register to generate 1 sec delay :

No. of count for 1 sec Delay = 1sec / 85 us = 11718.75 = 2DC6H

So the value to be filled in Timer’s 16 bit register = FFFF – 2DC6
= D239

so you need to load, TMR1H = 0xD2 . TMR1L = 0x39 .

Calculate the delay according to your crystal.

Best wishes

imranahmed

imranahmed

Points: 2
Helpful Answer Positive Rating
#include<htc.h>
#include<pic.h>
__CONFIG(FOSC_HS & WDTE_OFF);
#define _XTAL_FREQ 12000000
unsigned char x,COUNT=0;
interrupt led()
{
if (PIR1bits.TMR1IF==1)
{
PIR1bits.TMR1IF=0;
++COUNT;
}
}
void main()
{
CMCON=7;
ADCON1=7;
TRISC=0;
T1CON=0b00000101;
PIR1=0b00000001;
PIE1=0b00000001;
OPTION_REG=0b11000000;
INTCON=0b11000000;
TMR1H=0xD2;
TMR1L=0x38;
while(1)
{
PORTC=COUNT;
}
}

I wrote this above code but PORTC value cannot increase after 1 sec delay it increases fast.

you have to use interrupt routine as

if (PIR1bits.TMR1IF==1)
{
PIR1bits.TMR1IF=0;
count++;
TMR1H = 0xD2; // you have to load the timer value in the interrupt routine also
TMR1L = 0x38;
}

imranahmed

imranahmed

Points: 2
Helpful Answer Positive Rating
Ok Thanks.

For RPM meter, external and timer interrupts both would be used or only one can do job.

hello

You can use 2 timers
Timer1 for One seconde reference using interrupt
Timer0 as counter on RA4 (in 16 bits mode better)
Code:
if (PIR1bits.TMR1IF==1)
{
PIR1bits.TMR1IF=0;
count++;
TMR1H = 0xD2; // you have to load the timer value in the interrupt routine also
TMR1L = 0x38;
Flag=1;  // flag to say 1sec elapsed
Timer1bits.TMR1ON=0; // stop timer1
}

.. to do ...
use a long int for Count
init timer0 for counting on RA4
count on rising or falling edge...

Code:
while(1)
{
Count=0;
Timer0=0; // init value timer0 to zero
Timer0.bits.TMR0ON=1; // enable counting
// wait fro one second
while(Flag==0)
{
if (Timer0.bits.TMR0IF==1)
{
Count=Count+65535;  // sumarize all counter overflows
Timer0.bits.TMR0IF=0;
}
}
Flag=0;
Value=value + (long) Timer0; // add the rest inside the timer0
/*
here you have the nb of pulses during 1 seconde..
Count is in Hertz
then convert to RPM
and display
*/
}

if (PIR1bits.TMR1IF==1)
{
PIR1bits.TMR1IF=0;
count++;
TMR1H = 0xD2; // you have to load the timer value in the interrupt routine also
TMR1L = 0x38;
}

I write values in interrupt function but 1 sec delay cannot achieve.

Timer1 does not have prescaler of 256. check datasheet section "Timer1 Module".
Above i have explained you how to calculate. Dont use those values. Calculate it .

imranahmed

imranahmed

Points: 2
Helpful Answer Positive Rating
OOh,
OK i am doing this.

I did this,

Fosc=2MHz/4 = 500000

prescaler is 8 ====>> 500000/8 = 62500 then

65535-62500 = 3035 = 0BDB ====> 0BH and DBL.

But 1 sec delay cannot achieve, One thing let me know that the bit T1OSCEN would 1 or 0.Please tell me.

YES, TIMER1 INTERRUPT WORK SUCCESSFULLY THANKS TO ALL.

Last edited:

hello,

on this PIC the prescaler on timer1 cannot be set to 1/256
you are using 00 => prescale =1/1
try T1CON=0b00110101; // precaler maxi = 1/8
so modifie the precount value:
18660 = 0x48E4 => 125mS
and count 8 times x 125ms => to get 1seconde

and Timer0 is also 8bits counter !!!

Code:
volatile int Sec ; // compteur de secondes
volatile int count;
volatile int Flag;

if (PIR1bits.TMR1IF==1)
{
PIR1bits.TMR1IF=0;
count++;
TMR1H = 0x48; // you have to load the timer value 18660 in the interrupt routine also
TMR1L = 0xE4;
if (count>8)
{
Flag=1;  // one second elapsed used for TMR0 counting
count=0;
Sec ++; // increment secondes
}
}

void main()
{
Sec=0;
count=0;
......
while(1)
{
Count=0;
Timer0=0; // init value timer0 to zero
Timer0.bits.TMR0ON=1; // enable counting
// wait fro one second
while(Flag==0)
{
if (Timer0.bits.TMR0IF==1)
{
Count=Count+255;  // sumarize all counter overflows
Timer0.bits.TMR0IF=0;
}
}
Flag=0;
Value=value + (long) Timer0; // add the rest inside the timer0
/*
here you have the nb of pulses during 1 seconde..
Count is in Hertz
then convert to RPM
and display
*/

imranahmed

imranahmed

Points: 2
Helpful Answer Positive Rating
Can we use two interrupts such Timer interrupt and external interrupt on RB0/INT.

yes you can use any no. of interrupts.

Error [1375] D:\MPLAB_Project\RPM_Meter_16f977a\RPM.c; 27. multiple interrupt functions (_Timer1 and _led) defined for device with only one interrupt vector

This error occurring ,how to fix it.

post your full code. So that we can help you

#include<htc.h>
__CONFIG(FOSC_HS & WDTE_OFF);
#define _XTAL_FREQ 2000000
unsigned char x;
unsigned int COUNT=0;
interrupt led()
{
if(INTCONbits.INTF==1)
{
INTCONbits.INTF=0;
for(x=0;x<=5;x++)
{
PORTD=255;
__delay_ms(500);
PORTD=0;
__delay_ms(500);
}
}
}
interrupt Timer1()
{
if (PIR1bits.TMR1IF==1)
{
PIR1bits.TMR1IF=0;
COUNT++;
TMR1L=0xDB;
TMR1H=0x0B;
}
}
void main()
{
CMCON=7;
ADCON0=0;
TRISC=0;
TRISD=0;
T1CON=0b00110101;
PIR1=0b00000001;
PIE1=0b00000001;
OPTION_REG=0b11000000;
INTCON=0b11010010;
while(1)
{
PORTC=COUNT;
}
}

I think you are using Hi-tech c compiler. I dont know the syntax of it. But still ill try to help. Hope it may help you
1. Use "void" before interrupt functions and compile the program.
I advise you not to use delay in interrupt routine.

Still no success then load the program which i mentioned below. I have made some changes.
HTML:
#include<htc.h>
__CONFIG(FOSC_HS & WDTE_OFF);
#define _XTAL_FREQ 2000000
unsigned char x;
unsigned int COUNT=0;

int1 interrupt_flag = 1;

void interrupt_isr()
{
if(INTCONbits.INTF==1)
{
INTCONbits.INTF=0;
interrupt_flag = 0;
}

if(PIR1bits.TMR1IF == 1)
{
PIR1bits.TMR1IF=0;
COUNT++;
TMR1L=0xDB;
TMR1H=0x0B;
}
}

void main()
{
CMCON=7;
ADCON0=0;
TRISC=0;
TRISD=0;
T1CON=0b00110101;
PIR1=0b00000001;
PIE1=0b00000001;
OPTION_REG=0b11000000;
INTCON=0b11010010;
while(1)
{
PORTC=COUNT;
if(interrupt_flag==0)
{
for(x=0;x<=5;x++)
{
PORTD=255;
__delay_ms(500);
PORTD=0;
__delay_ms(500);
}
}
interrupt_flag = 1;
}
}

Thank you very much for help I understand what problem occurred and problem is fixed and I used same as you only one interrupt function use and use different interrupt flags in IF condition.

But one problem is occurring when i run proteus simulation the portd blinking but it should blink after detecting rising edge on RB0/INT pin.

In INTCON register you have to set the bit which is used for rising edge trigger or falling edge trigger. You should set the bit for rising edge trigger.

Edit: Sorry, I was wrong. You have to look the values of INTEDG bit of OPTION_REG register.

Last edited:

I set for rising edge but portE blinking before pressing button.Please see attached files.

Attachments

• pic.bmp
1,001.1 KB · Views: 58
• pictext.txt
670 bytes · Views: 63

Try to clear PORTE using PORTE = 0x00 after the TRISE initialization. Also try

Code C - [expand]1
INTCONbits.RBIF==1

instead of

Code C - [expand]1
INTCONbits.INTF==1

Clear PORTB after initialization. The problem might be because there is no TRISB in the code. Use TRISB = 0xFF; and then use your old code.

imranahmed

imranahmed

Points: 2
Helpful Answer Positive Rating
Status
Not open for further replies.