confusing clocks - Page 1
Forum section: electronics / general

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 03, 2016, 11:05:41 am
content: http://ww1.microchip.com/downloads/en/devicedoc/39632c.pdfpage 26I bought the 18f2550 thinking it's just a regular pic chip, but it turns out that it's mainly used for usb applications, although that is useful, but it's not what I need right now, all I need is to run the damn thing knowing what clock speed i'm using, and the datasheet is so focused on settings clock for usb.It's just that i'm not certain, and one thing I've learned in this field, is that if you're not 100% sure of everything, things will go bad.I understand the OSCCON (OSCCON<6:4> == IRCF2:IRCF0) settings for prescaling the internal 8MHz oscillator, but I don't understand the rest of them.I'm trying to get a 16MHz external clock source to be transformed to a 1MHz frequency clock.what do the PLLDIV and CPUDIV do exactly ? and what are the differences between them ? Can I use both of them at the same time ?EDIT : Just wanted to add that I do not want to use the internal oscillator.

author: rs20
author_rank: Super Contributor
timestamp: June 03, 2016, 11:27:47 am
content: Page 24 tells you the full story. PLLDIV and CPUDIV do what they say on that diagram. I was going to write a detailed explanation here, but I'd just be verbally describing the diagram!With this chip, it is impossible to derive 1 MHz CPU clock from 16 MHz primary or secondary oscillators (at least, not without ignoring the "(4 MHz Input only)" warning on that one particular PLL there). Unless there's further dividers elsewhere. You can, however, use the internal oscillator with OSCCON<6:4> = 100, having some fun with manipulating the tuning bits.If you're thinking this seems odd, this seems unusual to me too. The PLL in my ARM dev board is vastly more versatile than this.You could also use a simple binary counter chip to divide by 16 for you.EDIT: Just an additional note to clarify: You expressed a frustration that Table 2-3 only showed clocked configuration "for USB". Just to make it absolutely clear, Table 2-3 is anexhaustivelist ofallpossible clock/oscillator configurations, whether you want USB or not (excepting those with input clock frequencies other than 4/8/12/16/20/24/40/48 MHz, for which use of the PLL is banned and you're restricted to the /1, /2, /3 and /4 options set by CPUDIV) (and except internal oscillator options.)

author: uncle_bob
author_rank: Unknown
timestamp: June 03, 2016, 11:37:48 am
content: HiThis is a PIC, so the "cpu clock" and the "instruction execution speed" are two different things. If you are after a 1 us execution speed, you need something other than a 1 MHz CPU clock ...Not saying this is an issue in this case, just mentioning it since it is a VERY common thing to trip over.Bob

author: ealex
author_rank: Frequent Contributor
timestamp: June 03, 2016, 11:40:36 am
content: HelloI'm not used to PIC cpu's but the clock tree is quite readable:PLLDIV is used to set the proper PLL refference value - the PLL module must see only 4MHz at it's inputIf you are not using the PLL it will not affect your clock settings.The CPUDIV seems to change 2 different dividers - the one connected to the "Oscillator Postscaler" and the one connected to the "PLL Postscaler".You can select the "Primary Clock" source via "FOSC3:FOSC0" and use that to choose the peripheral clock.If you want to use the internal oscillator then you will connect via "INTOSC Postscaler" and set OSCCON<6:4> to "100"With your 16MHz XTAL you can only obtain a 4MHz clock - divide by 4.If you want to use an external XTAL you can either use a 4MHz crystal if the Primary Oscillator can use it, set CPUDIV to '11' ( /4 ), set FOSC3:FOSC0 to 0 to choose Primary clock from "Oscillator Postscaler" then set the main mux to Primary ClockIf it can't oscillate that low, you should be able to make an external oscillator 4 / 3 / 2 /1MHz with some TTL gates and feed that signal via OSC1 or OSC2 pins - read the datasheet for this

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 03, 2016, 11:55:35 am
content: Hello,Quote from: ealex on June 03, 2016, 11:40:36 amFOSC configuration is simpleCode:; FOSC = XT_XT XT oscillator (XT); FOSC = XTPLL_XT XT oscillator, PLL enabled (XTPLL); FOSC = ECIO_EC EC oscillator, port function on RA6 (ECIO); FOSC = EC_EC EC oscillator, CLKO function on RA6 (EC); FOSC = ECPLLIO_EC EC oscillator, PLL enabled, port function on RA6 (ECPIO); FOSC = ECPLL_EC EC oscillator, PLL enabled, CLKO function on RA6 (ECPLL); FOSC = INTOSCIO_EC Internal oscillator, port function on RA6, EC used by USB (INTIO); FOSC = INTOSC_EC Internal oscillator, CLKO function on RA6, EC used by USB (INTCKO); FOSC = INTOSC_XT Internal oscillator, XT used by USB (INTXT); FOSC = INTOSC_HS Internal oscillator, HS oscillator used by USB (INTHS); FOSC = HS HS oscillator (HS); FOSC = HSPLL_HS HS oscillator, PLL enabled (HSPLL)I use FOSC = HS for external high speed oscillator clock source.Quote from: ealex on June 03, 2016, 11:40:36 amthis is bad news for me.Quote from: ealex on June 03, 2016, 11:40:36 amI only have 20MHz, 16MHz and 12MHz oscillators, so I can't test this right now.thanks for your replythis has been repeated, so I have to mention it,I do not want to use the internal oscillator.

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 03, 2016, 11:57:30 am
content: Quote from: uncle_bob on June 03, 2016, 11:37:48 amI understand it's the instruction execution speed in pic is1 instruction per 4 cpu cycles, right ?so, if my final clock speed is 4MHz , this line is correct ?Code:#define _XTAL_FREQ 4000000

author: uncle_bob
author_rank: Unknown
timestamp: June 03, 2016, 12:06:46 pm
content: Quote from: MAD MACRO on June 03, 2016, 11:57:30 amHiYes, for a "1 MHz" instruction rate, you want a 4 MHz CPU clock.=====It's really rare to see an application that has a *low* instruction rate requirement. About the only one I can think of off the top of my head it timing. There, your loops are all so weird that it quickly becomes a "don't bother" sort of thing. Peripheral clocks don't go through quite the same process. If that is the concern, we may be focusing in the wrong area ...Bob

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 03, 2016, 12:16:36 pm
content: Quote from: uncle_bob on June 03, 2016, 12:06:46 pmThe reason I want 1MHz frequency, is for a self educational reasons, to understand the prescaling system more.

author: uncle_bob
author_rank: Unknown
timestamp: June 03, 2016, 12:21:46 pm
content: Quote from: MAD MACRO on June 03, 2016, 12:16:36 pmHiWith a PIC, you can't always get any and every clock frequency. Some other MCU's are more flexible in this regard. The PIC comes from a world of "faster it better" and does not offer the range of low speed options that others do. For most real world applications (other than low power) that's not a bit problem. Back in the 1980's it let them sell the chips for a lot less money that would have otherwise been the case. Today it's a relic of decisions made back in a long gone era.Bob

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 03, 2016, 01:45:34 pm
content: Thanks bobso, If I have an external oscillator of 16MHz frequencyand these too lines of codes.Code:#pragma config FOSC = HS // external high speed osc#pragma config CPUDIV = OSC4_PLL6 // oscillator src clock: /4I should have a 4MHz clock speed , right ?Code:#define _XTAL_FREQ 4000000i'm using a delay of 10 seconds for led toggling and i'm getting a delay of about 2.1 seconds delay only.

author: uncle_bob
author_rank: Unknown
timestamp: June 03, 2016, 02:16:27 pm
content: Quote from: MAD MACRO on June 03, 2016, 01:45:34 pmHiIf you start from 16, divide by 4, you get a CPU clock of 4 MHz. That should give you an instruction execution of 1 us for most of them.If the LED is blinking 5X to fast, you either are starting from 80 MHz (unlikely), or are not dividing by 4 (more likely), or there is a bug in your code (this sort of thing happens to the best of us ...).Simple checks:1) If you change the divide does the blink speed change?2) If you take away the external clock does it stop blinking?If it passes both of those tests, look for a bug in the code.Bob

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 03, 2016, 02:34:12 pm
content: Quote from: uncle_bob on June 03, 2016, 02:16:27 pm1) yes2) yesThis is my code simplified as possible, tried it though.Code:#include <xc.h>#define _XTAL_FREQ 4000000//BEGIN CONFIG#pragma config FOSC = HS#pragma config CPUDIV = OSC4_PLL6#pragma config WDT = OFF#pragma config LVP = OFF#pragma config CPD = OFF//END CONFIG/*miscellaneous*/#define _BV(NUM) (1 << NUM)#define toggle(LAT,PIN) LAT ^= _BV(PIN)#define set_output(TRIS,PIN) TRIS &= ~_BV(PIN)/*miscellaneous*/void delay_10ms(unsigned char n){while (n-- != 0) __delay_ms(10);}int main(){set_output(TRISC,0);while(1){toggle(LATC,0);delay_10ms(1000);}return 0;}

author: uncle_bob
author_rank: Unknown
timestamp: June 03, 2016, 02:43:35 pm
content: HiI suspect that whatever compiler you are using is confused about how the clocks are set up.Bob

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 03, 2016, 02:44:53 pm
content: Quote from: uncle_bob on June 03, 2016, 02:43:35 pmi'm using xc8, what do you mean confused ?

author: uncle_bob
author_rank: Unknown
timestamp: June 03, 2016, 02:47:58 pm
content: Quote from: MAD MACRO on June 03, 2016, 02:44:53 pmHiYou are using the delay 10 ms call for all of your timing. When you make a call like this in C, it goes off and looks up a bunch of defined "stuff' to figure out what to do to wait for that amount of time. The compiler sorts out all the various defines and runs a loop of some sort (or maybe does something else). If the defines that the compiler is using are not correct, the delay will be wrong.Bob

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 03, 2016, 03:02:18 pm
content: Quote from: uncle_bob on June 03, 2016, 02:47:58 pmSo, I made my own definition like this, and used this one in the functionCode:#define delay_ms(x)_delay((unsigned long)((x)*(_XTAL_FREQ/1000)))I get only 9.2 ms delay , but not 10.

author: uncle_bob
author_rank: Unknown
timestamp: June 03, 2016, 03:15:24 pm
content: HiTake a look at the assembly output and see what it's really doing with your functions.Bob

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 03, 2016, 03:17:22 pm
content: Quote from: uncle_bob on June 03, 2016, 03:15:24 pmI think this is the most relevant part of the asm code, I can't read assembly very well, it's like ancient black magic to me now.Code:_main:;incstack = 0optstack 30line27l616:bcf(0+(0/8)+(c:3988)),c,(0)&7;volatileline29l618:movlw(01h)&0ffhxorwf((c:3979)),c;volatileline30l620:movlw(0E8h)&0ffhcall_delay_10msgotol618globalstartgotostartopt stack 0line33GLOBAL__end_of_main__end_of_main:signat_main,90global_delay_10msnot sure if this would be helpful, but a friend of mine(who works at the shop that I go to) told me once that the all chips and ICs that we have here are low quality and not as accurate as they're meant to be.

author: JPortici
author_rank: Super Contributor
timestamp: June 03, 2016, 06:07:04 pm
content: Quote from: uncle_bob on June 03, 2016, 12:21:46 pmLike a dsPIC,PIC32 and PIC12,16,18 that aren't ancient relics like a 18F2550Anyway, to be of some use to the topic...It is strange indeed that you get a much different delay time (a much lower one in this case)what i'd try to do is to use an interrupt from a timer to get a precise delay and see if the clock is at the frequency it should be

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 03, 2016, 07:44:32 pm
content: Quote from: JPortici on June 03, 2016, 06:07:04 pmwell, thanks for the tip, well do, in post #15 i've mentioned that I've added my own definition of delay_ms() and it changed the results.first mistake was a compiler's fault, and got that fixed, but it's still not accurate enough, from 10 seconds to 9.2 is not good enough.Tried that, using timer0 interrupt.loading results...

author: uncle_bob
author_rank: Unknown
timestamp: June 03, 2016, 10:17:08 pm
content: Quote from: MAD MACRO on June 03, 2016, 07:44:32 pmHiWhat is the source of your 16 MHz clock?Bob

author: JPortici
author_rank: Super Contributor
timestamp: June 03, 2016, 11:37:07 pm
content: But where are you using timer0? i don't see itAnyway, I wouldn't use timer 0 for this purpose as it's harder to get a precise timing.For this sort of tasks i use instead Timer2 and the likes: an interrupt is generated everytime the timer matches the period register, so the frequency between interrupts is exactly FCLK / (4 * PRESCALER * (PR2 + 1))with timer 0 you either let it overflow at 255->0 or calculate the lenght of the interrupt routine and inside it you set the TMR0 value to get the interrupts spaced every XX ms

author: Simon
author_rank: Unknown
timestamp: June 04, 2016, 05:45:12 pm
content: please can we put uC questions in the right section ?

author: dannyf
author_rank: Super Contributor
timestamp: June 04, 2016, 07:26:54 pm
content: QuoteThe clock tree is pretty clear. To do what you need, you don't need PLL. So pick XT/HS/EC/ECIO, and then set CPUDIV to 4 -> 16Mhz / 4 = 4Mhz.Done.