RM遥控&键鼠控制总结

硬件&通信介绍

RM比赛中各个参赛队伍使用的都是大疆官方提供的遥控器套装,包括遥控器和接收机,接收机上共三个引脚:VCC,GND,DBUS(数据通道),首次使用需要进行遥控器和接收机配对,在两者都上电的情况下短按接收机上的对频按键即可(位于指示灯旁边)。在官方更新了遥控器的固件版本之后,遥控器上手轮也已经开放。

遥控器通讯采用的是2.4GHz频段的DBUS通讯协议,接收机工作电压为4-8.4V,输出信号满足TTL电平,但是为负逻辑,因此接收机和单片机之间需要加反相器来获得正确的数据(官方开发板的USART1接口已经集成)。

接收机的数据发送周期为14ms,每次发送18字节数据,和单片机通过串口通信,通信参数如下:

1.jpg

2.jpg

什么是DBUS?

DBUS是一个轻量级的IPC,用于进程间或进程与内核间的通信,DBUS通信结构下图:

Bus daemon(总线守护进程):DBUS是点对点进行通信,所以基本上DBUS进程连接的都是Bus daemon,Bus daemon负责将受到的DBUS信息进行路由、转发。DBUS进程将信息发送给Bus daemon,Bus daemon会结合消息的目标地址、对象路径、消息的类型、以及DBUS进程希望受到的信息进行综合,然后转发。

解码

遥控器的数据每一帧为18个字节,采用串口接收,每个字节都用CPU处理效率较低,因此考虑使用DMA,串口中断使能IDLE(线路空闲),当一帧数据接收完毕之后触发串口中断,调用DMA进行接收。官方手册提供了基于标准库的串口&DMA配置以及解码函数,在这里只贴出中断服务函数(HAL库)以及解码函数,串口和DMA略去。

代码实现(如果要使用请提前定义相关变量):

void RemotreCtl_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);
}

在上面的代码里,DMA被用于UART通信,以实现高效的数据接收。

键鼠控制的小tips

键鼠控制和遥控器有所不同,按键存在延时,按下一个键该键值会被置高一段时间,并且在中断中不能通过延时来解决该问题。

按下按键之前:

3.jpg

短暂按下按键之后:

4.jpg

基本上短按都会持续 7~14次接收周期, 所以如果想要用按键做模式切换的话,至少需要延时20个接收周期,也就是在第一次接收到这个键之后20次接收中断中不再对这个键进行解码,因为模式切换通常来说不会在短时间内进行,所以我建议1S之内都不对这个按键进行解码,从而实现可靠模式切换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值