View previous topic :: View next topic |
Author |
Message |
amcfall
Joined: 20 Oct 2005 Posts: 44
|
Clock / PLL on 18F4550 |
Posted: Thu Jun 01, 2006 7:50 am |
|
|
OK, I'm quite confused here. I'm setting up a project with a 18F4550 and can't figure out why I'm gertting the wrong frequency (haven't even gotten to the USB portion yet).
Looking at fig 2-1 in the manual (clock diagram), I had decided on the following setup:
4Mhz crystal
XTPLL mode
PLL1 (no prescaler, 4Mhz input)
CPUDIV4 (to get 24Mhz from the 96Mhz PLL)
When I use the XT fuse and set the clock for 4Mhz, everything works as expected. When I attempt to use XTPLL and set the clock for 24Mhz I get longer durations than expected on the buzzer pin. I scoped it it looked like the clock was running slower than calculated. I changed the clock speed to 16Mhz and timing is correct (RS232 works also). So, somehow it's running at 16 instead of 24. I figure I'm doing somehting wrong, but I'm not sure what (haven't messed with PLL before).
The following code works, but the clock is set for 16 and I expected 24 to be the corect setting.
Code: |
#include <18F4550.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
// #FUSES XT
#FUSES XTPLL //Crystal/Resonator with PLL enabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT_NOSL //Brownout enabled during operation, disabled during SLEEP
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV20 //Brownout reset at 2.0V
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES NOMCLR //Master Clear pin enabled
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL1 //No PLL PreScaler
#FUSES CPUDIV4
#FUSES USBDIV
#use delay(clock=16000000)
#DEFINE BUZZER PIN_C2
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
void main(void) {
unsigned int16 buzzy=0;
delay_ms(100);
printf("\r\n\npower on\n\r\n\r");
for (buzzy=0;buzzy<10000;buzzy++)
{
output_high(BUZZER);
delay_us(500);
output_low(BUZZER);
delay_us(500);
}
delay_ms(1000);
printf("\r\n\ndone beeping\n\r\n\r");
while(1);
delay_cycles(1);
}
|
Thanks,
Avery
EDIT: Compiler 3.236 |
|
|
amcfall
Joined: 20 Oct 2005 Posts: 44
|
|
Posted: Thu Jun 01, 2006 8:06 am |
|
|
The more I dig the more confused I am. Here's what MPLAB says my fuses are, under CPU system clock postscaler:
[Osc1/Osc2 src: /4] [96Mhz PLL src: /6]
the 1/6 postscaler would jive with the 16Mhz clock, so I must be reading this completely wrong.
Avery |
|
|
amcfall
Joined: 20 Oct 2005 Posts: 44
|
|
Posted: Thu Jun 01, 2006 9:03 am |
|
|
CPUDIV4 gives
[Osc1/Osc2 src: /4] [96Mhz PLL src: /6]
CPUDIV3 gives
[Osc1/Osc2 src: /3] [96Mhz PLL src: /4]
So there's some relation between these things I don't get. Can anyone tell me where I should have seen this in the data sheet? I had assumed that CPUDIV4 (which says system clock by 4 in fuses.txt) meant divide PLL by four, which must be wrong.
Sorry if I'm just talking to myself, going crazy here...
Avery |
|
|
andrewg
Joined: 17 Aug 2005 Posts: 316 Location: Perth, Western Australia
|
|
Posted: Sat Jun 03, 2006 1:20 am |
|
|
Figure 2.1 "Clock diagram" in the datasheet gives a good overview for how the clocks are done.
Yes, CPUDIV divides differently depending on if you're using the PLL or not. All shown in the diagram. _________________ Andrew |
|
|
rberek
Joined: 10 Jan 2005 Posts: 207 Location: Ottawa, Canada
|
|
Posted: Sat Jun 03, 2006 5:47 am |
|
|
CCS only has 4 fuse settings, CPUDIV1-4. Therefore picking CPUDIV4 would probably selects configuration bits CPUDIV1 = 1 and CPUDIV0 = 1.
I'd then expect the fuse setting CPUDIV3 to select config bits CPUDIV1 =1 and CPUDIV0 = 0, which should give you what you want as you suspect already. |
|
|
amcfall
Joined: 20 Oct 2005 Posts: 44
|
|
Posted: Sat Jun 03, 2006 9:05 am |
|
|
rberek wrote: | CCS only has 4 fuse settings, CPUDIV1-4. Therefore picking CPUDIV4 would probably selects configuration bits CPUDIV1 = 1 and CPUDIV0 = 1.
I'd then expect the fuse setting CPUDIV3 to select config bits CPUDIV1 =1 and CPUDIV0 = 0, which should give you what you want as you suspect already. |
Yup, it looks like:
CPUDIV2 System Clock by 2
actually loads a value of 2 into the register... Not an actual divisor of 2. I feel stupid for spending so long on sucvh a simple problem. I was hung up on the description in fudses.tct where is says system clock by 2.
Thanks
Avery |
|
|
|