View previous topic :: View next topic |
Author |
Message |
Twitie
Joined: 08 Nov 2004 Posts: 11
|
RS232 Interrupt problem~~ |
Posted: Mon Nov 08, 2004 7:42 pm |
|
|
Hello all~! I am a student and currently I am doing a project using RS232 interrupt. I did a test on this (code below) and found that the interrupt was working only for the first time. When it returned to the main function and I send 'c' again for second time interrupt, it won't work anymore. Any problem with my code?
Code: |
#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#int_rda
void serial_isr() {
char value;
value=getc();
if(value=='c')
{
output_high(PIN_D0);
output_high(PIN_D1);
}
}
void main()
{
enable_interrupts(global);
enable_interrupts(int_rda);
printf("Enter 'c' \r\n");
do
{
output_high(PIN_D0);
delay_ms(300);
output_low(PIN_D0);
delay_ms(300);
output_high(PIN_D1);
delay_ms(300);
output_low(PIN_D1);
delay_ms(300);
} while (TRUE);
}
|
Thx a lot~!! |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Mon Nov 08, 2004 9:29 pm |
|
|
I am not sure if you have these leds flashing just to test interrupt or if needed for your actual project. If this is just to test interruppts then here is an alternative you might want to try.
Code: | #include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
bit found_it;
#int_rda
void serial_isr() {
char value;
value=getc();
if(value=='c')
found_it = true;
}
void main()
{
found_it = false;
enable_interrupts(global);
enable_interrupts(int_rda);
printf("Enter 'c' \r\n");
do
{
if (found_it)
{
found_it = false;
output_high(PIN_D0);
output_high(PIN_D1);
delay_ms(300);
}
output_high(PIN_D0);
delay_ms(300);
output_low(PIN_D0);
delay_ms(300);
output_high(PIN_D1);
delay_ms(300);
output_low(PIN_D1);
delay_ms(300);
} while (TRUE);
}
|
_________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Twitie
Joined: 08 Nov 2004 Posts: 11
|
|
Posted: Mon Nov 08, 2004 10:18 pm |
|
|
Thx asmallri ~
The code works. However, the "bit found_it;" cannot be declared. I change it to "boolean found_it;" and it works.
Anyway, I wonder why my code is not working since both codes are logically the same. |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Mon Nov 08, 2004 10:27 pm |
|
|
Try 'int1' instead of 'bit'. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Mon Nov 08, 2004 11:38 pm |
|
|
Quote: | Anyway, I wonder why my code is not working since both codes are logically the same. |
I didn't go through it before because I dod not know what you were trying to achieve. The original code used a function both inside and outside the interrupt hander. Some of the CCS code is non rentrant because a local variable used by the handler would be overwritten by the interrupt hander using the same functions. The compiler deals with this by adding a disable interrupt instruction to the fuction outside the interrupt handler. I believe (but do not know for sure) that this only happens when the function appears both inside and outside an interrupt handler. I do not know if this is the case with output_xxxx() functions - you would need to look into the .lst file to see what the compiler is doing. However the output_xxxx() functions contain multiple lines of assembler and you are interrupting this code. There are scenarios where this can cause problems as output ports may not be setback to the same state they were in prior to the interrupt but I do not know if this is happening in this case - again you would need to examine the .lst file to see if this is possible.
The real difference is the use of the flag in the new version. If the flag is set then you are going to set both LEDs outputs high and they will remain high for 300ms so you will see them. In the original version you interrupt handle could set the output high but the outputs then could be immediatley changed by the mainlie code on return from interrupt in which case you would not be able to see anything happening. In other words the interrupt handle in the new version does not do the "grunt work" it sets a flag and the mainline does the work. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Tue Nov 09, 2004 1:36 am |
|
|
asmallri wrote: |
I didn't go through it before because I dod not know what you were trying to achieve. The original code used a function both inside and outside the interrupt hander. Some of the CCS code is non rentrant because a local variable used by the handler would be overwritten by the interrupt hander using the same functions. The compiler deals with this by adding a disable interrupt instruction to the fuction outside the interrupt handler. I believe (but do not know for sure) that this only happens when the function appears both inside and outside an interrupt handler. I do not know if this is the case with output_xxxx() functions - you would need to look into the .lst file to see what the compiler is doing. However the output_xxxx() functions contain multiple lines of assembler and you are interrupting this code. There are scenarios where this can cause problems as output ports may not be setback to the same state they were in prior to the interrupt but I do not know if this is happening in this case - again you would need to examine the .lst file to see if this is possible. |
This is not the case for output_xxxx() functions since they are always implemented as inline.
I'm suspecting the way the original code changed the RD0 and RD1 is the culprit. They were toggled both inside the ISR and in the main(), so in the event of an interrupt happening, it would be difficult to distinguish what was actually changing them. They may have been high due the code in the main() while the ISR also set them high.
In the original code change your ISR to the code below and see if RD2 toggles everytime you press 'c'.
Code: | #int_rda
void serial_isr() {
char value;
value=getc();
if(value=='c')
output_toggle(PIN_D2);
}
|
|
|
|
Guest
|
|
Posted: Tue Nov 09, 2004 3:23 am |
|
|
I tried and it is working~ thx a lot guys! thx for helping. |
|
|
|