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

RS232, Interrupts, RX Buffer, and strstr

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



Joined: 21 Jul 2005
Posts: 36

View user's profile Send private message

RS232, Interrupts, RX Buffer, and strstr
PostPosted: Wed Jul 12, 2006 4:18 am     Reply with quote

My code reads into an RX buffer, compares the incoming data to a string, then outputs the following 4 characters in the buffer if the string is matched.

At least, its supposed to do that...
I used ex_sisr.c as a framework.

RX code:

Code:

#include <18F452>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=40000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7, DISABLE_INTS, STREAM=Wireless) //Wireless
#use rs232(baud=115200, xmit=PIN_B1, rcv=PIN_B0, DISABLE_INTS, STREAM=Computer) //Computer


#define BUFFER_SIZE 64
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
char lam_tx1[] = "TX001";
char *ptr;
#include <string>

#int_rda
void serial_isr() {
   int t;

   buffer[next_in]=fgetc(Wireless);
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!
}

#define bkbhit (next_in!=next_out)

BYTE bgetc() {
   BYTE c;

   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}



void main() {
int i;

   enable_interrupts(global);
   enable_interrupts(int_rda);

   fprintf(Computer, "\r\n\Running...\r\n");

               // The program will delay for 10 seconds and then display
               // any data that came in during the 10 second delay

   do {
      delay_ms(10000);
      fprintf(Computer, "\r\nBuffered data => ");
      while(bkbhit)
        fputc(bgetc(),Computer );
ptr = strstr(buffer,lam_tx1);

if(ptr!=NULL)
{
disable_interrupts(global);
ptr=NULL;
fprintf(Computer,"\n\rTX001 found\n\r");
fprintf(Computer,"\n\r\n\r4 characters after TX001: ");
for(i=0;i<3;i++)
{
fputc(ptr+i,Computer);
}
fprintf(Computer,"\n\r\n\r");
enable_interrupts(global);

} //end of strstr if

   } while (TRUE);
}


TX code is simply a repeating string. PIN_E2 is a diagnostic LED (this flashes as it should):

Code:

//******************************************************************************
// INCLUDE FILES
#define Fosc 40000000               // I'm using a 40 MHz crystal
#include <18F452>
#device *=16 ADC=10

// COMPILER DIRECTIVES and HARDWARE CONFIGURATION
//#use delay(clock = Fosc)

#fuses EC_IO      // EC Oscillator with RA6 configured as DIO
#fuses NOOSCSEN      // Oscillator System Clock Switch Disabled
#fuses NODEBUG      // No Background Debugger
#fuses NOLVP      // Low Voltage ICSP Disabled
#fuses NOPROTECT    // No Code Protect
#fuses NOWDT      // No onboard watchdog
#fuses PUT         // Power Up Timer Enabled
#fuses BROWNOUT      // Brown Out Reset enabled


#use delay(clock = Fosc)

#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7, STREAM=Wireless)




// MAIN PROGRAM & SETUP

void main()
{
term=0;
setup_adc(ADC_CLOCK_DIV_64);// Fastest method of reading adc with 40MHz clock
setup_adc_ports( ANALOG_RA3_REF ); //
// LED output showing Init
output_high(PIN_E2);
delay_ms(500);
output_low(PIN_E2);
delay_ms(500);
output_high(PIN_E2);
delay_ms(500);
output_low(PIN_E2);



while(1)
{

output_low(PIN_E2);
fprintf(Wireless,"TX001DATA\n");

output_high(PIN_E2);


delay_ms(2000);
} //end of while 1

} //end of main


I have disable_interrupts in the RX code to prevent data interrupting the
strstr compare with the buffer.

This code isn't totally what I want.

What I'm looking for is some code that will listen for
TXZZZYYYY

where ZZZ is a 3 digit number, YYYY is a 4 character string (e.g. DATA), and based on what ZZZ and YYYY are, I want the PIC to capture the next so many characters from RS232 In.

(e.g. sending TX00132KS would tell the PIC to capture the next 32k characters, or so on.)

Any ideas?
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Jul 12, 2006 5:21 am     Reply with quote

Its relatively straight forward as long as you have some sort of delimiter to synchronize to such as the TX or maybe a character that is unique.

Extract from the work buffer to a command buffer.

Say you know your commands always start with $. You would extract a character from the ring buffer, if it is a $ character then set the offset of you command buffer to 0, set a flag to indicate you have found the sync character, and clear the characters_in_command_buffer counter. Fetch the next character from the ring buffer and put into the next location of the command buffer. If a $ then repeat the previous process (i.e. ignore contents of the buffer) anything else if valid for that offset (as determined by the offset into the command buffer then continue, if valid, flush the buffer and clear the flags. Once you have received all the characters into your command buffer you can pass the command buffer to your command interpreter (call) when it returns form the call - flush all flags and pointers and start again.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
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