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 CCS Technical Support

Jump out of while(1) on interrupt

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



Joined: 26 Sep 2005
Posts: 3

View user's profile Send private message

Jump out of while(1) on interrupt
PostPosted: Mon Sep 26, 2005 2:27 am     Reply with quote

Hello,

I am writing a program for PIC16 to measure a number of counter related things (freq, period, capacitance, etc.) but I am stuck at managing the button events and change system states. Down is the sample code.
I want to jump to the beginning of the measurement cycle on button press and initiate according to the new state not waiting for measurement to complete (some may take 10 sec). Without the goto_address() it changes the state properly but I have to wait for the counting cycle to finish. With the goto_address() it does not seem to do anything. Any help is appreciated.
Code:

#int_rb
void button_interrupt() {
   disable_interrupts(GLOBAL);
   if (input(PIN_B5)==0){
                                // debounce
      currentState++;}      // to next state
      
   else if (input(PIN_B6)==0){
                                // debounce      
                                if (currentState==cap || currentState==ind)
      lc_calibrate();}
      
   else if (input(PIN_B7)==0){
                                // debounce
      if (currentState==cap)
         cap_null();
      else if (currentState==ind)
         ind_null();}
      
   enable_interrupts(GLOBAL);   
   goto_address (label_address(measureCycle));
}

void main() {
   lcd_init();
   system_test();
   
   currentState = freq1s; // this is the initial state
     
    enable_interrupts(INT_RB);
   enable_interrupts(GLOBAL);

measureCycle:   

   while(TRUE)
   {
      switch (currentState){
      case freq01s:
         frequency = pulse_count (ms100);
         display_on_LCD (frequency, gate01s);
         break;
      case freq1s:
         frequency = pulse_count (ms1000);
         display_on_LCD (frequency, gate1s);
         break;
      case freq10s:
         frequency = pulse_count (ms10000);
         display_on_LCD (frequency, gate10s);
         break;
      case period:
         period = measure_period()
         display_on_LCD (period);
         break;
         }
   }
}
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Mon Sep 26, 2005 6:27 am     Reply with quote

The interrupt handler saves working registers when it enters the isr. These registers are then restored when leaving the isr. This code
Code:
enable_interrupts(GLOBAL);
goto_address (label_address(measureCycle));
will trash those registers. In addition, the return address from when the isr was called will be left on the hardware stack. This will also cause you problems.
bdivi



Joined: 26 Sep 2005
Posts: 3

View user's profile Send private message

PostPosted: Mon Sep 26, 2005 6:46 am     Reply with quote

Yes, I can understand the issue.

The question here is how to work it out - I have no problems loosing the W register and the program counter. I just want to trash them and start over from a specific point. I will take care of reinitializing the registers.

Thanks anyway for the help.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Mon Sep 26, 2005 7:03 am     Reply with quote

You could use the watchdog.

Set your state in the ISR
Timeout the watchdog in the ISR
On startup, check for the wdt and bypass and intial startup code (initializations) and go to your state machine.
bdivi



Joined: 26 Sep 2005
Posts: 3

View user's profile Send private message

PostPosted: Mon Sep 26, 2005 8:49 am     Reply with quote

So it is efectively reseting the PIC. I have two questions here:

1. Can I use the reset_cpu() instead?
2. How I preserve the system state after reset? Is the RAM sufficient or I use the EEPROM?
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Mon Sep 26, 2005 9:31 am     Reply with quote

On a wdt the RAM should not be affected. You would not be able to use the #zero_ram CCS option though. This would kill any values that have been stored. Also, any values that need to survive the reset cannot be initialized in their declaration. You will need to do this in the main(). You will need to test to see if the wdt caused the reset. If so, then do NOT initialize the variables since this would destory their values. The reset_cpu() could be used on a PIC18 since you can test to see the cause of the reset. On the PIC16, you would need to set a flag or save an eeprom value to determine that you reset via code. You could use the POR (power on reset) flag to do this. Any reset that is not caused by a power on reset could be used to switch your task. Read the section in the datasheet about the POR.
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