RoboMaster

标题: 【分享帖】北京理工大学DreamChaser战队-遥控&键鼠控制总结 [打印本页]

作者: BITDreamChaser    时间: 2019-1-30 21:17
标题: 【分享帖】北京理工大学DreamChaser战队-遥控&键鼠控制总结
大家好,由于想要获取补报步兵射击对抗和工程攀岛取弹的报名资格,故分享一下遥控&键鼠控制的心得,欢迎大家评论交流~~
遥控通信总结
一、概述
在逛论坛的时候发现还没有同学对遥控部分内容做过比较详细的整理,因此在这里做一个遥控器&键鼠的通讯和控制上的总结,主要包括硬件、通讯格式、解码和一些小tips,便于以后的同学学习,本人也是第一年参加比赛,欢迎各路大神在下方留言补充纠正~
二、硬件&通信介绍
RM比赛中各个参赛队伍使用的都是大疆官方提供的遥控器套装,包括遥控器和接收机,接收机上共三个引脚:VCC,GND,DBUS(数据通道),首次使用需要进行遥控器和接收机配对,在两者都上电的情况下短按接收机上的对频按键即可(位于指示灯旁边)。在官方更新了遥控器的固件版本之后,遥控器上手轮也已经开放。
遥控器通讯采用的是2.4GHz频段的DBUS通讯协议(这里不对DBUS进行过多阐释了,有兴趣的同学可以自行学习),接收机工作电压为4-8.4V,输出信号满足TTL电平,但是为负逻辑,因此接收机和单片机之间需要加反相器来获得正确的数据(官方开发板的USART1接口已经集成)。
接收机的数据发送周期为14ms,每次发送18字节数据,和单片机通过串口通信,通信参数如下:

[attach]21532[/attach]

[attach]21533[/attach]

三、解码
遥控器的数据每一帧为18个字节,采用串口接收,每个字节都用CPU处理效率较低,因此考虑使用DMA,串口中断使能IDLE(线路空闲),当一帧数据接收完毕之后触发串口中断,调用DMA进行接收。官方手册提供了基于标准库的串口&DMA配置以及解码函数,在这里只贴出中断服务函数(HAL库)以及解码函数,串口和DMA略去。
代码实现(如果要使用请提前定义相关变量):
1.中断服务函数
voidRemotreCtl_Data_Receive(void)
{
uint32_t rx_data_len = 0;                                                               
if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET))     //判断一帧数据是否接收完成
{
  __HAL_UART_CLEAR_IDLEFLAG(&huart1);                          //清空IDLE标志位                                       
  (void)USART1->SR;                                               //清空SR寄存器                                  
  (void)USART1->DR;                                              //清空DR寄存器                   
  __HAL_DMA_CLEAR_FLAG(&hdma_usart1_rx,DMA_FLAG_TCIF2_6); //清除DMA传输完成标注                      
  HAL_UART_DMAStop(&huart1);                                  //停止DMA接收                                                    
  rx_data_len=BSP_USART1_DMA_RX_BUF_LEN-__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);//数据量
  HAL_UART_Receive_DMA(&huart1,USART1_DMA_RX_BUF, BSP_USART1_DMA_RX_BUF_LEN); //读数据
  if(rx_data_len== 18)                                             //如果数据量正确,则进行解码                                                       
  {
            RC_DataHandle(USART1_DMA_RX_BUF);                                            
  }
}
}
2.解码函数
voidRC_DataHandle(uint8_t *pData)
{
         if(pData == NULL)
    {
        return;
    }
         /*pData[0]为ch0的低8位,Data[1]的第三位为ch0的高三位*/
    RemoteCtrlData.remote.ch0 =((uint16_t)pData[0] | (uint16_t)pData[1] << 8) & 0x07FF;
         /*pData[1]的高5位为ch1的低五位,pData[2]的低6位为ch1的高6位*/
         RemoteCtrlData.remote.ch1 = ((uint16_t)pData[1] >> 3 |(uint16_t)pData[2] << 5) & 0x07FF;
         /*pData[2]的高2位为ch3的低二位,pData[3]为ch3的3~10位,pData[4]的最低位为ch3的最高位*/
         RemoteCtrlData.remote.ch2 = ((uint16_t)pData[2] >> 6 |(uint16_t)pData[3] << 2 | (uint16_t)pData[4] << 10) & 0x07FF;
         /*pData[4]的高7位为ch4的低7位,pData[5]的低4位为ch4的高4位*/
         RemoteCtrlData.remote.ch3 = ((uint16_t)pData[4] >> 1 |(uint16_t)pData[5] << 7) & 0x07FF
         /*pData[5]的高8位为S1*/
         RemoteCtrlData.remote.s1 = ((pData[5] >> 6) &0x03);
         /*pData[5]的6、7位为s2*/
         RemoteCtrlData.remote.s2 = ((pData[5] >> 4) &0x03);
         /*pData[6]和pData[7]鼠标x方向*/
         RemoteCtrlData.mouse.x = ((int16_t)pData[6] |(int16_t)pData[7] << 8);
         /*pData[8]和pData[9]为鼠标Y方向*/
         RemoteCtrlData.mouse.y = ((int16_t)pData[8] | (int16_t)pData[9] << 8);
         /*pData[10]和pData[11]为鼠标Z方向*/
         RemoteCtrlData.mouse.z   = ((int16_t)pData[10] | (int16_t)pData[11] << 8);
         /*pData[12]为鼠标左键*/
         RemoteCtrlData.mouse.press_l = pData[12];
         /*pData[13] 为鼠标右键*/
         RemoteCtrlData.mouse.press_r = pData[13];
         /*pData[14]和pData[15]为键盘*/
         RemoteCtrlData.key.v = ((int16_t)pData[14]) |((int16_t)pData[15] << 8);
}
四、键鼠控制的小tips
键鼠控制和遥控器有所不同,接收机发送频率较高,按键存在延时,按下一个键该键值会被置高一段时间,并且在中断中不能通过延时来解决该问题。
                                          [attach]21534[/attach]            
按下按键之前
                                                                                                [attach]21535[/attach]
短暂按下按键之后
基本上短按都会持续 7~14次接收周期, 所以如果想要用按键做模式切换的话,至少需要延时20个接收周期,也就是在第一次接收到这个键之后20次接收中断中不再对这个键进行解码,因为模式切换通常来说不会在短时间内进行,所以我建议1S之内都不对这个按键进行解码,从而实现可靠模式切换。

2019年1月30日
                                                                            北京理工大学
RM战队电控组整理


作者: 快拆小分队    时间: 2019-2-15 11:32
没人支持吗?
作者: RMBO    时间: 2019-2-23 16:18
我想请问下,上面两个函数是自己写的还是说RM例程里有的?RM例程没有找到。。
作者: 火星探索    时间: 2019-3-13 09:54
写的不错
作者: plasma    时间: 2019-3-16 21:13
不知道为何我们获取到的鼠标速度要么是0要么是65536
作者: whl970831    时间: 2019-3-20 21:04
为啥人这么少,这是篇很好的文章啊
作者: schur    时间: 2019-3-22 01:13
学习了,学习了。。。。
作者: Dior    时间: 2019-3-24 11:31
支持!真正的好文章
作者: 時光    时间: 2019-3-24 16:24
这个延时问题为何不用“按键按下一次有效”来解决呢?
作者: 机智市民老徐    时间: 2019-4-2 22:24
厉害厉害

作者: leeka12138    时间: 2019-4-4 22:01
有点意思
作者: 加号Plus    时间: 2019-4-15 19:52
前来学习一下
作者: Dior    时间: 2019-4-17 00:07
支持支持支持
作者: 1105195664    时间: 2019-4-23 00:11
好东西啊   学习了 支持支持!!!
作者: lixun233    时间: 2019-5-1 14:24
说得好!
作者: lcpdeb    时间: 2019-5-13 04:46
能不能把ZXC等改成键盘上别的按键?
作者: 默呢mone    时间: 2019-9-8 01:58
同问,能不能改键位
作者: 默呢mone    时间: 2019-9-8 02:07
请问用串口空闲中断+DMA接受数据比用DMA中断接受数据好在哪里啊。。。

作者: YZW    时间: 2019-9-14 10:04
dalao厉害,谢谢分享
作者: C-Gerald    时间: 2019-10-4 11:49
鼠标z轴是哪个方向?
作者: C-Gerald    时间: 2019-10-8 21:43
哪位大佬给我解释一下鼠标Z轴是什么意思?
作者: IKEMURA_Kei    时间: 2019-10-21 18:26
支持支持,感谢分享
作者: IKEMURA_Kei    时间: 2019-10-21 18:27
赞,学到了学到了
作者: Chadwick    时间: 2019-12-28 17:16
祖传代码
作者: 星灼丶    时间: 2021-1-21 21:00
感谢分享
作者: 考研究生    时间: 2021-3-28 21:19
支持支持




欢迎光临 RoboMaster (https://bbs.robomaster.com/) Powered by Discuz! X3.2