欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

GPS导航电文编码与校验

程序员文章站 2024-03-08 22:23:04
...

 导航电文包含卫星的时间和位置信息,是进行导航定位不可缺少的起算数据。导航电文,又称为数据码或 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文件中给出了解码和校验的流程图如下

GPS导航电文编码与校验

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);






}