近日编写了一个手机的灯控系统:


因为添加了许多以前不具备的功能,并且为了数据传输更加稳定,格式更加规范,并且为了以后再进行同类项目的格式统一,本次特地根据计算机网络,在已有的协议HipulseU基础上进一步改造,自制了一套应用层的协议。

首先本套协议的格式定义如下:



协议格式:


SOI7EH起始位标志1字节ASCII: 7EH


VER10H1字节ASCII: 31H,30H


ADR01H1字节ASCII:30H,31H


CID1命令 41H 运行控制命令


42H配置文件读写命令


43H时钟控制命令


44H写EEPROM命令


45H写文件名


CID2辅助命令1字节


----------------------------------------------------------------------------------------------------------------------


CID1=41H时运行命令


CID2:


10H:参数配置信息n条每条14字节HEX(28字节ASCII码)


13H:参数运行EEPROM中的配置信息开机缺省。


14H:参数运行CID1=45H中指定的文件。


20H:停止命令


----------------------------------------------------------------------------------------------------------------------


CID1=42H时写配置文件


CID2:


00H:~FEH写配置文件


FFH:写配置文件,续写配置文件结束


CID1=43H:时钟


CID2:


00H:写时钟命令格式:年-月-日-星期-时-分-秒 (分别为两个字节ASCII码)


01H:读时钟命令格式:年-月-日-星期-时-分-秒


02H:设置开机关机时间



格式开始:(年-月-日-参数-时-分-秒)


结束:(年-月-日-参数-时-分-秒)






参数:两字节ASCII码


D7D6D5 D4 D3D2 D1 D0


011 1 11 1 1


星期日六五四三二一


10000 0 00


年月日十分秒


111


----------------------------------------------------------------------------------------------------------------------


CID1=44H时向EEPROM写配置信息


CID2:


00H:向EEPROM写配置信息


----------------------------------------------------------------------------------------------------------------------


CID1=45H:文件名


CID2:


00H:文件名(写入或运行的文件名,1字节)


----------------------------------------------------------------------------------------------------------------------


CID1=46H:预览设置


CID2:


00H: 1倍


01H: 10倍


02H:100倍


03H:1000倍


----------------------------------------------------------------------------------------------------------------------




LENGTH 2字节长度先传高字节再传低字节


其中:校验码:LCHKSUM=D15~D12


长度标示码:LENID=D11~D0表示INFO中传送的ASCII码字节数


校验码计算:D11~D8+D7~D4+D3~D0,求和后模16余数取反加1


INFO数据格式


COMMAND INFO






CHKSUM数据格式


CHKSUM的计算是除SOI,EOI和CHKSUM外,其它字符按ASCII码值累加求和,所得结果模65536余数取反加1



EOI 0DH结束码




响应信息


SOI7EH起始位标志1字节ASCII: 7EH


VER10H1字节ASCII: 31H,30H


ADR01H1字节ASCII:30H,31H


CID160H


CID2RTN


LENGTH2字节长度先传高字节再传低字节


其中:校验码:LCHKSUM=D15~D12


长度标示码:LENID=D11~D0表示INFO中传送的ASCII码字节数


校验码计算:D11~D8+D7~D4+D3~D0,求和后模16余数取反加1


INFO数据格式


DATA INFO



CHKSUM数据格式


CHKSUM的计算是除SOI,EOI和CHKSUM外,其它字符按ASCII码值累加求和,所得结果模65536余数取反加1



EOI 0DH结束码



RTN:


00:正常


01:VER错


02:CHKSUM错


03:LCHKSUM错


04:CID2无效


05:命令格式错


06:无效命令


E0:地址错


E1~EFH:其它错误


12H:参数文件名文件中存配置文件名每个配置文件名1字节(ASCII两字节)


11H:参数文件名每个1字节(两字节ASCII码)



协议中的所有内容都是把一字节的内容,用两字节的ascii码来替换,例如原本的内容是一字节0x2f,最终会被替换为

0x32 0x46(2的ascii码是0x32,f的ascii码是0x46)

由于本次使用的是Android编程所以最终协议被封装成java包,

首先定义数据格式类把要传输的数据定义为Data类:

publicclassData{privatebyte[]sol;privatebyte[]eol;privatebyte[]ver;privatebyte[]adr;privatebyte[]cid1;privatebyte[]cid2;privatebyte[]lenid;privatebyte[]info;privatebyte[]chksum;//以下定义Data类的各个数据成员变量的getter和setter方法}





再定义一个DataOperator类用对,Data类进行各种操作。

由于要进行十六进制代码与ascii码之间的转换所以,要创建一个静态数组来进行两者的对应:

publicclassAscii{publicstaticbyte[]ASCII=newbyte[]{0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};}



下面主要介绍LCHKSUM的计算方法和CHKSUN的计算方法:

下面是LCHKSUM的计算方法,该方法通过对相应的LENGTH内容进行构造LCHKSUM

publicbyte[]createLength_chksum(byte[]src){byte[]result=newbyte[1];//用来记录计算len_chksum时的中间转换变量intlen_check=0;//计算len_chksum先计算长度每个字节所代表的ascii码的字符的真值和for(inti=0;i<3;i++){if(src[i]>0x39){len_check=len_check+(src[i]&0xff)-0x37;}else{len_check=len_check+(src[i]&0xff)-0x30;}}//System.out.println(len_check);//把相应的和模16len_check%=16;//再把结果取反len_check=16-len_check;//得到结果的ascii码的真值if(len_check==16){result[0]=0;}else{result[0]=Ascii.ASCII[len_check];}//System.out.println(result[0]);returnresult;}



下面是CHKSUM的计算方法,参数为整个数据(除了开始和结束位):

publicbyte[]createChksum(byte[]src){//用来记录计算chksum时的中间转换变量intcheck=0;//用来存放chksum结果byte[]result=newbyte[4];//计算每一字节的和for(inti=1;i<src.length;i++){//System.out.println(src[i]);inta=src[i]&0xff;check=check+a;}System.out.println(check);//把和对65535求余数check=check%65536;//再把求余之后的结果取反check=65536-check;//把最后的结果分为四字节的ascii码result[0]=Ascii.ASCII[((check>>12)&0x0000000f)];result[1]=Ascii.ASCII[((check>>8)&0x0000000f)];result[2]=Ascii.ASCII[((check>>4)&0x0000000f)];result[3]=Ascii.ASCII[((check&0x0000000f))];System.out.println(result[0]+""+result[1]+""+result[2]+""+result[3]);returnresult;}