How to parse lines of serial data?

Discussion to talk about software related topics only.
Post Reply
User avatar
mx270a
Posts: 80
Joined: Tue Jan 19, 2010 6:55 pm

How to parse lines of serial data?

Post by mx270a »

I have found examples of how to read serial data and work with it character-by-character, but I'm looking to parse or split the data in larger chunks. Specifically, the incoming data will be messages delimited by a carriage return. I want to split the data at the carriage returns, and then within that one line of data, split that on some other delimiter (a comma or other char).

I have figured out how to append incoming data to a buffer with STRCAT, and I think STRTOK will split the data into pieces. Is there an example of doing this in one of the example applications?

Thanks,
Lance
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: How to parse lines of serial data?

Post by tod »

If you're using C++ you can put the code in a std::string and use friendly commands like find and substr. Here's a simple example that extracts a command from a string up to a delimiter and returns the portion after the delimiter

Code: Select all

	//Extract the command (without parameters) and put in member var
	string ParsedMessage::ParseCommand(string message)
	{
		//Take everything up to the _cmdDelimiter as the command
		const size_t found_pos = message.find(_cmdDelimiter);

		if (found_pos != string::npos)
		{
			_command = message.substr(0, found_pos);
			return message.substr(found_pos + 1);
		}
		else
		{
			_command = message; //no delimiter treat the entire message as the command.
			return EMPTY_STRING;
		}
	}
I don't know if there are examples in the supplied NB code and I quit doing this in C a long time ago, but one basic approach with strtok is as follows

Code: Select all

  char* p_char = strtok(c_string_to_parse, ";\n");  //allow either ; or new line as delimiters
  while (p_char)
  {
   //Depending on how complicated your parsing is you'll have more code and method calls here
  //strncpy and strcat are typically useful

  //Then somewhere in the loop, usually near the end you use strtok again with the  alternate form
      p_char = strtok(NULL, ";\n");
   }
roarsinc2011
Posts: 3
Joined: Fri Sep 23, 2011 12:08 am

Re: How to parse lines of serial data?

Post by roarsinc2011 »

parsing Serial data in C#

01 {
02 InitializeComponent();
03 }
04
05 public void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
06 {
07 RxString = serialPort1.ReadExisting();
08 this.Invoke(new EventHandler(DisplayText));
09 }
10
11 private void Form1_Load(object sender, EventArgs e)
12 {
13 serialPort1.Open();
14 }
15 private void DisplayText(object sender, EventArgs e)
16 {
17 textBox1.AppendText(RxString);
18 }
19 private void textBox1_TextChanged(object sender, EventArgs e)
20 {
21
22 aTimer = new System.Windows.Forms.Timer();
23 aTimer.Tick += new EventHandler(TimerEventProcessor);
24 aTimer.Interval = 500;
25 aTimer.Start();
26 }
27
28 private void TimerEventProcessor(Object sender, EventArgs e)
29 {
30
31 textBox9.Text = "Data In";
32 textBox1.Text = "";
33 }
34
35 private void textBox9_TextChanged(object sender, EventArgs e)
36 {
37 int len = textBox1.Text.Length - textBox1.SelectionLength;
38
39 if (len > 15)
40 {
41 goto GoodSig;
42 }
43 if (len < 15)
44 {
45 goto Other;
46 }
User avatar
mx270a
Posts: 80
Joined: Tue Jan 19, 2010 6:55 pm

Re: How to parse lines of serial data?

Post by mx270a »

Oh, I like the C++ option. I'll try that out.

Thanks,
Lance
User avatar
mx270a
Posts: 80
Joined: Tue Jan 19, 2010 6:55 pm

Re: How to parse lines of serial data?

Post by mx270a »

In case anyone else tries to use strings, you have to add the following lines at the top of the file:

#include <string>
using namespace std;

And then my system was throwing a "unresolved inclusion string" message. To resolve that I had to add another directory to the list of includes. Right click the project, go to Properties, C/C++ Build, Settings, GNU C++ Compiler, Directories, Add, "C:\nburn\gcc-m68k\m68k-elf\include\c++\4.2.1", OK your way out.
User avatar
mx270a
Posts: 80
Joined: Tue Jan 19, 2010 6:55 pm

Re: How to parse lines of serial data?

Post by mx270a »

In case someone searches for this topic in the future, here is a more complete example. This uses the PK70 with quad RS232 serial card, so I have 4 ports to monitor and buffer data on until a carriage return shows up.

Code: Select all

#include <stdio.h>
#include <string.h>
#include <startnet.h>
#include <tcp.h>
#include <iosys.h>
#include <NBPKQuadSerial.h>
#include "io.h"
#include "tasks.h"
#include <iostream>
#include <string>
using namespace std;

int len;
void SerialDataParseLine(int port, string linein) {
	len = linein.length();
	if (len < 10) return; //All the data I deal with will be longer than this
	cout << "P" << port << ": " << linein << endl; //For display only

	if (linein[0] == '#') { //First char is a pound sign
		//Do something with the data
	}
}

string str[4];
size_t found;
void SerialDataAppend(int port, char *buf) {
	str[port].append(buf);
	found = str[port].find("\r\n"); //Check for a line break
	while (found != string::npos) { //Found one
		SerialDataParseLine(port, str[port].substr(0, found)); //Send the line on for processing
		str[port] = str[port].substr(found+2); //Remove the line we just read
		found = str[port].find("\r\n"); //Check for another line break
	}
	if (str[port].length() > 1024) {
		iprintf("Serial RX buffer exceeded 1KB without a line break, cleared.\r\n");
		str[port] = "";
	}
}


void SerialPortTask(void * pd) {
	int i;
	int fd_serial[4];    // Quad serial port fds
	static char Read_Serial[4][256];

	for (i = 0; i < 4; i++) { //Open all 4 serial ports
		fd_serial[i] = PK70QuadOpenSerial(i, 115200, 1, 8, eParityNone );
		//iprintf("Opening Serial Port %d = %d\r\n", i, fd_serial[i]);
	}

	while(1) {
		fd_set read_fds; // Declare fds masks for reading and errors
		FD_ZERO(&read_fds); // Init the read and error masks to 0 (no file descriptors)
		for (i = 0; i < 4; i++) { //Add fds for each serial
			FD_SET(fd_serial[i], &read_fds);
		}
		long wait = 1;
		if (select( FD_SETSIZE, &read_fds, (fd_set *)0, (fd_set *)0, wait)) {
		for (i = 0; i < 4; i++) {
				if (FD_ISSET(fd_serial[i], &read_fds)) {
					int rv = read(fd_serial[i], Read_Serial[i], 256);
					if (rv > 0) { //Got data
						Read_Serial[i][rv] = 0;//Null terminate the data
						SerialDataAppend(i, Read_Serial[i]);
					}
				}
			}
		}
	}
}
DWORD SerialTaskStack[USER_TASK_STK_SIZE];
void StartSerial() {
	iprintf("Starting Serial Port Task.\r\n");
	OSTaskCreatewName(SerialPortTask, (void *)0, &SerialTaskStack[USER_TASK_STK_SIZE], SerialTaskStack, SERIAL_PORT_TASK_PRIO, "QUADSERIAL");
}
-Lance
User avatar
pbreed
Posts: 1088
Joined: Thu Apr 24, 2008 3:58 pm

Re: How to parse lines of serial data?

Post by pbreed »

If you are trying to do command line parsing after a CR
Then you should look at and play with the telnet command example.

nburn\examples\telnetcmd

You do not need to use telnet with this.
It can be 100% serial.
It handles the parsing into complete lines and hands the finished buffer to your processing function
with a FILE * so you can just use fprintf to respond and all the steering logic to make responses go to the right place are handled for you.

Paul
Post Reply