多功能嵌入式解码软件
概述
在嵌入式开发的过程中,由于经常需要下位机与上位机通信,通信之间就需要协议,有协议就需要进行解码,而产品开发得过程中,协议可能不断更新,协议更新就需要解码软件更新,不断更新解码软件就很麻烦,如果所有人都愿意麻烦,那么我不愿意。在这里就产生了一个通用的解码类库,使用者就可以简单的改一下协议文件,通过调用这个类库,就可以实现解码,不需要再更改解码算法了。
class_frame类库就是这样的一个很方便的库件。
类库简介
1 #region 程序集 xutopia, version=1.0.0.0, culture=neutral, publickeytoken=null 2 // d:\workspace\09 uarttool\19\mydll\xutopia\xutopia\bin\debug\xutopia.dll 3 #endregion 4 5 using system.collections.generic; 6 7 namespace xutopia 8 { 9 public class class_frame 10 { 11 public bool protocolfresh; 12 public string framemsg; 13 14 public class_frame(); 15 16 public _decodedattimelystruct decodetimely(byte rxddat); 17 public void process_protocol_readed(string strpro); 18 public list<_savedecodestruct> savedecodedat(list<byte> listrxd); 19 20 public struct _decodedattimelystruct 21 { 22 public byte function; 23 public list<object> listre; 24 } 25 public struct _savedecodestruct 26 { 27 public byte function; 28 public string str; 29 } 30 } 31 }
名称空间:xutopia;
类的名称:class_frame;
属性:
public bool protocolfresh;
true : 已经正确解析出协议;
false : 没有协议。
public string framemsg;
解析出协议的信息。
方法:
public _decodedattimelystruct decodetimely(byte rxddat);
param:
rxddat:接收到的数据;
retval:
_decodedattimelystruct:解码的信息;
function : 功能码;
listre: 解码的数据。需要强制类型转换后才能使用。
public void process_protocol_readed(string strpro);
param:
strpro:读取到的协议文件;
public list<_savedecodestruct> savedecodedat(list<byte> listrxd);
param:
listrxd:接收到的数据的泛型集合。
retval:
每一种功能码的解码数据:
function:功能码;
str : 需要保存的数据。
验证类库
通信协议
下面进行一个示例:
下位机需要向上位机发送3中数据帧,数据帧以功能码来识别,每种数据帧的协议如下3个表格所示,上位机需要把这些数据按照协议解码出来,并进行保存以便分析。
通信协议:
准备协议文件
按照通信协议编写协议文件
/*
this is a protocol
2019-03-28
正文中不可以出现注释
e.g. 正文//注释内容
e.g. 正文
//注释内容
正文开头第一行必须是frametype
*/
/*
目前最后一行必须是空行
*/
frametype=header2 function
header1=0xa0
header2=0xa1
body=1
function=0xb1
index=1,type=unsigned char
index=2,type=unsigned short
index=3,type=unsigned int
index=4,type=short
index=5,type=int
index=6,type=float
index=7,type=double
endbody
body=2
function=0xb2
index=1,type=unsigned char
index=2,type=unsigned short
index=3,type=unsigned int
index=4,type=short
index=5,type=int
index=6,type=float
index=7,type=double
endbody
body=3
function=0xb3
index=1,type=unsigned char
index=2,type=unsigned short
index=3,type=unsigned int
index=4,type=short
index=5,type=int
index=6,type=float
index=7,type=double
endbody
check=crc-ccitt
-----end file-----
模拟下位机发送数据
为了方便分析,这里使用虚拟串口助手在电脑上模拟出两个串口端口
编写软件模拟下位机按照协议发送数据
类库使用方法
读取协议文件
1 private void buttonreadprotocol_click(object sender, routedeventargs e) 2 { 3 string[] txtread = new string[2]; 4 5 txtread = selected_txt(); 6 if (txtread == null) 7 return; 8 textboxsettinglog.appendtext(txtread[0] + "\r\n"); 9 s.pro_read = txtread[1]; 10 c_f.process_protocol_readed(s.pro_read); 11 if (c_f.protocolfresh == true) 12 textboxsettinglog.appendtext(c_f.framemsg); 13 }
保存解码数据
/// <summary> /// 2019-05-06 /// </summary> private void savedecodedat() { string strpath = environment.currentdirectory; list<class_frame._savedecodestruct> re = new list<class_frame._savedecodestruct>(); re = c_f.savedecodedat(listsprxddat); for (int i = 0; i < re.count; i++) { byte id = re[i].function; string str = re[i].str; string strfile = strpath + "\\doc\\" + datetime.now.tostring("yy-mm-dd-hh.mm.ss") + "dec" + convert.tostring(id, 16) + ".txt"; if (re[0].str != null) savestring(str, strfile, filemode.create); else messagebox.show("null"); } }
实时解码数据
1 /// <summary> 2 /// 2019-05-07 3 /// </summary> 4 private void decode_header_function_sum8() 5 { 6 class_frame._decodedattimelystruct re = new class_frame._decodedattimelystruct(); 7 int cnt = listsprxddat.count(); 8 9 while (s.dec_lastcnt < cnt) 10 { 11 re = c_f.decodetimely(listsprxddat[s.dec_lastcnt++]); 12 list<object> l = re.listre; 13 byte id = re.function; 14 if (l != null) 15 { 16 byte ui8; 17 uint16 ui16; 18 uint32 ui32; 19 int16 i16; 20 int32 i32; 21 float f; 22 double d; 23 24 switch (id) 25 { 26 case 0xb1: 27 { 28 ui8 = (byte)l[0]; 29 ui16 = (uint16)l[1]; 30 ui32 = (uint32)l[2]; 31 i16 = (int16)l[3]; 32 i32 = (int32)l[4]; 33 f = (float)l[5]; 34 d = (double)l[6]; 35 textboxrxd.appendtext("--------0xb1\r\n"); 36 textboxrxd.appendtext(ui8.tostring() + " "); 37 textboxrxd.appendtext(ui16.tostring() + " "); 38 textboxrxd.appendtext(ui32.tostring() + " "); 39 textboxrxd.appendtext(i16.tostring() + " "); 40 textboxrxd.appendtext(i32.tostring() + " "); 41 textboxrxd.appendtext(f.tostring() + " "); 42 textboxrxd.appendtext(d.tostring() + " "); 43 textboxrxd.appendtext("\r\n"); 44 } 45 break; 46 case 0xb2: 47 { 48 ui8 = (byte)l[0]; 49 ui16 = (uint16)l[1]; 50 ui32 = (uint32)l[2]; 51 i16 = (int16)l[3]; 52 i32 = (int32)l[4]; 53 f = (float)l[5]; 54 d = (double)l[6]; 55 textboxrxd.appendtext("--------0xb2\r\n"); 56 textboxrxd.appendtext(ui8.tostring() + " "); 57 textboxrxd.appendtext(ui16.tostring() + " "); 58 textboxrxd.appendtext(ui32.tostring() + " "); 59 textboxrxd.appendtext(i16.tostring() + " "); 60 textboxrxd.appendtext(i32.tostring() + " "); 61 textboxrxd.appendtext(f.tostring() + " "); 62 textboxrxd.appendtext(d.tostring() + " "); 63 textboxrxd.appendtext("\r\n"); 64 } 65 break; 66 case 0xb3: 67 { 68 ui8 = (byte)l[0]; 69 ui16 = (uint16)l[1]; 70 ui32 = (uint32)l[2]; 71 i16 = (int16)l[3]; 72 i32 = (int32)l[4]; 73 f = (float)l[5]; 74 d = (double)l[6]; 75 textboxrxd.appendtext("--------0xb3\r\n"); 76 textboxrxd.appendtext(ui8.tostring() + " "); 77 textboxrxd.appendtext(ui16.tostring() + " "); 78 textboxrxd.appendtext(ui32.tostring() + " "); 79 textboxrxd.appendtext(i16.tostring() + " "); 80 textboxrxd.appendtext(i32.tostring() + " "); 81 textboxrxd.appendtext(f.tostring() + " "); 82 textboxrxd.appendtext(d.tostring() + " "); 83 textboxrxd.appendtext("\r\n"); 84 } 85 break; 86 default: 87 textboxrxd.appendtext("frame id err\r\n"); 88 break; 89 } 90 } 91 } 92 }
在uarttool中使用类库
读取协议文件,协议文件的信息会在textbox框中显示出来。
如下图模拟下位机软件开始向上位机发送数据
uarttool打开串口,点击保存数据和解码数据会把原始数据和解码后的数据保存下来
解码后的数据如图,和发送的一致。
上一篇: 初识Pyhon之准备环境
下一篇: PyQt 5 的学习引言