gpt4 book ai didi

c - NMEA校验和计算计算

转载 作者:太空狗 更新时间:2023-10-29 15:26:11 25 4
gpt4 key购买 nike

我正在尝试为已由 GPS 计算出的 NMEA 语句找到校验和。

char GPRMCBuf[POS_BUFFER] = {0xA0, 0xA2, 0x00, 0x48, 0xDD, 
0x24, 0x47, 0x50, 0x52, 0x4D, 0x43, 0x2C, 0x31, 0x35,
0x30, 0x35, 0x32, 0x30, 0x2E, 0x30, 0x30, 0x30, 0x2C,
0x41, 0x2C, 0x34, 0x31, 0x32, 0x31, 0x2E, 0x37, 0x39,
0x37, 0x37, 0x2C, 0x4E, 0x2C, 0x30, 0x30, 0x32, 0x31,
0x30, 0x2E, 0x39, 0x36, 0x36, 0x37, 0x2C, 0x45, 0x2C,
0x31, 0x2E, 0x35, 0x30, 0x2C, 0x35, 0x38, 0x2E, 0x32,
0x39, 0x2C, 0x32, 0x33, 0x30, 0x37, 0x31, 0x35, 0x2C,
0x2C, 0x2C, 0x41, 0x2A, 0x35, 0x38, 0x0D, 0x0A, 0x0F,
0x05, 0xB0, 0xB3};

听说最后第 3 个和第 4 个字符是校验和,即 0F05但我们想纠正算法。我们使用的算法如下

Index = first,
checkSum = 0,
while index < msgLen,
checkSum = checkSum + message[index],
checkSum = checkSum AND (2^15-1).
increment index.

我们编写的代码如下:

#include<stdio.h>
main()
{
unsigned char i;
unsigned short chk;

char test[]={ 0x47, 0x50, 0x52, 0x4D, 0x43, 0x2C, 0x31,
0x35, 0x30, 0x35, 0x32, 0x30, 0x2E, 0x30, 0x30,
0x30, 0x2C, 0x41, 0x2C, 0x34, 0x31, 0x32, 0x31,
0x2E, 0x37, 0x39, 0x37, 0x37, 0x2C, 0x4E, 0x2C,
0x30, 0x30, 0x32, 0x31, 0x30, 0x2E, 0x39, 0x36,
0x36, 0x37, 0x2C, 0x45, 0x2C, 0x31, 0x2E, 0x35,
0x30, 0x2C, 0x35, 0x38, 0x2E, 0x32, 0x39, 0x2C,
0x32, 0x33, 0x30, 0x37, 0x31, 0x35, 0x2C, 0x2C,
0x2C, 0x41,0x2A, 0x35, 0x38, 0x0D, 0x0A};

chk = 0;

for(i = 0; i < 70; i++)
{
chk = chk + test[i];
chk = chk & 32767;
}
printf("A=%hu\n", chk);
return 0;
}

问题是我们得到的是 3588,但它应该是 3845(0F05)。

请帮助我们解决这个算法。

最佳答案

您已经做出了很好的尝试,但是您有一些错误。我认为以下链接是 NMEA 的一个很好的起点:http://www.gpsinformation.org/dale/nmea.htm

您会在介绍中看到每个命令都是独立的,以 $ 开头符号并以回车/换行组合结束。校验和(如果存在)位于消息的末尾并以星号开头 * .您还会看到校验和是 $ 之间所有字节的 XOR。和 * , 校验和,十六进制,在 * 之后ASCII 格式。

您的输入数据在开头和结尾也有一些噪音,您需要将其丢弃。让我注释您的输入:

char GPRMCBuf[POS_BUFFER] = {
0xA0, 0xA2, 0x00, 0x48, 0xDD, // these bytes are not part of the message

0x24, // this is the '$' character, so this is the message start byte

// checksum calculation starts with the next byte (0x47)
0x47, 0x50, 0x52, 0x4D, 0x43, 0x2C, 0x31, 0x35, // GPRMC,15
0x30, 0x35, 0x32, 0x30, 0x2E, 0x30, 0x30, 0x30, 0x2C, // 0520.000,
0x41, 0x2C, 0x34, 0x31, 0x32, 0x31, 0x2E, 0x37, 0x39, // A,4121.79
0x37, 0x37, 0x2C, 0x4E, 0x2C, 0x30, 0x30, 0x32, 0x31, // 77,N,0021
0x30, 0x2E, 0x39, 0x36, 0x36, 0x37, 0x2C, 0x45, 0x2C, // 0.9667,E,
0x31, 0x2E, 0x35, 0x30, 0x2C, 0x35, 0x38, 0x2E, 0x32, // 1.50,58.2
0x39, 0x2C, 0x32, 0x33, 0x30, 0x37, 0x31, 0x35, 0x2C, // 9,230715,
0x2C, 0x2C, 0x41, // ,,A
// checksum calculation ends here

0x2A, // The '*' character, i.e. message/checksum delimiter
0x35, 0x38, // The checksum, '5' and '8', so the checksum is 0x58
0x0D, 0x0A, // The CR/LF line terminator

0x0F, 0x05, 0xB0, 0xB3 // these bytes are not part of the message
};

所以,校验和的计算是:

chk = 0;
chk = chk ^ 0x47; // chk = 0x47
chk = chk ^ 0x50; // chk = 0x17
chk = chk ^ 0x52; // chk = 0x45
...
chk = chk ^ 0x41; // chk = 0x58

请注意,您最终会得到 0x58 , 在消息中为 0x35 0x38 .因此,一旦您正确地构造了消息并调整了 for 循环以遍历校验和字节,循环体就变成了:

chk ^= test[i];

在循环之后,您需要转换 chk 的两个半字节转换为 ASCII 并与信号校验和进行比较,或将信号校验和转换为二进制值并与 chk 进行比较.

关于c - NMEA校验和计算计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32076761/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com