简介:该篇文章描述了如何分离串口传输的命令和参数数值
一般来讲如果不是使用复杂的自定义协议,那么通常标志位+参数是非常有效的一种从串口控制下位机的方式,这里说明下这种分析传入的命令并分离为所需参数的算法
这里我使用Arduino来实现,其他架构也是照葫芦画瓢:
整体流程:
数据传入----记录-----解析出数据-----用于其他逻辑
实现的功能:
例如我传入/A100 /B200,那么数组0将存储整数100和200两个数值
例如我传入/ST 那么就会执行预先设置好的一个函数
1.初始化
初始化一个是内存空间的开辟(我是使用C/C++语言来编写这些代码),另一个是串口初始化与启用
我可以明确的了解要传入的数据会产生最多四组数值,肯定没有第五组因为逻辑是固定的,如果要动态开辟空间可以使用指针链表与类,但在嵌入式环境下不推荐因为容易崩。
因为是主要是演示所以我就简化了对于内存释放的操作。
初始化阶段的代码:
long numdata[4]={0,0,0,0}; //record value
String recData = ""; //recording received data from upper machine
int mark = 0; //process data flag
字符串类型recData,用以记录从串口传入的数据,提供给处理函数进行判断。
整数类型mark,这个在c++中也可以使用bool代替,主要是用来标识目前接收的数据是否处理完了。
char dat[64]="";
int curSetData = 0;
curSetData用于记录目前所赋值的整数在数组的位置,由命令标志来决定
2.数据接收
在串口缓存中还有数据的时候,循环读取记录,并且置数据处理标志位为1
while (Serial.available() > 0)
{
recData += char(Serial.read());
delay(2);
mark = 1;
}
3.数据处理
主要几个步骤,分别为判断数据存在与否,判别命令通用前缀,判断命令,记录数值
判断记录的数值是否为空
if (recData.length() > 1) // judge length
{
Serial.println(recData);
}
else
{
mark = 0;
return;
}
判别命令通用前缀
没有这个前缀就直接返回不作处理,这里写的比较简单
if (recData[0] == '/')
判断命令(参数为字母+数字)
判断命令之后,置记录位,之后向依照记录的值向数组位置存储数据
if (recData[i] == 'V')
else if (recData[i] == 'A')
else if (recData[i] == 'B')
判断命令(参数仅仅为两个字符)
if (recData[0] == '/')
{
if (recData[1] == 'S' && recData[2] == 'T')
{
Serial.print("Start test");
mark = 0;
}
if (recData[1] == 'E' && recData[2] == 'S')
{
Serial.print("Emmergency stop");
mark = 0;
}
}
记录数值
主要是将字符类型转换为整数类型
if (recData[i] >= '0' && recData[i] <= '9')
{
numdata[curSetData] = numdata[curSetData] * 10 + (recData[i] - '0');
}
之后我记录2,3,4,0字符其实也就是重复第一步,然后加上目前已经记录的被转换为数字类型的数值的10倍,也就是最新记录的数字将作为个位数。
反馈数据(调试)
memset(dat,0,64);
sprintf(dat,"Current set: %d,All Value: %d",curSetData,numdata[curSetData]);
Serial.println(dat);
Serial.println(numdata[0]);
Serial.println(numdata[1]);
Serial.println(numdata[2]);
接收数据并处理的部分代码
void serial_get()
{
static int j = 0;
while (Serial.available() > 0)
{
recData += char(Serial.read());
delay(2);
mark = 1;
}
if (mark == 1)
{
if (recData.length() > 1) // judge length
{
Serial.println(recData);
}
else
{
return;
}
if (recData[0] == '/')
{
//using this loop to get number and change to
for (int i = 1; i < recData.length() ; i++)
{
if (recData[i] == 'V')
{
curSetData = 0;
numdata[curSetData] = 0;
}
else if (recData[i] == 'A')
{
curSetData = 1;
numdata[curSetData] = 0;
}
else if (recData[i] == 'B')
{
curSetData = 2;
numdata[curSetData] = 0;
}
if (recData[i] >= '0' && recData[i] <= '9')
{
numdata[curSetData] = numdata[curSetData] * 10 + (recData[i] - '0');
}
}
memset(dat,0,64);
sprintf(dat,"Current set: %d,All Value: %d",curSetData,numdata[curSetData]);
Serial.println(dat);
Serial.println(numdata[0]);
Serial.println(numdata[1]);
Serial.println(numdata[2]);
}
if (recData[0] == '/')
{
if (recData[1] == 'S' && recData[2] == 'T')
{
Serial.print("Start test");
mark = 0;
}
if (recData[1] == 'E' && recData[2] == 'S')
{
Serial.print("Emmergency stop");
mark = 0;
}
}
else
{
return;
}
recData = String("");
mark = 0;
j = 0;
}
}
所有代码:
long numdata[4]={0,0,0,0}; //record value
String recData = ""; //recording received data from upper machine
int mark = 0; //
void setup()
{
Serial.begin(115200);//set serialport baud rate
}
char dat[64]="";
int curSetData = 0;
void serial_get()
{
static int j = 0;
while (Serial.available() > 0)
{
recData += char(Serial.read());
delay(2);
mark = 1;
}
if (mark == 1)
{
if (recData.length() > 1) // judge length
{
Serial.println(recData);
}
if (recData[0] == '/')
{
//using this loop to get number and change to
for (int i = 1; i < recData.length() ; i++)
{
if (recData[i] == 'V')
{
curSetData = 0;
numdata[curSetData] = 0;
}
else if (recData[i] == 'A')
{
curSetData = 1;
numdata[curSetData] = 0;
}
else if (recData[i] == 'B')
{
curSetData = 2;
numdata[curSetData] = 0;
}
if (recData[i] >= '0' && recData[i] <= '9')
{
numdata[curSetData] = numdata[curSetData] * 10 + (recData[i] - '0');
}
}
memset(dat,0,64);
sprintf(dat,"Current set: %d,All Value: %d",curSetData,numdata[curSetData]);
Serial.println(dat);
Serial.println(numdata[0]);
Serial.println(numdata[1]);
Serial.println(numdata[2]);
}
if (recData[0] == '/')
{
if (recData[1] == 'S' && recData[2] == 'T')
{
Serial.print("Start test");
mark = 0;
}
if (recData[1] == 'E' && recData[2] == 'S')
{
Serial.print("Emmergency stop");
mark = 0;
}
}
else
{
return;
}
recData = String("");
mark = 0;
j = 0;
}
}
void loop()
{
serial_get();
}
注:这些代码是和另一位工程师讨论的结果,我们都有应用在一些小制作上,