CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

After SLEEP(), delay is forever.

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
theMagni



Joined: 21 May 2004
Posts: 48
Location: Victoria, BC

View user's profile Send private message Visit poster's website

After SLEEP(), delay is forever.
PostPosted: Fri Aug 06, 2004 3:37 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Aug 06, 2004 4:30 pm     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Fri Aug 06, 2004 5:32 pm     Reply with quote

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. Mad

Thank you.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Aug 06, 2004 6:37 pm     Reply with quote

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

View user's profile Send private message Visit poster's website MSN Messenger

PostPosted: Fri Aug 06, 2004 10:14 pm     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Mon Aug 09, 2004 10:26 am     Reply with quote

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

View user's profile Send private message Visit poster's website

Found the problem.
PostPosted: Mon Aug 09, 2004 3:47 pm     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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