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

printf during interrupt

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



Joined: 23 Feb 2006
Posts: 1

View user's profile Send private message

printf during interrupt
PostPosted: Thu Feb 23, 2006 3:12 pm     Reply with quote

I need the PIC to send a character once it's been interrupted. It clearly interrupts, as the outputs are all set low, but it won't print anything to the screen on interrupt.

Code:

#include <16F88.h>
#device adc=10
#use delay(clock=4000000)
#use rs232(baud=9600,parity=n,xmit=PIN_B5,rcv=PIN_B2,bits=9)
#fuses NOWDT,INTRC_IO, NOPUT, MCLR, BROWNOUT, NOCPD, NOWRT, NODEBUG, NOPROTECT

char a;
int once=0;
#byte port_b = 6

#INT_RB
RB_isr(){

static char i;
disable_interrupts(global);  //don't get interrupted during interrupt

delay_ms(1000);
      output_low(PIN_A0);
      output_low(PIN_A1);
      output_low(PIN_A2);
      output_low(PIN_A3);
      output_low(PIN_A4);
      output_low(PIN_A6);
      output_low(PIN_A7);
      printf("0"); //Board has been unexpectedly removed, send stop character
         //PC should now send an 8
i = port_b; //read Port B
enable_interrupts(global);

}


void main()
{
   setup_oscillator(OSC_4MHZ|OSC_INTRC);
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_RB);  //enables change on pin interrupt Port B4-B7
   enable_interrupts(global);

   output_high(PIN_B0);  //power LED

   port_b_pullups(TRUE);  //interrupt routine responds to floating Port B
   delay_us(10);

   while(TRUE){

   if(!input(PIN_B4) && !input(PIN_B6)){  //both optical switches have been set, board is ready
      if(once==0){  //Start character should be sent only first time switches close
         printf("9");  //Send start Character
         once++;}
      a=getc();  //receive character from PC
      output_low(PIN_A0);  //Set all segments low
      output_low(PIN_A1);
      output_low(PIN_A2);
      output_low(PIN_A3);
      output_low(PIN_A4);
      output_low(PIN_A6);
      output_low(PIN_A7);
   switch(a){
   case '1': //PC will send characters in the form of numbers, so main program can iterate segments
      output_high(PIN_A0);  //turn a segment on
      break;
   case '2':
      output_high(PIN_A1);
      break;
   case '3':
      output_high(PIN_A2);
      break;
   case '4':
      output_high(PIN_A3);
      break;
   case '5':
      output_high(PIN_A4);
      break;
   case '6':
      output_high(PIN_A6);
      break;
   case '7':
      output_high(PIN_A7);
      break;
      default:  //Receive an 8 to end test cycle and wait for board to be removed
         once=0; //Allow start character to be sent again
         while(!input(PIN_B4) && !input(PIN_B6)){
            //printf("Remove Board\n\r");
            delay_ms(1000);       
         }
      break;
   }
}
   else{
      output_low(PIN_A0);  //keep output pins low while switches are not set
      output_low(PIN_A1);
      output_low(PIN_A2);
      output_low(PIN_A3);
      output_low(PIN_A4);
      output_low(PIN_A6);
      output_low(PIN_A7);
      once=0;
   
   }

}//end while(1)
}//end main
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Feb 23, 2006 3:36 pm     Reply with quote

There are many things wrong with your program. I've fixed some
of them. There are also design problems, such as doing massive
delays inside an isr, including doing printfs inside an isr.

Make the changes shown in bold:
Quote:
#include <16F88.h>
#device adc=10
#use delay(clock=4000000)
#use rs232(baud=9600,xmit=PIN_B5,rcv=PIN_B2, ERRORS)
#fuses NOWDT,INTRC_IO, NOPUT, MCLR, BROWNOUT, NOCPD, NOWRT,
NODEBUG, NOPROTECT, NOLVP



#INT_RB
RB_isr(){

static char i;
disable_interrupts(global); // THIS IS NOT NEEDED
delay_ms(1000);
output_low(PIN_A0);
output_low(PIN_A1);
output_low(PIN_A2);
output_low(PIN_A3);
output_low(PIN_A4);
output_low(PIN_A6);
output_low(PIN_A7);
printf("0"); //Board has been unexpectedly removed, send stop character
//PC should now send an 8
i = port_b; //read Port B
enable_interrupts(global); // THIS WILL CRASH THE PROGRAM

}
specialk



Joined: 12 Nov 2005
Posts: 27

View user's profile Send private message

PostPosted: Thu Feb 23, 2006 5:39 pm     Reply with quote

PCM programmer wrote:

disable_interrupts(global); // THIS IS NOT NEEDED
enable_interrupts(global); // THIS WILL CRASH THE PROGRAM
Why are you suggesting he remove either of these? I use both of them all of the time in the serial interrupt (at the beginning and end) without any issues. While they aren't necessary they certainly will not crash the program.

-special [k]
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Feb 23, 2006 6:01 pm     Reply with quote

Quote:
I use both of them all of the time in the serial interrupt (at the
beginning and end) without any issues. While they aren't necessary they
certainly will not crash the program.


Those two lines are not necessary and one of them is dangerous.
The PIC automatically disables global interrupts when it responds to an
interrupt. Look in section 12-10 of the 16F877 data sheet. It says:
Quote:
When an interrupt is responded to, the GIE bit is cleared
to disable any further interrupt

So you don't have to do it in code. It's done for you in hardware,
automatically.

After the isr is finished, it jumps to the exit code in the CCS interrupt
dispatcher. This code restores all saved registers and executes a
RETFIE instruction. You can see this code in the .LST file.
Section 12-10 of the 16F877 data sheet says:
Quote:
The “return from interrupt” instruction, RETFIE, exits the interrupt
routine, as well as sets the GIE bit, which re-enables interrupts.


If you re-enable global interrupts inside the isr, you are doing so before
the isr has exited, and before the interrupt dispatcher has restored all
the saved registers, and before the RETFIE instruction. If another
interrupt occurs or if one is already pending, the PIC will jump to
the interrupt dispatcher again and overwrite all the saved registers,
and clobber your other saved values, etc. There is no support for
nested interrupts.

The fact that you got away with doing this is just pure luck. In your
situation, the interrupt source is the incoming RS-232 characters.
These occur at a wide enough interval so that the isr and interrupt
dispatcher code have safely exited by the time your next RDA interrupt
occurs. If you had another source of interrupts that occurred
asynchronously to the RDA interrupts (such as INT_EXT or INT_RB),
the program could easily crash.
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