View previous topic :: View next topic |
Author |
Message |
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
HS OSC in FUSES and "setup_oscillator" |
Posted: Mon May 27, 2019 10:58 am |
|
|
Hello!
Selecting HS in the FUSES and in #use delay (clock = 20000000) and I use 8MHz in "setup_oscillator", is it a bad setting? Assuming that I have 8MHz crystal and want to set the ADC clock to run at 8MHz?
The code below shows what I mean:
Code: | #include <16F886.h>
#device ADC = 10
#FUSES NOWDT,HS, PUT, NOPROTECT, NOMCLR, NOCPD, NOBROWNOUT,NOIESO, FCMEN,
#use delay(clock = 20000000)
void init() // Hardware initialization
{
setup_oscillator(OSC_8MHZ);
setup_adc(ADC_CLOCK_DIV_8); // 8Tosc ADC conversion time
setup_adc_ports( sAN12 | sAN11 | sAN9 | sAN10 | sAN8); // Select Analog Inputs
setup_comparator(NC_NC_NC_NC); // disable comparator module |
_________________ All is well even in the well! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Mon May 27, 2019 12:00 pm |
|
|
The delay setting must match what speed your chip is actually running at.
Otherwise every timing based operation will be wrong.
However you seem very confused. Setup_oscillator is to configure the
_internal_ oscillator, not an external crystal. You need to physically
look at your board. Is there a crystal?. On your chip, if there is it'll be
connected to pins 9 & 10. If ir is present, then look on it. It'll have a number
giving it's frequency.
If there is a crystal, then get rid of 'setup oscillator', and put the
frequency value of the crystal into #use delay.
If there is not a crystal, then change #use delay to 8MHz, and get rid
of the HS fuse. |
|
|
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
|
Posted: Mon May 27, 2019 12:57 pm |
|
|
Solved! Thanks for your explanations. _________________ All is well even in the well! |
|
|
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
|
Posted: Mon May 27, 2019 1:40 pm |
|
|
Sorry, if I may ask again, can I use "setup_oscillator(OSC_8MHz)"on those PICs that have 32MHz and 16MHz internal oscillator?
Or must I set it with their internal oscillator speed in case I want to make use of the "INTRC_IO"? _________________ All is well even in the well! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Mon May 27, 2019 1:52 pm |
|
|
Many chips with internal oscillators have programmable postscalers for these.
Many of the older chips only had a 4MHz oscillator. No other settings.
Then later ones typically have a 8MHz oscillator a postscaler (that can give
normally, 8, 4, 2, 1MHz, and a PLL that can be fed from the 8MHz or 4Mhz
output to give 16 and 32MHz.
Understand that the setup file for whatever chip you use, will only contain
the options that are supported by it's oscillator. The chip's data sheet
will also show what frequencies are available from the internal oscillator. |
|
|
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
|
Posted: Mon May 27, 2019 2:35 pm |
|
|
Ok understood. Thanks. _________________ All is well even in the well! |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1354
|
|
Posted: Mon May 27, 2019 6:42 pm |
|
|
One thing to be aware of that I ran into recently. If the setup oscillator call you put in cannot be achieved by the FUSES you have chosen, it will silently change your fuses to whatever the setup_oscillator call will need. It did this to me on a PIC24 chip using one of the more recent versions of the compiler.
I had the fuses and #use delay() setup for 8MHz for normal operation, but added a call to setup_oscillator() which changed it to 32MHz (to run a quick calc). It changed the FUSES to only support the 32MHz so all of my UARTs and such stopped working. Took me a bit to figure out what happened since it had been working fine for the last few months (until that change).
I expected that from the precompiler stuff (#use delay() for example), but a runtime call of a function caught me off guard.
It was my fault for not checking the datasheet and not double checking the fuses after making the change, but like I said...working fine for months with no issue, so I wasn't expecting a FUSE change. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Mon May 27, 2019 11:08 pm |
|
|
I think you will find it is the #use delay that did the 'override'.
If you have a #use delay statement _after_ the fuse settings, and it
conflicts, the compiler will use the fuses that match the delay, not those
you have already set.
Place the fuses after the #use delay, and your fuses override those
implicit in the delay statement. |
|
|
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
|
Posted: Tue May 28, 2019 12:34 am |
|
|
A Learner has big ears! Taken into the PIC memory address in on side of my head. _________________ All is well even in the well! |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1354
|
|
Posted: Tue May 28, 2019 5:39 pm |
|
|
Ttelmah wrote: | I think you will find it is the #use delay that did the 'override'.
If you have a #use delay statement _after_ the fuse settings, and it
conflicts, the compiler will use the fuses that match the delay, not those
you have already set.
Place the fuses after the #use delay, and your fuses override those
implicit in the delay statement. |
No it wasn't the use delay, which was set to 8MHz. I'm aware of how the order affects the fuses. Commenting out the setup_oscillator() call changed the fuses back to what I set. Uncommenting the setup_oscillator() call changed them to the unworking state.
EDIT:
Here ya go with an example:
Code: |
#include <24fj256ga406.h>
#use delay(clock = 8MHz)
#FUSES FRC
#FUSES NOPR
void main(){
setup_oscillator(OSC_INTERNAL,32000000,8000000);
}
|
Compiler version 5.078 and 5.080
Note that the placement of the #use delay() doesn't actually matter in this case since I specified "clock=" instead of something like "internal=" or "crystal=", which do change fuses. The result is the same even if the #use delay is after the fuses in this configuration (again due to using "clock=").
with that setup_oscillator() line of code the fuses change to:
Code: |
Word 7L: FFE1 FRC_PLL PLL4X IESO
H: 0000
|
take out the setup_oscillator() line and the fuses go back to normal
Code: |
Word 7L: FFF8 FRC NOPLL IESO
H: 0000
|
Again, my fault for not checking the datasheet and seeing the fuses I chose wouldn't work with the setup_oscillator() call. I would have hoped for a compiler error instead of silently changing them. I know it is a very grey line, but having a runtime call change fuses silently was a bit more jarring for me than a precompiler call (like the order and type of #use delay() for example).
Also note that while this example is simple and has the setup_oscillator() call right in the main(), my actual case was 20k lines of code and the call was buried in a function only called when certain commands were to be given. It still affected the fuses in the same way. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Wed May 29, 2019 3:07 am |
|
|
Yes. You can see 'why' it has to do this. On this chip the PLLMODE, is set
in the fuses and cannot be changed. So since you are asking for *4PLL
in the setup_oscillator, it sets this in the fuses.
The error is really that it is done 'silently'. A simple warning that 'PLL
mode changed based on oscillator setting', would save any annoyance.
Ask CCS if they could warn in this situation. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1354
|
|
Posted: Wed May 29, 2019 8:46 am |
|
|
I'd be more of the mind to say for a runtime call to generate a compiler error. Warnings for precompiler directives, as those are the normal means for changing things like FUSES, but errors for runtime calls. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Wed May 29, 2019 1:02 pm |
|
|
Yes, Something simple like 'setup_oscillator mode selected requires PLL*4
fuse setting'. |
|
|
|