|
|
View previous topic :: View next topic |
Author |
Message |
bwgames
Joined: 21 Jul 2005 Posts: 36
|
RS232, Interrupts, RX Buffer, and strstr |
Posted: Wed Jul 12, 2006 4:18 am |
|
|
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
|
|
Posted: Wed Jul 12, 2006 5:21 am |
|
|
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!! |
|
|
|
|
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
|