|
|
View previous topic :: View next topic |
Author |
Message |
asherc
Joined: 21 Apr 2010 Posts: 4
|
Select clock source |
Posted: Wed Apr 21, 2010 5:57 am |
|
|
Hello ! I am coding for a pic18f45j10. For power saving I want to switch between internal clock INTRC and 4 x pll clock, which with a 10MHz xtal should be 40MHz. Datasheet says OSCCON scs0.1=11 selects INTRC. After reset scs0,1=00. When I try to write it to be 11 the scs0 will not change but scs1 changes to 1 in the initialize routine. I wonder if I have a mistake or maybe there is a simulator problem. Here is the code:
Code: |
#include <18f45j10.H>
#device HIGH_INTS = TRUE
#fuses H4_SW, NOWDT//,DEBUG
#use DELAY(CLOCK=40,000,000)
#use FAST_IO(A)
#use FAST_IO(B)
#use FAST_IO(C)
#use FAST_IO(D)
#use FAST_IO(E)
#use RS232(BAUD=9600, XMIT=PIN_C6,RCV=PIN_C7)
#byte TRIS_B = 0xF93 //location for tris_b taken from raph code
#byte LAT_B = 0xF8A //
#byte PORT_B = 0xF81
#bit LED = LAT_B.5 //make code nice and readable
#bit INT0 = LAT_B.0 //might take a look in watch window.
#byte TRIS_D = 0xF95
#byte LAT_D = 0xF8C
#byte PORT_D = 0xF83
#BIT night = PORT_D.7 //from the light sensor
#BIT disconnect = LAT_D.6 //disconnect the 12v system
#byte INTCON = 0xFF2 //
#bit INT0IF = INTCON.5 //Later might poll instead of enter isr if not play nice
#byte INTCON2 = 0xFF1 //01000000 !RBPU=X, INTEDG0=1, INTEDG1=X, INTEDG2=X, -, TMR0IP=X,-, RBIP=X
#BIT INTEDG0 = INTCON2.4
#byte OSCTUNE = 0xF9B //
#bit PLLEN = OSCTUNE.6
#byte OSCCON = 0xFD3 //
#BIT SCS0 = OSCCON.0 //these scs0&1 select the clock source 11 = INTRC, 01 = primary clock (4 x 10MHz; H4_SW)
#BIT SCS1 = OSCCON.1
#BIT OSTS = OSCCON.3 //oscillator ready when set
//define a boolean type to help keep code compatible with pseudo code specification
typedef short int myboolean;
#define Truee 1
#define Falsee 0
#define ledon 0
#define ledoff 1
//these are my global signal and function delarations
myboolean C_Ok_internal = falsee; //boolean variable to capture valid interupt
unsigned char Clip=1, Line=201 ; //used to reference mp3 tracks
unsigned char Count120 = 0; //used to count to 2 minutes
//string Int_To_String(int) ; //convert integer to string
void Initialize(void); //initialize IO, clock, low power mode, interrupt, ..
void HSPLLtoSysCk(void); //make high speed pll (4x10Meg) the system clock
void INTRCtoSysCk(void); //make internal (slow !) INTRC (32kHz) the system clock
myboolean Valid_Interrupt(void) ; //ensure valid interrupt
//void _12V_Disconnect(bool); //disconnect/reconnect 12 volt system to save power
//myboolean Night_Time(void) ; //test the light sensor. dont play lines when its night time
void Play (unsigned char) ; //play the track referenced by 8 bit argument (1 to 250)
void main (void)
{
Initialize(); //Initialize IO, Clock, power save state, interupt
while (1) //loop forever
{
if (Count120 == 120) //true when player has been inactive for 2 minutes
{
disconnect = falsee; //reconnect power to sensor so can read light sensor
DELAY_MS(100); //give the light sensor some time to make reading
if (!night) //only play lines if the lights are one
{
HSPLLtoSysCk(); //make high speed pll (4x10Meg) the system clock
Play(Line); //play the next line
INTRCtoSysCk(); //go back to the slow clock
if (Line == 250)
{ Line = 201; }
else
{ Line++ ; } //increment line between 200 and 250
}
disconnect = truee; //disconnect power to audio amplifier and sensor to save power
Count120 = 0; //reset the counter
}
if (C_Ok_internal ) //true when there has been a valid interupt
{
disconnect = falsee; //reconnect 12 volt power
HSPLLtoSysCk(); //make high speed pll (4x10Meg) the system clock
Play(Clip); //play the next Clip
disconnect = truee; //disconnect power to audio amplifier and sensor to save power
INTRCtoSysCk(); //go back to the slow clock
if (Clip == 200)
{ Clip = 0; }
else
{ Clip++ ; } //increment Clip between 0 and 200
Count120 = 0; //reset the counter
C_Ok_internal = falsee; //clear my interrupt flag
}
DELAY_MS(100); //fingers crossed this is about 1 second (32kHz)
Count120++; //increment the counter
}
}
//want to interupt fast cos might be playing mp3
#INT_EXT FAST //pre compile directive
VOID ext_isr(VOID)
{
C_Ok_internal = valid_Interrupt();
}
myboolean Valid_Interrupt(void) //ensure valid interrupt
{
myboolean V_I;
//check integrity of signal
DELAY_MS(1); //wait one cycle to test INT0 to be sure not a glitch
if (INT0 == 1 ) //if still high then no glitch
{
V_I = truee;
DELAY_MS(50); //wait till signal inactive before returning
}
else
{
V_I = falsee;
}
//INTCONbits.INT0IF = 0; //clear the INT0 interupt flag// dont need to do this for ccs
return V_I;
}
void Initialize (void)
{
//set up external interrupt on port b 0 (INT0).
INTCON = 0b11010000 ; //GIE=1, PEIE=1, TMR0IE=0, INT0IE=1, RBIE=0, TMR0IF=0, INT0IF=0, RBIF=0
INTEDG0 = 1; //rising edge
//set port b 5 to output and light the led
TRIS_B = 0b11011111 ; //others can be input cos i think the might be used for icd
LED = LEDON; //this turns the LED on as it is connected to Vdd
// bit7 on the Port D is from the light sensor. bit6 on the Port D drives the 12 volt system disconnect relay.
TRIS_D = 0b10111111; //
disconnect = true; //start with 12v system disconnected
//perhaps better to enable the PLL straight away as this might help switching to it
PLLEN = 1; // Enable PLL
INTRCtoSysCk(); //to save power select the 32kHz internal clock (INTRC) as system clock
}
void HSPLLtoSysCk(void) //make high speed pll (4 x 10Meg xtal) clock the system clock
{
// set OSCCON<1:0> = 10 to select primary clock (HSPLL) as system clock
SCS0 = 0;
SCS1 = 1;
//Primary clock source set by FOSC 0:1 (HSPLL / H4_SW)
//SPI_WRITE(0xFF);
}
void INTRCtoSysCk(void) //make internal slow IntRc the system clock
{
// set OSCCON<1:0> = 11 to select INTRC as system clock
SCS0=1;
SCS1=1;
}
void Play (unsigned char Track_Number) //play the track Track_Number.mp3 in MMC
{
unsigned char Count10 = 10;
//for easy play iteration of code, 3 frequencies will be displayed on the led. If it is
//a line, then will use a slow frequency. If a clip less than 10, then will use twice the frequency.
//If it is a clip > 10 then will make it twice as fast again. Will make it flash 10 times
while (Count10)
{
if (Track_Number > 200) //it is a line
{
led=ledoff;// switch off led
Delay_ms(250); //fingers crossed this is about 2 seconds (40MHz)
led=ledon;// switch on the led
}
if (Track_Number < 10) //clip < 10
{
led=ledoff;// switch off led
Delay_ms(125); //fingers crossed this is about 1 second (40MHz)
led=ledon; // switch on the led
}
if (Track_Number > 10 && Track_Number < 201)
{
led=ledoff;// switch off led
Delay_ms(60); //fingers crossed this is about .5 seconds (40MHz)
led=ledon;// switch on the led
}
Count10--;
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Wed Apr 21, 2010 7:18 am |
|
|
Several comments:
First, something like 50$%of your code, is pointless. There is no point in declaring the TRIS, and LAT registers, the compiler already knows where these are. Just use the set_tris_x function, and the output_high/low functions. It'd make your code more readable, and less likely to have errors.
Second, you are using the 'FAST' interrupt ability. Now, you show a function being called in this interrupt, but not the code used for this. _BEWARE_. The fast interrupt, requires _you_ to do all the work associated with saving registers in the interrupt handler. Unless you are doing so, your code won't work properly... The speed here comes at the cost of _you_ having to understand exactly what must be done inside an interrupt handler.
Third, why not just use the setup_oscillator function?.
setup_oscillator(OSC_INTRC);
setup_oscillator(OSC_NORMAL|OSC_PLL_ON);
Use the compiler.
Best Wishes |
|
|
asherc
Joined: 21 Apr 2010 Posts: 4
|
|
Posted: Thu Apr 22, 2010 3:08 am |
|
|
thank you Ttelmah for your comments. i agree it seems silly to declare built in registers and worse still to assign them address locations. the thing is i am using legacy code as a framework as i need to use some chunks of that code later. besides when i commented out the #byte lines for port b it did not compile. I take the point about using FAST interrupt thanks for that.
Unfortunately using setuo_oscillator(osc_intrc) has produced exactly the same result as me directly assigning the osccon bits scs0 and scs0. the problem is scs0 will not change from 0 to 1. i would have been somewhat disquieted if there had been a difference frankly.
i am wondering if this is a bug in the mplab simulator?
much appreciate any suggestions |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Thu Apr 22, 2010 4:23 am |
|
|
Didn't spot you were using a simulator.
Yes.
Historically, MPLAB, has always had problems with anything that changes clock rates after boot.
Best Wishes |
|
|
|
|
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
|