|
|
View previous topic :: View next topic |
Author |
Message |
khwoo
Joined: 26 May 2009 Posts: 12
|
PIC16f877a Timer and interrupt problem |
Posted: Wed Jul 01, 2009 6:12 am |
|
|
I am doing a programming on a rpm (revolution per minute) counter for a toy car. When an IR sensor signal input to the PIC, interrupt will be enabled and timer 0 will started to count the rpm and display the value in 16x2 lcd.
The below code shows about the interrupt and timer0:
Code: |
#use delay (clock = 20000000)
#include <LCD.C>
#define INTS_PER_MINUTE 153 // (40000000/(4*256*256))
BYTE minutes; // A running minutes counter
BYTE int_count; // Number of interrupts left before a minute has elapsed
#int_rtcc // This function is called every time
void clock_isr() { // the RTCC (timer0) overflows (255->0).
BYTE start;
int_count=INTS_PER_MINUTE;
set_timer0(0);
setup_counters( RTCC_INTERNAL, RTCC_DIV_256 | RTCC_8_BIT);
enable_interrupts(GLOBAL);
enable_interrupts(INT_EXT); // For this program this is apx 153 times
if(--int_count==0) { // per minute.
++minutes;
int_count=INTS_PER_MINUTE;
}
}
|
And the to display the rpm value per minute in lcd, the code is shown below:
Code: |
void main ( void )
{
char display [ 4 ];
// Initialization
input(PIN_B0);
output_high(PIN_A0);
output_high(PIN_A1);
output_high(PIN_A2);
output_high(PIN_A3);
output_low(PIN_A4);
output_low(PIN_A5);
lcd_init();
lcd_gotoxy (1,1);
lcd_putc ("RPM:" +minutes );
}
|
The above code are combined together but nothing shown in the lcd.
Can anyone correct my mistakes? Thanks. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jul 01, 2009 12:53 pm |
|
|
Quote: | #int_rtcc // This function is called every time
void clock_isr() { // the RTCC (timer0) overflows (255->0).
BYTE start;
int_count=INTS_PER_MINUTE;
set_timer0(0);
setup_counters( RTCC_INTERNAL, RTCC_DIV_256 | RTCC_8_BIT);
enable_interrupts(GLOBAL);
enable_interrupts(INT_EXT); // For this program this is apx 153 times
if(--int_count==0) { // per minute.
++minutes;
int_count=INTS_PER_MINUTE;
}
} |
Never enable global interrupts inside an interrupt routine. The 16F877a
does not support nested interrupts.
Also, the PIC has a built-in module CCP that can be used to measure
frequency. There are several example threads on the forum which
show how to do this. Do a search for Tachometer on the forum's
search page. |
|
|
khwoo
Joined: 26 May 2009 Posts: 12
|
Problem on ccs compiler ver. 4.068 code |
Posted: Thu Jul 02, 2009 3:46 am |
|
|
Code: |
#include <16f877a.h>
#use delay (clock = 20000000)
#fuses NOWDT,NOPUT,HS,NOPROTECT
#include <LCD.C>
#define INTS_PER_10SECOND 153 // (4000000/(4*256*256*0.1))
BYTE ten_seconds; // A running seconds counter
BYTE int_count; // Number of interrupts left before ten second has elapsed
#int_rtcc // This function is called every time
void clock_isr() { // the RTCC (timer0) overflows (255->0).
// For this program this is apx 76 times
if(--int_count==0) { // per second.
++ten_seconds;
int_count=INTS_PER_10SECOND;
}
} |
Can anyone check the problem for the above code? I m using 4Mhz crystal oscillator, and i would like to count for every 10 seconds... I had refered to the examples in ccs..
The code below is about interrupt and lcd display:
Code: |
void main() {
BYTE start;
int_count=INTS_PER_10SECOND;
set_timer0(0);
setup_counters( RTCC_INTERNAL, RTCC_DIV_256 | RTCC_8_BIT);
enable_interrupts(INT_RB);
// enable_interrupts(GLOBAL);
while (TRUE)
{
set_tris_a(1);
lcd_init();
lcd_putc("\RPM:\n");
lcd_putc("++ten_seconds");
}
}
|
My interrupt pin is RB0 (INT) and RA0 to RA3 are my output pins connected to LCD pin 11 to 14.
Anything wrong in the code above kindly correct me.
Because its cannot display anything..
Thanks.. |
|
|
Ttelmah Guest
|
|
Posted: Thu Jul 02, 2009 7:50 am |
|
|
The obvious thing is that you do need to enable_interrupts(GLOBAL) _in the main_.
The point about this, is that you _must_ have it, or the interrupt will not be responded to, but you must _never have it inside the interrupt_ (not only pointless here, since the global interrupt must be enabled, or you will never arrive in the handler, but 'lethal', since the hardware disables this during the interrupt, and re-enabling it,can result in interrupts inside interrupts, which the chip does not support.....).
Best Wishes |
|
|
mkuang
Joined: 14 Dec 2007 Posts: 257
|
Re: Problem on ccs compiler ver. 4.068 code |
Posted: Thu Jul 02, 2009 8:43 am |
|
|
khwoo wrote: | Code: |
#include <16f877a.h>
#use delay (clock = 20000000)
#fuses NOWDT,NOPUT,HS,NOPROTECT
#include <LCD.C>
#define INTS_PER_10SECOND 153 // (4000000/(4*256*256*0.1))
BYTE ten_seconds; // A running seconds counter
BYTE int_count; // Number of interrupts left before ten second has elapsed
#int_rtcc // This function is called every time
void clock_isr() { // the RTCC (timer0) overflows (255->0).
// For this program this is apx 76 times
if(--int_count==0) { // per second.
++ten_seconds;
int_count=INTS_PER_10SECOND;
}
} |
Can anyone check the problem for the above code? I m using 4Mhz crystal oscillator, Thanks.. |
You are using a 4Mhz crystal? The code says 20Mhz.
That said, if you are using a 4Mhz crystal, the basic tick is 1us, so your timer0 in 8 bit mode will overflow every 1us times 256 * 256 = 65.536ms. Timer0 overflows 15.259 times per second.
If you want your interrupt to fire every 10s you have to use timer0 in 16 bit mode. I am not sure how you would do that in your device but chances are if you use:
setup_counters( RTCC_INTERNAL | RTCC_DIV_256 );
it would be in 16 mode. By trial and error you can figure out that with a 4Mhz crystal (1 Mhz instruction clock) you would set timer0 to 26473 so that it would overflow every (65536-26473)*1us*256 = 10.000128 seconds. Your complete code in main() would be something like:
Code: |
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
set_timer0(26473);
clear_interrupt(int_timer0);
enable_interrupts(int_timer0);
enable_interrupts(GLOBAL);
|
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|