|
|
View previous topic :: View next topic |
Author |
Message |
theMagni
Joined: 21 May 2004 Posts: 48 Location: Victoria, BC
|
After SLEEP(), delay is forever. |
Posted: Fri Aug 06, 2004 3:37 pm |
|
|
Hello, group:
I'm using a 16F87/88 and I'm getting it to sleep to save power. It is to wake up after a prescribed time and do some more tasks. The timekeeping and interrupting are taken care of by an Epson RTC.
The timer interrupt (attached to int_ext) wakes up the chip successfully, and it continues to work as expected. However, once the program gets to a delay_ms(1000); call, the program hangs indefinitely. I know that the code is good, as it runs with no problems the first time around.
I am using the internal oscillator, and the ISR does include an OSCILLATOR refresh. Note that the delay is not the first line, and many other functions (without delays) are running great. It's only at the delay line does the program freeze. The #use_delay is there because I've tried it with and without to no avail.
If you can help me out, it would be greatly appreciated.
Code: |
#int_ext
void wakey_wakey()
{
//The first step - as always - is to turn on the oscillator.
OSCILLATOR = 0b01101100;
#use delay(clock=4000000)
//Reading and/or writing the port clears the interrupt flags.
PORT_B = PORT_B;
//turning off the GPS line makes the GPS_fix functions time out.
CS_GPS = LOW;
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 06, 2004 4:30 pm |
|
|
Quote: | However, once the program gets to a delay_ms(1000); call, the program hangs indefinitely |
One possible answer could be that the PIC is not really running at 4 MHz,
even though you think it is. It might be running at 31.25 KHz.
At 4 MHz, an instruction cycle takes 1 us. So a software delay loop
for 1 second would execute 1 million instruction cycles. But suppose
you're really running at 31.25 KHz ? Then an instruction cycle is 128 us.
If you had a #use delay(clock=4000000) statement, then your 1 second
delay would become 128 seconds. Your program would appear to hang.
To check if this is happening, temporarily change the delay to 8 ms.
Change it from this:
delay_ms(1000);
to this:
delay_ms(8); |
|
|
theMagni
Joined: 21 May 2004 Posts: 48 Location: Victoria, BC
|
|
Posted: Fri Aug 06, 2004 5:32 pm |
|
|
Woah, that's right. Good catch. Thanks. Now, the question I have is:
"Why isn't it running at 4MHz, even though I explicity told it to run at 4MHz?"
I've been struggling with this for most of the day, so imagine that question with as many expletives as you see fit.
Thank you. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 06, 2004 6:37 pm |
|
|
Can you post the #byte statement where you declare the register
address of the OSCILLATOR register ?
There are two registers in the 16F88 associated with the oscillator.
One of them is called OSCCON and the other is OSCTUNE.
It bothered me a little bit to see that you were using "OSCILLATOR"
as the register name, because then there's no way to know what
PIC register you're actually referring to. I assume that your
intention is to use OSCCON. It's address is 0x8F. Can you confirm
that your #byte statement is set to this value ? |
|
|
Gabriel Caffese
Joined: 09 Oct 2003 Posts: 39 Location: LA PLATA, ARGENTINA
|
|
Posted: Fri Aug 06, 2004 10:14 pm |
|
|
Hi,
If you want your micro to run at 4Mhz, just do this:
#use delay(clock=4000000)
setup_oscillator(OSC_4MHZ);
When you want to slow down to 31Khz, run these lines:
#use delay(clock=31000)
setup_oscillator(OSC_31KHZ);
Gabriel.- |
|
|
theMagni
Joined: 21 May 2004 Posts: 48 Location: Victoria, BC
|
|
Posted: Mon Aug 09, 2004 10:26 am |
|
|
PCM programmer wrote: | Can you post the #byte statement where you declare the register
address of the OSCILLATOR register ?
|
Code: |
#byte OSCILLATOR = 0x8F
#bit OSC_STABLE = OSCILLATOR.2
#byte OSC_TUNE = 0x90
|
I know it's not the "official" name, but this way it's easier for me to remember what it is. The plan was to be able to say "OSCILLATOR = FOUR_MHZ;" so it would be really easy to see when the speed changes.
Anyway, further testing has shown that the interrupt isn't what changes the speed; the loop itself is changing the speed. Here's the main routine. If anyone could figure out what is changing the oscillator speed, that would be excellent. The sleep() function is commented out on purpose.
Thanks for your help.
Code: |
main()
{
/*This minor main routine does the following:
1. Checks the the SEEPROM next location.
2. Broadcasts all fixes when turned on.
3. Gets a fix every hour.*/
struct GPS_data G_P_S;
int compressed_GPS[10];
int1 status = 0;
long seeprom_location = 0;
long counter = 0;
int data = 0;
//initialize. Set the tristating, the oscillator, etc.
OSCILLATOR = 0b01101100;
do{/*nothing*/}while(!OSC_STABLE);
TRIS_A = 0b00000000;
TRIS_B = 0b00000011;
CS_GPS = LOW;
CS_EEPROM = HIGH;
CS_RTC = LOW;
VHF_MOD = LOW;
CS_RTC_READ = LOW;
PORT_B = PORT_B;
setup_spi( SPI_MASTER | SPI_H_TO_L );
ext_int_edge( H_to_L );
enable_interrupts( int_ext );
enable_interrupts( global );
//put something in the ID number field.
write_EEPROM( ID_NUMBER, 5 );
//status = set_address(0);
//check the memory location
seeprom_location = get_address();
status = write_RTC( RTC_FOUT_CONTROL, 0b00000000 );
//broadcast all the GPS fixes.
//broadcast the GPS data from the SEEPROM
//The seeprom is only 15 bit, so a number beyond that is clearly
//wrong, and the SEEPROM has not been initialized.
if( seeprom_location < 32767 )
{
status = transmit_high_speed_data( 0 );
}
else
{
status = reset_SEEPROM();
}
delay_ms(200);
vhf_chirp(2);
//get a fix
//RS-232 mode
do
{
OSCILLATOR = 0b01101100;
do{/*nothing*/}while(!OSC_STABLE);
//turn off chirps
TRIS_A = 0b00000000;
TRIS_B = 0b00000011; //back to SPI mode.
CS_GPS = LOW;
CS_EEPROM = HIGH;
CS_RTC = LOW;
VHF_MOD = LOW;
CS_RTC_READ = LOW;
PORT_B = PORT_B;
//turn off the chirp
status = write_RTC( RTC_FOUT_CONTROL, 0b00000000 );
//set the AIRQ to hi-Z.
status = write_RTC( RTC_CONTROL1, 0b00000000 );
//get a fix
//RS-232 mode
TRIS_B = 0b00000111;
G_P_S.almanac = 0;
G_P_S.gotdate = 0;
status = get_GPS_fix( &G_P_S );
//chirp 3 times when a fix is found.
vhf_chirp(3);
//spi mode;
TRIS_B = 0b00000011;
if( G_P_S.quality )
{
status = sync_time( &G_P_S );
TRIS_B = 0b00000011;
}
//chirp at 60 ppm (so we know it's running)
status = write_RTC( RTC_FOUT_CONTROL, 0b10110000 );
//get the fixes on the hour.
status = disable_RTC();
data = read_RTC( RTC_MIN );
data += 0x10;
if(data > 0x59 )
{
data -= 0x60;
}
status = write_RTC( RTC_MINUTES_ALARM, data );
status = write_RTC( RTC_HOURS_ALARM, 0b10000000 );
status = write_RTC( RTC_WEEK_ALARM, 0b10000000 );
status = write_RTC( RTC_DAY_ALARM, 0b10000000 );
status = write_RTC( RTC_CONTROL1, 0b00000010 );
//start the clock up.
status = enable_RTC();
TRIS_B = 0b00000111;
printf("LRM: %x\n\r", data);
if( G_P_S.quality )
{
seeprom_location = get_address();
status = pack_data_type_4( &G_P_S, compressed_GPS );
TRIS_B = 0b00000011; //back to SPI mode.
for( counter = 0; counter <= 10; counter ++)
{
//write the next byte of the GPS data.
status = write_SEEPROM( seeprom_location + counter,
compressed_GPS[counter] );
}
status = set_address( seeprom_location + 10 );
status = vhf_transmit( compressed_GPS, 10 );
TRIS_B = 0b00000111;
printf( "WT: %lu \n\r", seeprom_location );
}
//go to low-power mode and wait for the RTC alarm to turn
//the chip back on.
//sleep();
}while(true);
delay_us(10);
}
#int_ext
void wakey_wakey()
{
//The first step - as always - is to turn on the oscillator.
OSCILLATOR = 0b01101100;
do{/*nothing*/}while(!OSC_STABLE);
//#use delay(clock=4000000)
//Reading and/or writing the port clears the interrupt flags.
PORT_B = PORT_B;
//turning off the GPS line makes the GPS_fix functions time out.
CS_GPS = LOW;
}
|
|
|
|
theMagni
Joined: 21 May 2004 Posts: 48 Location: Victoria, BC
|
Found the problem. |
Posted: Mon Aug 09, 2004 3:47 pm |
|
|
That was fun. The problem was with the vhf_tansmit() function - I didn't disable the Timer One counter, and for some reason it was making the delay run forever.
Weird. Eerie.
Thanks for the help. |
|
|
|
|
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
|