上一章介绍了简短的几行C#代码,从串口读取北斗数据的方法。
这一章需要介绍一下北斗数据接口的基本协议,也就是类似下面的命令的含义。
$CCICA,0,0*4B\r\n
网上有很多比较早的代码是基于北斗4.0的协议,那个协议是一种二进制协议,编程人员需要认真准备数据中的每一个bit,如果出错,调试会极为困难。
所以后来出现了2.1协议,这个协议是文本协议,北斗终端中的芯片负责把它们转换成二进制,实际内部传输的仍是二进制,但编程起来更加容易,所以新的北斗终端都会支持2.1协议。
关于这个2.1协议,北斗官网上曾经公开过一份文档《北斗卫星导航系统用户终端通用数据接口(预)》,发布日期为2014年8月,后来这个资料被撤下了,但还能从其它地方找到,只是文档中有许多错误。
北斗指令以$开始(据说也可以是叹号!,但我现在还没遇到),然后是5个字符的指令代码,后面有多个参数,用逗号分隔,*表示指令结束,hh是校验码,最后是回车换行符,十六进制为0x0D和0x0A。
$CCICA,0,0*4B\r\n
指令代码为5个字符,前2个字符为发送器(信源)的标识符,后3个字符为语句标识符。
前2个字符的定义见下表:
标识符 | 发送器(信源)数据类型 |
---|---|
BD | 北斗导航定位系统(BDS) |
GP | 全球定位系统(GPS-global positioning system) |
GN | 全球导航卫星系统(GNSS-global navigation satellite system) |
GL | GLONASS系统 |
GA | 伽利略系统 |
CC | 计算机系统 |
后面3个字符的定义可参考《北斗卫星导航用户终端通用数据接口2.1协议》,不同的北斗厂商又增加了不同的自定义语句。
例如:CCICA、BDICI、BDGGA、GPGGA、GNGGA、GPGSA、CCRMO、CCTXA、BDFKI都是常用的指令。
hh校验码是$ 和*之间(不含$和*)所有字符的异或,然后用两个16进制大写字符表示,C#代码如下。
byte sum = 0;
foreach (char c in bdstr)
{
if (c == '$' || c == '!') continue;
if (c == '*') break;
sum ^= (byte)c;
}
return sum.ToString("X2");
下面以$CCICA指令为例,说明校验码的生成过程。
$BDICI,0925867,2204536,1934946,6,60,3,N,0*0F
现在我们可以实现一个小功能,给串口写入一段北斗命令,立刻从串口读取一行信息,可以开展北斗命令的测试工作。
///
/// 这个函数不是非常严谨,由于串口通讯是异步的,
/// 你给串口写入一行命令,然后立即读串口,存在一定的概率,紧接的反馈文本行并不是你期望的结果,
/// 比如,你发送了$CCICA,可能并不能立即收到$BDICI反馈。
///
/// 串口
/// 北斗命令,程序自动补上校验码
/// 串口的一行反馈信息
static string SendCmd(SerialPort port, string cmd)
{
cmd = cmd.Trim();
cmd = cmd + "*" + CheckSum(cmd) + "\r\n";
Console.Write("写串口:" + cmd);
port.Write(cmd);
return port.ReadLine();
}
///
/// 计算校验码, $和*(或行尾)之间(不含$和*)的所有字符的异或。
///
/// 北斗指令
/// 两个16进制数字,大写
static string CheckSum(string bdstr)
{
byte sum = 0;
foreach (char c in bdstr)
{
if (c == '$' || c == '!') continue;
if (c == '*') break;
sum ^= (byte)c;
}
return sum.ToString("X2");
}
现在主程序比较简单了,我们可以试验两条北斗命令的输出结果。SBX的反馈信息包括设备的厂商、类型、协议版本、序列号和卡号等信息。有关SBX的说明可以参看北斗2.1协议。
string result = SendCmd(port, "$CCICA,0,0");
Console.WriteLine(result);
result = SendCmd(port, "$CCRMO,SBX,2,0");
Console.WriteLine(result);
1)4.0协议不好调试,常用2.1文本协议
2)$开头
3)命令有5个字符,前2个是信源,后3个是命令的含义
4)*hh是校验码,异或生成,两个16进制数
5)回车换行\r\n放末尾