|
|
View previous topic :: View next topic |
Author |
Message |
Zac280
Joined: 23 Feb 2006 Posts: 1
|
printf during interrupt |
Posted: Thu Feb 23, 2006 3:12 pm |
|
|
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
|
|
Posted: Thu Feb 23, 2006 3:36 pm |
|
|
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
|
|
Posted: Thu Feb 23, 2006 5:39 pm |
|
|
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
|
|
Posted: Thu Feb 23, 2006 6:01 pm |
|
|
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. |
|
|
|
|
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
|