RoboMaster遥控器数据解析

位运算及遥控器数据解析

RoboMaster遥控器官方例程里面有一个数据解析函数,下面就来为同学们解析数据解析(套娃)。
程序源码如下:

//遥控器数据解析
void RemoteDataProcess(uint8_t *pData)
{
    
    
	RC_CtrlData.rc.ch0 = ((int16_t)pData[0] | ((int16_t)pData[1] << 8)) & 0x07FF; 
	RC_CtrlData.rc.ch1 = (((int16_t)pData[1] >> 3) | ((int16_t)pData[2] << 5)) & 0x07FF;
	RC_CtrlData.rc.ch2 = (((int16_t)pData[2] >> 6) | ((int16_t)pData[3] << 2) |((int16_t)pData[4] << 10)) & 0x07FF;
	RC_CtrlData.rc.ch3 = (((int16_t)pData[4] >> 1) | ((int16_t)pData[5]<<7)) & 0x07FF;
 
	RC_CtrlData.rc.s1 = ((pData[5] >> 4) & 0x000C) >> 2;
	RC_CtrlData.rc.s2 = ((pData[5] >> 4) & 0x0003);
	RC_CtrlData.mouse.x = ((int16_t)pData[6]) | ((int16_t)pData[7] << 8);
	RC_CtrlData.mouse.y = ((int16_t)pData[8]) | ((int16_t)pData[9] << 8);
	RC_CtrlData.mouse.z = ((int16_t)pData[10]) | ((int16_t)pData[11] << 8); 
	RC_CtrlData.mouse.press_l = pData[12];
	RC_CtrlData.mouse.press_r = pData[13];
	RC_CtrlData.key.v = ((int16_t)pData[14]) | ((int16_t)pData[15] << 8);
	//your control code ….
}

这段代码来自大疆官方遥控器例程,虽然这里不理解也没关系,对于使用该代码没有影响,但是在这里还是分析一下这段代码的含义。

移位运算符

C语言中,移位运算符是位操作的其中一种。位移运算符有两种:左移(<<)和右移(>>)。下面分别介绍:

左移运算符是将其左侧的运算对象每一位的值左移其右侧运算对象指定的位数。左侧运算对象移出的左侧指舍弃,右侧空出来的位用0补齐。

假设有一个八位数组counter[7],当前存储数据为“10011001”,进行位运算:(10011001)<<3,表示将该数据左移三位.
移位完成:(10011001_ _ _ );
由于数组只能存储8位,所以前三位被舍弃:(11001
_ _ _);
后三位由0补齐:(11001000)。

需要注意的是,该操作产生一个新的值,但不改变其运算对象的值,在上述运算中,counter[7]的值一直都是10011001,不会因为位运算而改变数值,如果想改变其数值,可以使用左移赋值运算符(<<=)。

右移与左移原理相同,此处不再赘述。

遥控器数据获取

RoboMaster遥控器使用 DBUS 接收遥控器的数据,一帧数据的长度为18字节,每字节有8位,一共144位,根据遥控器的说 明书可以查出各段数据的含义,从而进行数据拼接,完成遥控器的解码,从RoboMaster遥控器接收系统用户手册可以查到:
图片来自RoboMaster官网
从图片中可以看到,遥控器的三个通道都是11位,但是每个字节只有8位,这个时候就要使用数组拼接。我们设一个8位数组pData;ch0由pData[0]的8位加上pData[1]的后3位组成,ch2由pData[1]的前5位和pData[2]的后6位组成,以此类推。用图片表示为:
在这里插入图片描述

我们知道,遥控器上有一个拨轮,设为CH4,那么它的数据接收怎么写?
CH4和CH0一样,是11位。从上面的程序源码可知,前面存储数据用到了pData[15],那么接下来CH4用到的就是pData[16]和pData[17]的后三位,
代码为:

扫描二维码关注公众号,回复: 15109602 查看本文章

RC_CtrlData.rc.ch4 = ((int16_t)pData[16] | ((int16_t)pData[17] << 8)) &
0x07FF;

遥控器数据解码

以大疆例程里ch0数据解码为例展开讲解:

RC_CtrlData.rc.ch0 = ((int16_t)pData[0] | ((int16_t)pData[1] << 8)) & 0x07FF;

我们假设pData[0]数据为 11001011,pData[1]数据为 10001110,将pData[1]左移8位,作为数据的高八位,对应pData[0]的数据就作为低八位,那么此时数据为 1000111011001011 ,后面的0x7FF转换为2进制是 111 1111 1111,取与操作(&)后结果为 11011001011,即为接收到的数据。
手写
再说一下CH1数据解析:

RC_CtrlData.rc.ch1 = (((int16_t)pData[1] >> 3) | ((int16_t)pData[2] << 5)) & 0x07FF;

同理,我们假设pData[1]数据为 10001110,pData[2]数据为 11000001,将pData[1]右移3位,作为低八位,pData[2]左移5位,作为高八位,那么此时数据为 1100000110001110 ,后面的0x7FF转换为2进制是 111 1111 1111,取与操作(&)后结果为 00110001110,即为接收到的数据(算法和上面一样,就不插图了,太丑了 )。

后面其他的数据处理原理和上述两个大差不差,这里不再赘述。

版权归作者(Alliance战队电控组小昕同学)所有,需要转载或引用请注明来历和作者,若为其他用途或者有其他疑问则联系本文作者。

猜你喜欢

转载自blog.csdn.net/weixin_45850927/article/details/121299686
今日推荐