[嵌入式] 裁判系统用户数据读取

  [复制链接]
管理员robomasters
2018-2-11 11:44:28 显示全部楼层

马上注册,玩转Robomaster!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
用户数据协议说明
裁判系统的学生接口外发的数据一帧分为 4 个部分,分别是帧头数据、命令码 ID、数据、帧尾校验数据。

1、帧头数据

/**
  * @brief  frame header structure definition
  */
typedef __packed struct
{
  uint8_t  sof;
  uint16_t data_length;
  uint8_t  seq;
  uint8_t  crc8;
} frame_header_t;

帧头数据
占用字节
详细描述
sof1数据的域ID,学生接口域:0xA5
data_length2每帧内数据data的长度
seq1包序号
crc81帧头的crc校验结果

2、命令码
一个命令码对应一帧包含具体信息的数据。
命令码
占用字节
cmdid2

3、数据
为命令码 ID 对应的数据结构,数据长度即这个结构体的大小。
数据
占用字节
datadata_length

4、帧尾数据
每帧数据的crc16校验结果存储在这个位置。
帧尾数据
占用字节
crc162

数据发送和接收

1、数据发送
数据发送部分比较简单,数据打包好后,其实就是正常的数据加上了帧头帧尾和校验数据,这个时候我们只需要把打包好的数据的数组直接通过串口发送出去即可。不管是使用串口进行普通的移位发送,还是使用 DMA 发送,都可以很容易的实现。
使用如下函数打包要发送的数据:

/**
  * @brief     pack data to bottom device
  * @param[in] cmd_id:  command id of data
  * @param[in] *p_data: pointer to the data to be sent
  * @param[in] len:     the data length
  */
void data_pack_handle(uint16_t cmd_id, uint8_t *p_data, uint16_t len)
{
  memset(computer_tx_buf, 0, COMPUTER_FRAME_BUFLEN);
  frame_header_t *p_header = (frame_header_t*)computer_tx_buf;
  
  p_header->sof          = UP_REG_ID;
  p_header->data_length  = len;
  
  memcpy(&computer_tx_buf[HEADER_LEN], (uint8_t*)&cmd_id, CMD_LEN);
  append_crc8_check_sum(computer_tx_buf, HEADER_LEN);
  
  memcpy(&computer_tx_buf[HEADER_LEN + CMD_LEN], p_data, len);
  append_crc16_check_sum(computer_tx_buf, HEADER_LEN + CMD_LEN + len + CRC_LEN);
}

2、数据接收
裁判系统的数据发送出来时不同的帧数据长度是不定的,而且可能会有连续帧或者断帧的情况出现,这个时候使用接收遥控器数据的方法来接收就会出现问题。下面给大家提供接收裁判系统数据的具体思路,主要包含串口不定长数据的接收,以及接收到的数据的存储和解析。

2.1 串口不定长数据接收
首先解决不定长数据的问题,因为数据不定长度,所以不能只靠一个固定长度的缓冲和空闲中断来接收数据,缓冲可能有溢出的情况,而且单片机的资源有限,也不可能使用很大的内存空间一次性接收完每次裁判系统发送过来的数据。
使用串口空闲中断,加 DMA 满中断来接收和存储串口数据。下面是两种中断配合使用时的具体情况:

  • 在串口空闲中断时,读取 DMA 缓冲中的所有数据并储存,然后重启 DMA,让 DMA 重新开始接收数据;
  • 在 DMA 缓冲满中断时,读取 DMA 缓冲中的所有数据并储存,然后让 DMA 重新开始接收数据。在这里可以使用 DMA 双缓冲,既提高效率,也不用使用程序来复位 DMA 接收缓冲;

使用空闲中断处理数据的时候需要注意,要记录此时 DMA 缓冲中的数据位数,然后作为缓冲的读写指针,下一次 DMA 满中断或者空闲中断时从这个位置开始读取。

2.2 数据储存
裁判系统的有些数据是固定频率发送的,但有些是随机发送的,比如伤害信息这种类型的数据,装甲受到打击后才会发送,而且只发送一次。为了防止有漏接的数据,可以使用队列来储存串口接收到的原始数据。
这个队列是存储串口接收数据的,可以自己实现队列的数据结构,如果是带操作系统的话,也可以使用其中自带的队列结构 api。需要注意的是进行队列读写操作时,队列为空或者满时尽量直接返回,不要阻塞程序。

2.3 数据解析

按照裁判系统的协议格式,如果要解析出有效数据,我们就需要在存储数据的队列中从帧头开始,分别通过帧头、命令码和数据长度、CRC8,以及最终的 CRC16 这些校验之后,才能认为这帧数据是有效的,也就解析出了有效的裁判系统数据。

3、示例代码

下面是具体功能实现的位置:

跳转到指定楼层

[嵌入式] 裁判系统用户数据读取

  [复制链接]
中士苏一休
2018-3-1 16:15:05 显示全部楼层
现在这个2.0.3.33的固件传输的帧还是会断帧,发一点然后过一会儿才发剩下的,然后这样就会导致进入空闲中断然后CRC就校验不过,所以还是很蛋疼的,坐等新固件

[嵌入式] 裁判系统用户数据读取

  [复制链接]
中士SKDZZC
2018-2-27 17:04:39 显示全部楼层
源程序看的一脸懵逼

[嵌入式] 裁判系统用户数据读取

  [复制链接]
上等兵buli
2018-3-29 17:05:01 显示全部楼层
哲理俊 发表于 2018-3-20 14:00
1、为什么空闲中断还会出现缓冲溢出的情况呢?我预先给一个大一点的缓冲比如100,理论上是可以接收到每一帧 ...

1、裁判系统发出的数据有的不是定频的,有可能有好几帧数据粘在一起的情况,缓冲设置的再长都会超,不能依靠一个很长的缓冲一次接完完整的数据;
2、dma满中断确实没什么必要,最新的代码里面好像已经去掉了,不过空闲中断重置DMA是什么?,你看的是遥控器接收数据的处理吧

[嵌入式] 裁判系统用户数据读取

  [复制链接]
上士Extreme
2018-2-11 14:11:26 显示全部楼层
罗老师牛匹

[嵌入式] 裁判系统用户数据读取

  [复制链接]
上士下午茶
2018-2-11 16:35:10 显示全部楼层
点赞~~~~
回复

使用道具 举报

[嵌入式] 裁判系统用户数据读取

  [复制链接]
下士llh6833
2018-2-28 17:06:17 显示全部楼层
赞一个
回复

使用道具 举报

[嵌入式] 裁判系统用户数据读取

  [复制链接]
上等兵aaa1234zzz
2018-3-1 15:47:23 显示全部楼层
赞赞赞赞
回复

使用道具 举报

[嵌入式] 裁判系统用户数据读取

  [复制链接]
下士Yez
2018-3-1 23:44:44 显示全部楼层
苏一休 发表于 2018-3-1 16:15
现在这个2.0.3.33的固件传输的帧还是会断帧,发一点然后过一会儿才发剩下的,然后这样就会导致进入空闲中断 ...

一休哥牛逼

[嵌入式] 裁判系统用户数据读取

  [复制链接]
下士qq545031318
2018-3-2 21:35:01 显示全部楼层
限制了工程机器人与英雄机器人同时抓取弹药箱的数量

[嵌入式] 裁判系统用户数据读取

  [复制链接]
下士15766115769
2018-3-2 22:19:43 显示全部楼层
限制了工程机器人与英雄机器人同时抓取弹药箱的数量

本版积分规则

触屏版 | 电脑版

Copyright © 2019 RoboMasters 版权所有

快速回复 返回顶部 返回列表