串口是流数据,有时候想从串口中得到想要的数据,但是却发现很难处理,因为它没有协议,没有长度。
就例如AT命令会有很多的返回值,通常都是一下字符串,想从串口中正确的拿到这些字符串,并且所有的命令字符串都不丢失。
例如:GETOKlsakOKlsasGETOKlkaslkllOK
这是串口发送过来的数据,我们需要寻找的数据是GETOK,并且里面有2个这样的命令,而且还有很多我们不需要的其它数据。
你会发现你想命令提取到并且其它数据不丢失,串口依然在来新的数据命令。这时候就需要我们写一个解析命令的程序来有效的解析了。
因为是开发这样的一个功能,我并没有选择在单片机上开发,我选择先在windows上面测试。
思路:
1在主线程把(串口)数据放到一个数组队列里面
2在子线程解析命令
需要把上面思想转变到单片机,就是主线程+串口中断
下面是整个代码:
// 串口命令解析.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "windows.h"
#include "string.h"
#include "conio.h"
char mes_buf[1024]={0};
int mes_len=1024;
static int num=0;
char buf1[]="hes";
char buf2[]="off";
char buf3[]="on";
//寻找子串并移除子串
int find_str_del(char *mes,char *str)
{
char *p;
int str_len=strlen(str);
p=strstr(mes_buf,str);
// printf("len:%d",str_len);
if(p)
{
printf("查找到有效指令:%s",p);
memset(p,0,str_len); //查找到的字符清零
//数组移动
num-=str_len;
while(*(p+str_len))
{
*p=*(p+str_len);
p++;
}
memset(p,0,str_len); //后位清零
return 1;
}
return 0;
}
//子线程函数
DWORD WINAPI ThreadFun(LPVOID pM)
{
while(1)
{
//printf("子线程\n");
//Sleep(2000);
find_str_del(mes_buf,buf1);
find_str_del(mes_buf,buf2);
find_str_del(mes_buf,buf3);
Sleep(100);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE handle = CreateThread(NULL, 0, ThreadFun, NULL, 0, NULL);
while(1)
{
//printf("主线程\n");
//Sleep(1000);
char ch=getch();
mes_buf[num++]=ch;
if(num==mes_len)num=0;
printf("主线程输入:%s\n",mes_buf);
}
return 0;
}
效果:
我们可以看到,队列里的数据不断的增加,只要发现有我们指令,立即能解析到并且把指令从数据队列里面移除。其它数据还在里面。
有人会问为什么不直接把其它数据也移除掉,我稍微解释一下,因为其它数据不一定是这样的垃圾数据,有可能串口里面还有其它的
可用命令。或者其它的有效数据待其它功能解析。
这个功能可以引用到很多串口通信的领域。特别是串口控制,AT解析,等等。
开源使科技进步,就算是微不足道我也要去做。