|
|
View previous topic :: View next topic |
Author |
Message |
David Eaves
Joined: 28 Sep 2004 Posts: 6
|
Interrupt frequency difference 16F877 -> 18F452 |
Posted: Tue Sep 28, 2004 2:48 pm |
|
|
Hi there,
This is the first time I haven’t been able to find the answer to my problem in this forum, I've also been trawling the Microchip website. Sorry if this has already been asked or is documented elsewhere...
I just got the PCH compiler as I needed more memory for a program which started off in a 16F877. I've migrated to an 18F452, all is fine I changed the port d address as I was directly referencing it and updated all the fuses (I also compared a 18F452 program headers done with the CCS IDE wizard)
All is working well apart from one thing; the interrupt rate is not as expected. On the board I am using a 3.2768MHz crystal divided down by 64 with Timer 1 to give a 50Hz interrupt rate (3.2768M/4/256/64) this works fine and is spot on with the 16F877
I converted the code to what is shown below which I believe should do the same thing.
setup_timer_0(RTCC_8_BIT | RTCC_INTERNAL | RTCC_DIV_64);
enable interrupts(INT_TIMER0);
(then a global enable later on)
When I run it the interrupt rate seems about 1.5 times slower than it should be. I'm using version 3.202 of the compiler (I have the 30 day update rights still I was just hanging on starting) . Having read the microchip datasheet it seems like it is still divide by 4 on the instruction rate. Is it me being dopey, a bug, or something with the 18F452?
Any help is much appreciated
Thanks
David Eaves |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Re: Interrupt frequency difference 16F877 -> 18F452 |
Posted: Tue Sep 28, 2004 3:06 pm |
|
|
David Eaves wrote: | Hi there,
This is the first time I haven’t been able to find the answer to my problem in this forum, I've also been trawling the Microchip website. Sorry if this has already been asked or is documented elsewhere...
I just got the PCH compiler as I needed more memory for a program which started off in a 16F877. I've migrated to an 18F452, all is fine I changed the port d address as I was directly referencing it and updated all the fuses (I also compared a 18F452 program headers done with the CCS IDE wizard)
All is working well apart from one thing; the interrupt rate is not as expected. On the board I am using a 3.2768MHz crystal divided down by 64 with Timer 1 to give a 50Hz interrupt rate (3.2768M/4/256/64) this works fine and is spot on with the 16F877
I converted the code to what is shown below which I believe should do the same thing.
setup_timer_0(RTCC_8_BIT | RTCC_INTERNAL | RTCC_DIV_64);
enable interrupts(INT_TIMER0);
(then a global enable later on)
When I run it the interrupt rate seems about 1.5 times slower than it should be. I'm using version 3.202 of the compiler (I have the 30 day update rights still I was just hanging on starting) . Having read the microchip datasheet it seems like it is still divide by 4 on the instruction rate. Is it me being dopey, a bug, or something with the 18F452?
Any help is much appreciated
Thanks
David Eaves |
Your numbers look good. There are 16K instructions between interupts so you are not running to fast. There could be some jitter on individual interupts caused by code that suspends interupts but that should be very minor. Are you doing anything that would set a value to the timer? Are you using a WDT? What happends in the interupt? |
|
|
Ttelmah Guest
|
Re: Interrupt frequency difference 16F877 -> 18F452 |
Posted: Tue Sep 28, 2004 3:07 pm |
|
|
David Eaves wrote: | Hi there,
This is the first time I haven’t been able to find the answer to my problem in this forum, I've also been trawling the Microchip website. Sorry if this has already been asked or is documented elsewhere...
I just got the PCH compiler as I needed more memory for a program which started off in a 16F877. I've migrated to an 18F452, all is fine I changed the port d address as I was directly referencing it and updated all the fuses (I also compared a 18F452 program headers done with the CCS IDE wizard)
All is working well apart from one thing; the interrupt rate is not as expected. On the board I am using a 3.2768MHz crystal divided down by 64 with Timer 1 to give a 50Hz interrupt rate (3.2768M/4/256/64) this works fine and is spot on with the 16F877
I converted the code to what is shown below which I believe should do the same thing.
setup_timer_0(RTCC_8_BIT | RTCC_INTERNAL | RTCC_DIV_64);
enable interrupts(INT_TIMER0);
(then a global enable later on)
When I run it the interrupt rate seems about 1.5 times slower than it should be. I'm using version 3.202 of the compiler (I have the 30 day update rights still I was just hanging on starting) . Having read the microchip datasheet it seems like it is still divide by 4 on the instruction rate. Is it me being dopey, a bug, or something with the 18F452?
Any help is much appreciated
Thanks
David Eaves |
I'd check that your crystal is running on frequency. The 18 family, are 'fussier' over their crystal selection, than the 16 chips (this is because of the extra complexities introduced by the PLL, and higher top frequency support).
Try adding a series resistor to the crystal to limit the drive to the chip, and have a look at the MicroChip application note about crystal selection, and especially the note that the chips require a parallel cut crystal, with the comment that 'use of a series cut crystal may give a frequency out of the crystal manufacturers specifications'. This applied to the 16 chips as well, but many people 'got away' with this on these chips, but on the 18 chips it becomes essential...
Best Wishes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Sep 28, 2004 3:42 pm |
|
|
Quote: | I'm using version 3.202 of the compiler (I have the 30 day update rights still I was just hanging on starting) . |
Just a quick comment. Get the latest version immediately before
your download rights run out. In fact, get any versions as soon as
they are posted. Save them under their own filenames. Examples:
pch3191.exe
pch3212.exe
Get both those versions now. Then you have the option to install
them later if you want to. They're available here:
http://www.ccsinfo.com/download.shtml
They have done a ton of bug fixes since vs. 3.202. You shouldn't
be using it, IMO. http://www.ccsinfo.com/versions.shtml |
|
|
David Eaves
Joined: 28 Sep 2004 Posts: 6
|
|
Posted: Tue Sep 28, 2004 4:14 pm |
|
|
Thanks for all the input so far:
Neutone, I'm not using WDT, or accessing/modifying the counter value anywhere in the program. The code function is to keep track of time by incrementing a variable until >49 incrementing another then resetting the first etc - it's compact low overhead code. This worked fine on the F877 version. I also have Timer 1 interrupts running at 12.5Hz in theory, these detect key presses and some other housekeeping tasks. The code all worked fine previously and it has been running for months.
Ttelmah
Good point about the crystal, I had read about that but was being a bit slack at checking it. From what you have said I will investigate it and try and find a specification for the crystal and try your mod. Just thinking about it I'll put another make and value of crystal in and see if I get the expected rates for that frequency.
PCM programmer
Very good point, I will do that. I hadn't activated them yet as I have been messing around with my net connection (switching to ADSL) in the last few days and I only got PCH on Friday. I'll get the new version before I try it again.
Thanks again
David |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
Re: Interrupt frequency difference 16F877 -> 18F452 |
Posted: Tue Sep 28, 2004 6:31 pm |
|
|
David Eaves wrote: | ..note that the chips require a parallel cut crystal, with the comment that 'use of a series cut crystal may give a frequency out of the crystal manufacturers specifications'. This applied to the 16 chips as well, but many people 'got away' with this on these chips, but on the 18 chips it becomes essential...
|
Parallel and Series cut crystals have different modes of resonance. Using either type in a circuit design for the other will give you the wrong frequency.
wrt 'many people getting away' if the wrong type of crystal is used, expect any timing sensitive code, such as attempting to do 115Kbps on a serial port to fail. |
|
|
David Eaves
Joined: 28 Sep 2004 Posts: 6
|
The plot thickens... |
Posted: Fri Oct 08, 2004 12:57 pm |
|
|
Hi all,
Sorry for my delay in the update here - my main job has been keeping me busy.
I did quite a bit of work looking into the timing problem I was having
-printed and read a lot of microchip stuff on crystals and tried different ones
- from this data played around with the Cp and Rs for the crystal. It still stayed the same error.
It then occured to me I should check if the whole thing was running at the right time. I tried transmiting with RS232 and found there were no problems. As the Timer 0 was out by around 1.5 too slow, if it was overall there was no way RS232 would work. So it seems my Crystal setup is okay.
This is silly now as it's not even out by a multiple you can sent up with Timer 0. I've had a good play around with the values and no avail it's still out. I think I'm going to hand code that bit in assembler now just to see if it makes any difference. I've also tried another chip and that had the same problem.
If anyone has any more ideas what the problem is, please let me know.
Thanks
David |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 08, 2004 1:13 pm |
|
|
You're going to have to post a test program. If you do that,
we can copy and paste it right in MPLAB (or the CCS IDE, I suppose)
and compile and run it on our hardware. Instead of conjecture,
we'd figure out the problem very quickly.
Make the test program be small. Only include lines of
code that demonstrate the problem. Don't do any
mistakes like letting the code run off the end of main().
Be sure to post all pre-processor statements that are
part of the program, such as #include, #use statements,
#byte, etc. Be sure to show all variable declarations.
In other words, a complete test program. |
|
|
David Eaves
Joined: 28 Sep 2004 Posts: 6
|
|
Posted: Fri Oct 08, 2004 4:23 pm |
|
|
Hi there,
Your right, that will be the best way of getting to the bottom of the problem rather than speculation. I will sort out a cut down version tomorrow that shows what is happening.
Thanks
David |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 08, 2004 4:41 pm |
|
|
Good. Also post the version of the compiler that you're currently using. |
|
|
David Eaves
Joined: 28 Sep 2004 Posts: 6
|
Code listing |
Posted: Sat Oct 09, 2004 1:52 pm |
|
|
Hi there, as suggested here is the code....
I've gone down to a simple program to hopefully show the problem. In doing this I now found that I'm having the same thing with a 16F877 so there is no difference, but the time is not as expected. I set this program up using the wizard on the CCS interface to make sure all was well that way. In the program I use the delay_ms to make a rough seconds counter, this isn't far out and shows that the crystal is running okay. The seconds counter that should be right seems to be running about 3-4 times slower than it should be.
Code: |
#include <16F877.h>
#device adc=10
#use delay(clock=3276800)
#fuses NOWDT,XT, PUT, NOPROTECT, BROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
#include <LCD.C>
//variables
int hours=8, minutes=30, seconds=0, time_counter=0, rough_tenths=0, rough_seconds=0;
#int_TIMER1
TIMER1_isr()
{
delay_ms(10);
//this simulates the timer1 I have running
}
#int_TIMER0
TIMER0_isr()
{
time_counter++;
if(time_counter>49){
time_counter=0;
seconds++;
if(seconds>59){
seconds=0;
minutes++;
}
if(minutes>59){
minutes=0;
hours++;
}
if(hours>23){
hours=0;
}
}
}
void send_time(){
printf(lcd_putc, "%02U", hours);
lcd_putc(":");
printf(lcd_putc, "%02U", minutes);
lcd_putc(":");
printf(lcd_putc, "%02U", seconds);
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64); //50Hz
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); //12.5Hz
setup_timer_2(T2_DISABLED,0,1);
lcd_init();
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
lcd_init();
lcd_putc("\f");
lcd_putc("LCD Test");
delay_ms(1500);
lcd_putc("\f");
enable_interrupts(global);
do{
send_time();
lcd_putc(" ");
printf(lcd_putc, "%U", rough_seconds);
delay_ms(96);
lcd_gotoxy(1,1);
rough_tenths++;
if(rough_tenths>9){rough_tenths=0; rough_seconds++; lcd_putc("\f");}
if(rough_seconds>59)rough_seconds=0;
}
while(true);
}
|
I guess now I am doing something silly as it is the same between the chips, I checked the orginal 16F877 program and it runs slow too. The compiler version is 3.212.
The only other variable is I changed programmer recently too, however, I have just updated the firmware on it and it seems okay. I did try to use my old one but it doesn't like XP and wasn't for working. I will try again to eliminate this fault.
Update: I have elimnated the programmer now, the old one shows exactly the same problem.
Thanks for any help
David
Last edited by David Eaves on Sun Oct 10, 2004 2:41 am; edited 1 time in total |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Sat Oct 09, 2004 5:47 pm |
|
|
You have a couple of problems here. Firstly the code produced by the compiler is non reentrant. See http://www.ccsinfo.com/forum/viewtopic.php?t=17661&highlight=delayms+interrupts
To solve this problem, if you use code (such as delay_ms) both inside and outside an interrupt handler, then the code outside the handler will disable interrupts for the duration of the function. That is why your sample code does not work.
Also your TMR0 ISR code is not optimal for the time processing. If you change it around a bit you will spend less time in this interrupt handler.
Code: |
if(time_counter>49)
{
time_counter=0;
seconds++;
if(seconds>59)
{
seconds=0;
minutes++;
if(minutes>59)
{
minutes=0;
hours++;
if(hours>23)
{
hours=0;
}
}
}
}
|
|
|
|
David Eaves
Joined: 28 Sep 2004 Posts: 6
|
|
Posted: Sun Oct 10, 2004 2:46 am |
|
|
Hi asmallri,
Thanks for the reply. I didn't realise that with the delay function, it is very useful to know. I have found one delay_ms(1) that is called from within the real timer_1 ISR. I'll try this out and see if it makes the difference. Good point with the timer_0 code, that is more elegant.
Update: I got rid of the delay_ms() and the problem is fixed. When I was writing the program before I was using an ancient version of the compiler (at least 4 years old) and it must handle it different hence the problem when I moved up to the 18F and new compiler version.
Thanks again for the help.
David |
|
|
|
|
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
|