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
How to parse lines of serial data?
Re: How to parse lines of serial data?
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
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
//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;
}
}
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");
}
-
- Posts: 3
- Joined: Fri Sep 23, 2011 12:08 am
Re: How to parse lines of serial data?
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 }
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?
Oh, I like the C++ option. I'll try that out.
Thanks,
Lance
Thanks,
Lance
Re: How to parse lines of serial data?
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.
#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?
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.
-Lance
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");
}
Re: How to parse lines of serial data?
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
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