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 CCS Technical Support

rs232 interrupt problem

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



Joined: 14 May 2007
Posts: 14

View user's profile Send private message

rs232 interrupt problem
PostPosted: Thu May 10, 2012 10:05 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu May 10, 2012 10:36 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu May 10, 2012 10:42 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri May 11, 2012 12:31 am     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Sun May 13, 2012 2:27 pm     Reply with quote

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
Very Happy Very Happy Very Happy
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Sun May 13, 2012 10:52 pm     Reply with quote

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
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