Page 1 of 1
How to parse lines of serial data?
Posted: Thu Sep 22, 2011 9:20 pm
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
Re: How to parse lines of serial data?
Posted: Fri Sep 23, 2011 12:25 am
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");
}
Re: How to parse lines of serial data?
Posted: Fri Sep 23, 2011 12:53 am
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 }
Re: How to parse lines of serial data?
Posted: Fri Sep 23, 2011 5:50 am
by mx270a
Oh, I like the C++ option. I'll try that out.
Thanks,
Lance
Re: How to parse lines of serial data?
Posted: Fri Sep 23, 2011 6:42 am
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.
Re: How to parse lines of serial data?
Posted: Sun Sep 25, 2011 7:55 pm
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
Re: How to parse lines of serial data?
Posted: Tue Sep 27, 2011 9:45 am
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