GPS导航电文编码与校验
导航电文包含卫星的时间和位置信息,是进行导航定位不可缺少的起算数据。导航电文,又称为数据码或 D 码,包含有关卫星的星历、卫星工作状态、时间系统、卫星钟运行状态等信息,是卫星信号的重要组成部分,也是用户利用卫星进行定位的数据基础。
1 编码及校验计算
根据 GPS ICD-200 规定,导航电文子帧以字为单位组成,字结构如图所示,每个字由24 位比特数据位和 6 比特的奇偶校验位组成。采用奇偶校验可以检验接受端和发送端数据是否一致,从而提高数据传输质量。下面给出传输导航电文的校验过程。
D1 = d1⊕D*30
D2 = d2⊕D*30
D3 = d3⊕D*30
D4 = d4⊕D*30
......
D24 = d24⊕D*30
D25 =D*29⊕d1⊕d2⊕d3⊕d5⊕d6⊕d10⊕d11⊕d12⊕d14⊕d14⊕d17⊕d18⊕d20⊕d23
D26 = D*30⊕d2⊕d3⊕d4⊕d6⊕d7⊕d11⊕d12⊕d14⊕d14⊕d15⊕d18⊕d19⊕d21⊕d24
D27 = D*29⊕d1⊕d3⊕d4⊕d5⊕d7⊕d8⊕d12⊕d13⊕d14⊕d15⊕d16⊕d19⊕d20⊕d22
D28 = D*30⊕d2⊕d4⊕d5⊕d6⊕d8⊕d9⊕d13⊕d14⊕d15⊕d16⊕d17⊕d20⊕d21⊕d23
D29 = D*30⊕d1⊕d3⊕d5⊕d6⊕d7⊕d9⊕d10⊕d14⊕d15⊕d16⊕d17⊕d18⊕d21⊕d22⊕d24
D30 = D*29⊕d3⊕d5⊕d6⊕d8⊕d9⊕d10⊕d11⊕d13⊕d15⊕d19⊕d22⊕d23⊕d24
式中d1-d24为原始数据位;D25-D30为通过公式计算得到的6比特奇偶校验码位;D1-D30为传输的比特位;D*29,D*30为每一子帧中上一个字的最后两位数据。需要注意的是第 1 子帧第 2字奇偶校验最后两位必须设置为 0,每一个子帧的最后一个字的奇偶校验最后两位也必须为0,为了保证该两位置零,通常利用该字的第 23、24 位配合实现;当 D*29,D*30为子帧第一个字时,D*29,D*30通常置零处理。
2 编码及校验程序
两个函数:
unsigned int computeChecksum(unsigned int source, int nib);// nib= 1 表示要通过配d23 d24使校验值的最后两位为0
unsigned int countBits(unsigned int v);
unsigned int countBits(unsigned int v)
{
unsigned long c;
const int S[] = {1, 2, 4, 8, 16};
const unsigned long B[] = {
0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF};
c = v;
c = ((c >> S[0]) & B[0]) + (c & B[0]);
c = ((c >> S[1]) & B[1]) + (c & B[1]);
c = ((c >> S[2]) & B[2]) + (c & B[2]);
c = ((c >> S[3]) & B[3]) + (c & B[3]);
c = ((c >> S[4]) & B[4]) + (c & B[4]);
return(c);
}
unsigned int computeChecksum(unsigned int source, int nib)
{
/*
Bits 31 to 30 = 2 LSBs of the previous transmitted word, D29* and D30*
Bits 29 to 6 = Source data bits, d1, d2, ..., d24
Bits 5 to 0 = Empty parity bits
*/
/*
Bits 31 to 30 = 2 LSBs of the previous transmitted word, D29* and D30*
Bits 29 to 6 = Data bits transmitted by the SV, D1, D2, ..., D24
Bits 5 to 0 = Computed parity bits, D25, D26, ..., D30
*/
/*
1 2 3
bit 12 3456 7890 1234 5678 9012 3456 7890
--- -------------------------------------
D25 11 1011 0001 1111 0011 0100 1000 0000
D26 01 1101 1000 1111 1001 1010 0100 0000
D27 10 1110 1100 0111 1100 1101 0000 0000
D28 01 0111 0110 0011 1110 0110 1000 0000
D29 10 1011 1011 0001 1111 0011 0100 0000
D30 00 1011 0111 1010 1000 1001 1100 0000
*/
unsigned long bmask[6] = {
0x3B1F3480UL, 0x1D8F9A40UL, 0x2EC7CD00UL,
0x1763E680UL, 0x2BB1F340UL, 0x0B7A89C0UL };
unsigned long D;
unsigned long d = source & 0x3FFFFFC0UL;
unsigned long D29 = (source>>31)&0x1UL;
unsigned long D30 = (source>>30)&0x1UL;
if (nib) // Non-information bearing bits for word 2 and 10
{
/*
Solve bits 23 and 24 to presearve parity check
with zeros in bits 29 and 30.
*/
if ((D30 + countBits(bmask[4] & d)) % 2)
d ^= (0x1UL<<6);
if ((D29 + countBits(bmask[5] & d)) % 2)
d ^= (0x1UL<<7);
}
D = d;
if (D30)
D ^= 0x3FFFFFC0UL;
D |= ((D29 + countBits(bmask[0] & d)) % 2) << 5;
D |= ((D30 + countBits(bmask[1] & d)) % 2) << 4;
D |= ((D29 + countBits(bmask[2] & d)) % 2) << 3;
D |= ((D30 + countBits(bmask[3] & d)) % 2) << 2;
D |= ((D30 + countBits(bmask[4] & d)) % 2) << 1;
D |= ((D29 + countBits(bmask[5] & d)) % 2);
D &= 0x3FFFFFFFUL;
//D |= (source & 0xC0000000UL); // Add D29* and D30* from source data bits
return(D);
}
3 解码
GPS的IDC文件中给出了解码和校验的流程图如下
4 解校验程序
其中:dta的bit23-bit存放导航电文比特的d1-d24,parity是参考校验值
unsigned int GPS_ParityCheck(int data,int parity,int D29,int D30)
{
unsigned int i,j,S[6];
int temp,S_temp,P;
int GPSX_Flag_Data_Parity;
unsigned int GPS_H[6]={0xEC7CD2,0x763E69,0xBB1F34,0x5D8F9A,0xAEC7CD,0x2DEA27};
temp=0;
P=0;
GPSX_Flag_Data_Parity=0;
if (D30==1) data=(~data)&0xFFFFFF;
for(i=0;i<6;i++)
{
S[i]=GPS_H[i]&data;
S_temp=S[i];
temp=0;
for(j=0;j<24;j++)
{
temp+=S_temp&1;
S_temp=S_temp>>1;
}
if (temp%2==0)
temp=0;
else
temp=1;
if ((i==0)||(i==2)||(i==5))
temp=temp^D29;
else
temp=temp^D30;
P=P|(temp<<(5-i));
}
//printf("P = %d\r\n",P);
if(P==parity)
GPSX_Flag_Data_Parity=1;
return GPSX_Flag_Data_Parity;
}
5 应用
#include <stdio.h>
#include <stdlib.h>
#include "GPSfun.h"
//#include "datafile.h"
int main()
{
//D29 = 1
//D30 = 0;
int dat[32] = {0,1,0,1,1,1,0,0,0,1,1,1,1,1,1,0,1,0,0,1,0,0,0,0,1,0,0,1,0,1};//已编码已校验的测试序列
int i;
unsigned int tmp;
tmp = 2; //D29 D30 : 10
//
for(i=0;i<24;i++)
{
tmp = tmp<<1;
tmp = tmp+dat[i];
}
tmp = tmp<<6;//第六位留空 存放校验位
tmp = computeChecksum(tmp,0); //该值的bit29-bit0应与dta一致
printf("tmp = %d\n",tmp);
tmp = 0;
for(i=0;i<24;i++)
{
tmp = tmp<<1;
tmp = tmp+dat[i];
}
tmp = GPS_ParityCheck(tmp,37,1,0);//37为参考校验值为dta的高六位,即六位校验码的值
printf("tmp = %d\n",tmp);
}
上一篇: asp.ent下合并两个结构相同的DataTable
下一篇: 使用jQuery Autocomplete(自动完成)插件 博客分类: JavaScript,jQuery jqueryautocoomplete
推荐阅读