|
|
View previous topic :: View next topic |
Author |
Message |
c0de
Joined: 14 May 2007 Posts: 14
|
rs232 interrupt problem |
Posted: Thu May 10, 2012 10:05 am |
|
|
Hello.
I'm trying to make an app for controlling a door. I use a PIC16F876A, a 4x3 keyboard and a 16x1 LCD.
I have tested the circuit but I can't get the serial interrupt working. The serial connection is ok because I have tested it by reading chars directly in the main loop. I used an example from this forum http://www.ccsinfo.com/forum/viewtopic.php?p=56005 but still doesn't works.
I'm not sure if the port C is set correctly. I use RC3, 4 and 5 as input pins from the keyboard. The other three available pins (RC0,1 and 2) are used for output.
Here is the code:
Code: |
#include <16F876A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,parity=N,bits=8)
#include <flex_lcd16x1.c>
#include <string.h>
///
#define BUFFER_SIZE 15
char key;
char rxdata[BUFFER_SIZE];
int index = 0;
int idata_valid = 0;
int istreamcomplete = 0;
#INT_RDA
void serial_isr ()
{
if( index<BUFFER_SIZE )
{
char rcvd = 0;
rcvd = getc();
if( rcvd=='[')
{
index = 0;
idata_valid = 1;
}
if( idata_valid==1 )
{
rxdata[index]=rcvd;
index++;
if( rcvd==']')
{
idata_valid = 0;
}
if( index>BUFFER_SIZE )
{
idata_valid = 0;
}
if( !idata_valid )
{
istreamcomplete = 1;
index = 0;
}
}
}
return;
}
|
And the main:
Code: |
void main() {
printf("welcome\n\r");
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
set_tris_a(0x00);
set_tris_c(0x38);
output_low(PIN_C0);
output_low(PIN_C1);
output_low(PIN_C2);
output_low(PIN_B0);
lcd_init();
delay_ms(500);
printf(lcd_putc,"\f");
printf(lcd_putc, " PIC16F76 LCD ");
delay_ms(2000);
printf(lcd_putc,"\f");
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
do {
if( istreamcomplete==1 )
{
disable_interrupts(INT_RDA);
if( rxdata[0]==91 )
{
cmd_check(rxdata);
}
deletebuffer();
enable_interrupts(INT_RDA);
}
//keyboard
key=check_keyboard();
lcd_gotoxy(1,1);
printf(lcd_putc,"key: %c",key);
if(key!='X')
printf("KEY: %c \n\r",key);
} while (TRUE);
}
|
The compiler is PCM v4.038 windows.
I would appreciate any idea/help.
Thank you,
Cosmin |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1348
|
|
Posted: Thu May 10, 2012 10:36 am |
|
|
Some general things:
1. Your ISR is kinda large. You should really be doing something like the ISR in the ex_sisr.c file in the examples folder and then in your main determining when the stream starts and ends. The ISR should just read the data and store it away until the main can get to it.
2. In your ISR, I *think* you have to call getc() each time. Currently, you only call it if the IF statement succeeds. You should still call getc() in the other case, even if you don't store the value.
3. You shouldn't declare variables in the middle of code. While the compiler doesn't complain, it isn't standard C and it isn't actually supported by the compiler and can cause bugs.
4. Unless you are using #use fast_io(), you shouldn't be setting TRIS values at all. The compiler will do it for you.
5. You don't have the ERRORS option in your #use rs232(), which you should. Failing to do so can cause your UART to lock up.
6. you really need to dial this code down to a much simpler program that still shows the problem. We don't really need the LCD stuff if it is the UART we are trying to help you with. It just makes it harder to trouble shoot. You should only be providing the #include <pic header>, the FUSES, the ISR, and the main() with just enough code to show the problem. It needs to be compilable so people here can toss it into CCS with a chip and see that it works (or doesn't work). |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu May 10, 2012 10:42 am |
|
|
Read the CCS forum guidelines.
Tell us what works and what does not.
Post the SHORTEST possible complete and compilable code which shows your problem.
Mike |
|
|
c0de
Joined: 14 May 2007 Posts: 14
|
|
Posted: Fri May 11, 2012 12:31 am |
|
|
Thank you for your answers. I apologize for the length of the post but I didn't knew exactly what can cause the interrupt problems. Now everything is clear and I will modify the code according to your suggestions.
Best regards,
Cosmin |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sun May 13, 2012 2:27 pm |
|
|
1- collapsing your buffer to reset it is not good practice
2- adding a character analysis/ decision code to the ISR is dangerous
in that you may be dwelling too long IN said ISR
3- study EX_SISR to see how to do a proper circularly buffered ISR
THEN , extract and examine chars as they arrive in your MAIN() and a global buffer to assemble the string you want to act upon
don't be building the "keeper" string in the ISR , as its bad juju all around
and a bad habit to begin with...
the rule should be - if it is not essential to add code to an ISR - then DON't
in your case it is clear that you don't have to make the ISR as complicated as you have tried to do so far
|
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Sun May 13, 2012 10:52 pm |
|
|
jeremiah wrote: | Some general things:
2. In your ISR, I *think* you have to call getc() each time. Currently, you only call it if the IF statement succeeds. You should still call getc() in the other case, even if you don't store the value.
|
This is a VERY important point.
IF you do not getc EVERY time (and honestly, you can also just read the buffer without using getc (if you look, getc checks to see if there is a char waiting -- well, if you're in the ISR, that's already a given. So it's a waste of an instruction -- at least it's been that was when I look in the past -- so DOUBLE CHECK)
Anyway - You MUST, ABSOLUTELY, POSITIVELY get whatever is in the buffer EVERY SINGLE time the interrupt fires or risk an overflow which makes the PIC unhappy.
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
|
|
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
|