View previous topic :: View next topic |
Author |
Message |
bdivi
Joined: 26 Sep 2005 Posts: 3
|
Jump out of while(1) on interrupt |
Posted: Mon Sep 26, 2005 2:27 am |
|
|
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
|
|
Posted: Mon Sep 26, 2005 6:27 am |
|
|
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
|
|
Posted: Mon Sep 26, 2005 6:46 am |
|
|
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
|
|
Posted: Mon Sep 26, 2005 7:03 am |
|
|
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
|
|
Posted: Mon Sep 26, 2005 8:49 am |
|
|
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
|
|
Posted: Mon Sep 26, 2005 9:31 am |
|
|
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. |
|
|
|