php接收终端数据需要涉及到解析转码函数
<? //数据为integer类型 $bytes=array( 0x55,0xAA,0x01,0x82,0x00,0x00,0x00,0x00, 0x44,0x00,0x4D,0xED,0x43,0x4F,0x2D,0x48, 0x45,0x41,0x4C,0x54,0x48,0x38,0x36,0x36, 0x37,0x36,0x32,0x30,0x32,0x31,0x32,0x33, 0x35,0x34,0x33,0x35,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x8E,0x01,0x00,0x00, 0xD1,0x07,0x01,0x01,0x14,0x10,0x21,0x00, 0x66,0x66,0xD6,0x40,0x02,0x00,0x00,0x00, 0x00,0x00,0x00,0x00 ); function check_data($bytes){ if(count($bytes)<12) return false;//头部长度判断 $new_H_CHK=~($bytes[0]+$bytes[1]+$bytes[2]+$bytes[3]+$bytes[4]+$bytes[5]+$bytes[6]+$bytes[7]+$bytes[8]+$bytes[9]+$bytes[11]); $new_H_CHK=bindec(substr(sprintf("%b",$new_H_CHK),-8))+1; $old_H_CHK=$bytes[10]; if($new_H_CHK!==$old_H_CHK) return false;//新生成的new_H_CHK跟数据中的H_CHK对比,如果数据是一样则会相等 $validate_header=$bytes[0]+$bytes[1]+$bytes[2]+$bytes[3]+$bytes[4]+$bytes[5]+$bytes[6]+$bytes[7]+$bytes[8]+$bytes[9]+$bytes[10]+$bytes[11]; $validate_header=bindec(substr(sprintf("%b",$validate_header),-8)); if($validate_header!==0) return false;//根据公式再次完整校验头部 $datalen=bindec(substr(sprintf("%b",$bytes[9]),-8).substr(sprintf("%b",$bytes[8]),-8));//获取包长度 $bytelen=count($bytes); if($datalen!=$bytelen) return false;//包长度校验 $sum_data=NULL; for($i=12;$i<$bytelen;$i++){ $sum_data+=$bytes[$i];//计算数据和值 } $new_D_CHK=bindec(substr(sprintf("%b",~$sum_data),-8))+1; $old_D_CHK=$bytes[11]; if($new_D_CHK!==$old_D_CHK) return false;//校验新生成的new_D_CHK和old_D_CHK,如果数据是一样则会相等 $validate_data=bindec(substr(sprintf("%b",$old_D_CHK+$sum_data),-8)); if($validate_data!==0) return false;//根据公式再次校验数据完整性 $a=0x66;$b=0x66;$c=0xD6;$d=0x40; echo get_float32($d,$c,$b,$a); return true; } //32位的二进制浮点数转回十进制的php浮点数 function get_float32($a,$b,$c,$d){ $float32=sprintf("%08b%08b%08b%08b",$a,$b,$c,$d); $S=substr($float32,0,1);//符号位 $E=substr($float32,1,8);//指数位 $E=bindec($E)-127;//减去中间数,获取真实的指数位,有可能是0减去127 $M=substr($float32,9);//有效数字,被减去1 $floatbin=""; if($E>0){ if($E!=128){//防止指数位全1 $floatbin="1".substr($M,0,$E)."_".substr($M,$E); } }else if($E<0){ if(abs($E)==1){ $floatbin=str_pad("",1,"0")."_1".$M; }else if($E!=-127){//防止指数位全0情况,即为0值 $floatbin="0_".str_pad("",abs($E)-1,"0")."1".$M; } }else if($E==0){ $floatbin="1_".$M; } $intpart=$decpart=""; if(!empty($floatbin)){ list($intpart,$decpart)=explode("_",$floatbin); } $val=0; for($i=1;$i<=strlen($intpart);$i++){ $val+=(intval($intpart[$i-1]))*pow(2,strlen($intpart)-$i);//二进制转回整数 } for($i=1;$i<=strlen($decpart);$i++){ $val+=(intval($decpart[$i-1]))*pow(2,0-$i);//二进制转回小数部分 } $val=$S==1?0-$val:$val;//符号数判断 return $val; } var_dump(check_data($bytes)); ?>
calc十进制小数转二进制
Windows自带的计算器可以方便地把十进制的整数转换成二进制的整数,但是十进制的小数则无法直接转换成二进制的小数。
今天,我发现了一个快速的解决办法!
一个十进制小数可以表示成“X.Y”的形式,“X”是整数部分,“Y”是纯小数部分,要分别进行转换,最后合在一起。
整数部分“X”的转换成二进制可以直接利用Windows的计算器,非常简单,不说了。
对纯小数部分“Y”的转换,要提前设定转换精度,比如精确到小数点后16位。别理解错了,对于二进制的小数点后16位在精度上仅相当于十进制小数点后的5位,并非十分高!
将“0.Y”乘以2的16次方,即“0.Y×65536”,结果可能会有小数部分,将小数部分四舍五入到个位,得到一个没有小数部分的纯整数,称作“Z”。
利用Windows计算器将“Z”转换成二进制,若结果不足16位,则在最前面补0,补够16位。这就是小数部分“Y”对应的二进制了。
现在将“X”和“Y”对应的二进制数码合在一起(中间当然要有小数点),就是最终结果了!
举个实例:把十进制纯小数“0.123”转换成二进制小数。
0.123×65536=8060.928
四舍五入后得到“8061”,转换成二进制为“1111101111101”,只有13位,前面需要补3个“0”,得到“0001111101111101”。因此结果是
0.123=(0.0001111101111101)2=(0.1F7D)16
浮点数二进制表示
http://blog.csdn.net/richerg85/article/details/20456969