RTCM
1. 一帧数据组成
2.数据接收
/*(1) synchronize frame */
if (rtcm.nbyte == 0)
{
if (data != RTCM3PREAMB)//RTCM3PREAMB:同步码
return 0;
rtcm.buff[rtcm.nbyte++] = data;
return 0;
}
//(2)添加一Byte数据
rtcm.buff[rtcm.nbyte++] = data;
// (3)当Byte数量为3时,读取数据长度(一帧RTCM数据除去CRC的数据的Byte数)
if (rtcm.nbyte == 3)
{
//getbitu(rtcm.buff, 14, 10)得到rtcm.buff第14个字节之后的10个字节信息。
// ,+3表示前三个byte(同步码、保留位、数据长度)
rtcm.len = (int)rtcmcmn.getbitu(rtcm.buff, 14, 10) + 3; /* length without parity */
}
//(4)读取完成nbyte数重置
if (rtcm.nbyte < 3 || rtcm.nbyte < rtcm.len + 3) //+3表示比数据长度多接收3个Byte,其为为校验位
return 0;
rtcm.nbyte = 0;
实时数据传输进来经过(1)(2)(3)(4)四个步骤存储到buff中。
注:byte[] buff。每次接收1Byte(字节)数据对应8bit(位)
- 位(bit):比特,指二进制中的一位,是二进制的最小信息单位。 bit也被称作小b,用b表示。(所以byte是大B),一个二进制数据0或1,是1bit。
- 字节byte:1byte有8位 最大值为255 最小值是0 2^8-1=255
/*
目的获取buff(byte数组)从pos位起始后len位表示的信息。
*/
public static uint getbitu(byte[] buff, int pos, int len)
{
uint bits = 0;
int i;
try
{
for (i = pos; i < pos + len; i++)
{
//[i / 8] 取整,i % 8取余
bits = (bits << 1) + ((uint)(buff[i / 8] >> (7 - i % 8)) & 1u);
}
}
return bits;
}
注:[i / 8]:当前位i所在的buff索引,buff[i / 8] :包含当前位信息的字节(Byte),(buff[i / 8] >> (7 - i % 8):截取字节中i位的信息。(bits << 1) :将上一次循环计算得到的高位信息左移来保留高位信息。
3. CRC校验
再通过(4)判定之后,接受完一帧数据通过CRC校验保证数据的完整性。
//(5)校验位,校验数据是否完整
if (rtcmcmn.crc24q(rtcm.buff, rtcm.len) != rtcmcmn.getbitu(rtcm.buff, rtcm.len * 8, 24))
{
//trace(2, "rtcm3 parity error: len=%d\n", rtcm.len);
return 0;
}
CRC检校原理
模2除法
RTKLIB中CRC-24Q检校代码:
crc = ((crc << 8) & 0xFFFFFF) ^ tbl_CRC24Q[(crc >> 16) ^ buff[i]];
- crc << 8表示将32位的crc左移8位,低位补0。(crc << 8) & 0xFFFFFF表示只取移位后从低位开始的24位,即从左到右24位。crc >> 16表示将crc右移16位。
- (crc >> 16) ^ buff[i] 表示对移位后的数据与buff[i]中的八位进行按位异或运算得到n
- 最后根据计算结果n选取tbl_CRC24Q数组中的第n个数在与(crc << 8) & 0xFFFFFF进行按位异或运算。
注:tbl_CRC24Q数组为八位二进制数组(即0-255的二进制表示),表示原始数据除以相应校验多项式后的余数表。
注:
<<:左移运算,a<<m,将a按二进制位向左移动m位,高位移除后,低位补0。
>>:右移运算,a>>m,将a按二进制位向右移动m位,低位移除后,高位补0。
^ :按位异或运算,二进制逐位非或,从最小(及最右)的位开始,对操作位数逐位操作,相同 为0,不同为1。例如:X:0000 1011 1111 Y:1111 0101 1111 X^Y:1111 1110 0000。
0xFFFFFF:0x表示16进制,FFFFFFFF 一个F代表4位的1111