I am new to programming PIC, I use PIC16F684 (via mikroC). I want to do an accurate (up to 1 minute per 24h) timer to control relay, so I chose an external 16 MHz crystal oscillator.

I connected it to RA4 and RA5 via two 22 pF capacitors to GND. I set oscillator to HS in "Edit Project" in mikroC, also set frequency to 16 MHz. Do I need to set OSCCON and to what value? Per my understanding it should be 0, as manual states (on page 31) for external oscillator.

I did consult AI (Copilot) and it tells me I should use OSCCON = 0x70, which does not make sense to me, as it actually sets the internal oscillator's frequency. Nonetheless, setting it to 0x70 makes my code work, but Delay_ms lasts twice as long. Then I did try outputting PWM, but it resulted in 8x times higher frequency than set (checked with oscilloscope). Also, I did test my timer's accuracy with timer interrupt, but I had to set the overflow value 8x times lower as well, or it would be too slow. Per calculation, I needed (60 x 1000) / 4.096 = 14648 overflows to count one minute, but I actually had to set it to 8x lower value.

To sum up - how do I set oscillator parameters correctly? Are project settings in mikroC enough, or should I set (and how) config bits? Is my PIC actually running 8x slower - at 2 MHz?

Here are my current settings:

enter image description here In K150 microbrn.exe (Fuses menu). I use this tool to upload HEX.

enter image description here The Edit Project menu.

  • 1
    \$\begingroup\$ Do not ask AI about stuff, it cannot know anything else except the thigs taught to it, and most likely it is not taught with fact data about your MCU but with forum discussions revolving around the subject including misconceptions about it. \$\endgroup\$
    – Justme
    Commented Mar 7 at 9:31

2 Answers 2


Do I need to set OSCCON and to what value? Per my understanding it should be 0, as manual states (31 page) for external oscillator.

Yes, this is correct, but insufficient to ensure a system clock of 16 MHz via your external crystal...the CONFIG register must be set correctly too.
CONFIG registers are not accessible via FLASH address, and must be programmed separately - I do not know how MIKRO development environment sets these configuration bits (I use MPLAB IDE).
For your 16 MHz crystal clock source, the three least significant bits of CONFIG should be set to 010 (binary).

If you wish to confirm the oscillator source (internal versus external) from your program, you can read bit #3 (OSTS)of OSCCON register (a read-only bit):

  • OSTS = 0....oscillator is from an external source, in your case, 16 MHz crystal
  • OSTS = 1....oscillator is from internal source, one of 8,4,2,1, 0.5, 0.25, 0.125 MHz

Microchip offers a further complication in oscillator configuration, to ensure that the system actually has a clock. It is termed "fail-safe clock monitor" - section 3.8 data sheet. It might be useful if you think the 16MHz crystal oscillator is unreliable. Crystal oscillators can take a long time to start up - many milliseconds...it may be dangerous to switch to a crystal clock that is slowly building amplitude, or if the oscillator has marginal amplitude.
An interrupt is triggered if the external crystal has failed. In this case, the processor has already and automatically switched to a slow internal oscillator. All software timing will be seriously slow while this internal oscillator is active.

  • \$\begingroup\$ I use K150 programmer to load the HEX. I also set Fuses in it - I understand those are the mentioned CONFIG bits? They match the ones in Edit Project: WDT, MCLRE,OSCILLATOR and others (i attached images to edited main question). \$\endgroup\$
    – Ri Di
    Commented Mar 7 at 16:55
  • \$\begingroup\$ With OSCON= 0x70, you've set internal oscillator to 8 MHz. However with OSCON's least significant bit reset to 0, the crystal oscillator (16MHz) is active. Unclear what frequency the compiler believes is active. "Fuses" refers to settings of CONFIG word, which you've set for HS crystal oscillator: 16 MHz. You could peek at OSCON's OSTS bit: it should be high, indicating that crystal frequency is active. \$\endgroup\$
    – glen_geek
    Commented Mar 7 at 20:08
  • \$\begingroup\$ So I did reading the OSTS - it seems it is indeed 1 - internal. I tested this by setting the LED output as 0 and then after delay as OSTS. So if LED blinks then OSTS is 1. The OSCCON is 0. \$\endgroup\$
    – Ri Di
    Commented Mar 7 at 20:28
  • \$\begingroup\$ I checked again (page 31) - it seems that OSTS 1 means it is running on EXTERNAL oscillator. \$\endgroup\$
    – Ri Di
    Commented Mar 7 at 21:16
  • \$\begingroup\$ Nice, you've confirmed that the crystal you've attached to RA4/RA5 @ 16 MHz is in charge, i.e. Fosc=16MHz. If you use TMR0 or TMR2 for time delay, these are clocked with Fosc/4, perhaps via prescalers. \$\endgroup\$
    – glen_geek
    Commented Mar 7 at 23:52

Setting the OSCCON to 0x70 will select an internal 8 MHz clock so it explains why you run at half speed of 16 MHz.

Which also means that since your oscillator speed is 8 MHz, the MCU executes code and runs the timer at 2 MHz.

So everything looks correct so far.

What you are likely missing is that you must program the CONFIG bits into the MCU, so it will select the correct HS oscillator mode and will use it as a clock source.

Be careful when programming the CONFIG bits. Programming them incorrectly may choose settings which cannot work in your system so the MCU has no clock it needs and will not work, or you lock yourself out from ever reprogramming the MCU.

Which is why most firmware flashing programs do not write the CONFIG or similar bits automatically without user really wanting to explicitly do so.

So selecting the HS as oscillator type in a project doesn't usally and actually do anything itself. It simply defines what value should be used to program the CONFIG memory address. But nothing writes to CONFIG memory unless you do it separately or allow it as a part of automatic batch programming of firmware plus CONFIG bits like you would do in production.

  • \$\begingroup\$ But why would it run on 2 Mhz then? Shouldnt it be 8 Mhz? Its weird that for Delay_ms it works 2x slower, but for timer interrupt and PWM its 8x slower. \$\endgroup\$
    – Ri Di
    Commented Mar 7 at 16:56
  • \$\begingroup\$ @RiDi If you look at PIC data sheet, that's how they work. The CPU uses 4 clocks per one machine instruction so with 16 MHz crystal it executes 2 million instructions per second. And from wherever your Delay_ms functiom came from, it knows this, but what it does not know that the chip is running at halg speed because you told the program you use a 16 MHz clock but chip uses 8 MHz clock. And timer interrupts and PWM run at CPU machine cycle speeds, not at crystal speeds. \$\endgroup\$
    – Justme
    Commented Mar 7 at 17:19
  • \$\begingroup\$ How accurate can internal oscillator be? What time variations could I expect in, lets say 24h, if temperature would differ in 30 degrees? Maybe I am overdoing this and should rely on internal oscillator. \$\endgroup\$
    – Ri Di
    Commented Mar 7 at 18:24
  • \$\begingroup\$ @RiDi Why do you ask - it literally reads on the first datasheet page after cover sheet and in oscillator parametets. It is factory calibrated to be 1% accurate, but at 3.5V and at 25 °C temperature, and 2% over much wider voltage and temperature range. One day is 1440 minutes so 1 minute accuracy per 1440 minutes is 0.07% and thus 1% is 14.4 minutes and 2% is 28.8 minutes. You likely want a crystal. \$\endgroup\$
    – Justme
    Commented Mar 7 at 19:16
  • \$\begingroup\$ Oh, I did not notice that. Tomorrow I'll go buy bunch of various crystal oscillators. Maybe those that I have are bad. I soldered a new one (same kind) - same problem. \$\endgroup\$
    – Ri Di
    Commented Mar 7 at 20:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.