概述
我使用代码对应的上位机版本为v6,具体通信协议格式在打开V6版本上位机–帮助信息–通信协议里可以看到。
这部分数据传输的核心简单的解帧。这部分的讲解以及匿名的通信协议的简介可以看另一篇文章**《串口通信协议》**
核心内容在下面一点,如果只需要研究通信协议可以直接看下面。
先来分析代码
依然注意到头文件中的一个结构体,这是一堆标志位,就不做赘述了。
typedef struct
{
u8 msg_id;
u8 msg_data;
u8 send_check;
u8 send_version;
u8 send_status;
u8 send_senser;
u8 send_senser2;
u8 send_rcdata;
u8 send_offset;
u8 send_motopwm;
u8 send_power;
u8 send_user;
u8 send_speed;
u8 send_sensorsta;
u8 send_location;
u8 send_omv_ct;
u8 send_omv_lt;
u8 send_vef;
u16 send_parame;
u16 paraToSend;
} dt_flag_t;
接下来的代码类似于任务调度,在不同时刻将不同的代码发出。(可以忽略以下一大段代码)
/
//Data_Exchange函数处理各种数据发送请求,比如想实现每5ms发送一次传感器数据至上位机,即在此函数内实现
//此函数应由用户每1ms调用一次
extern float ultra_dis_lpf;
void ANO_DT_Data_Exchange(void)
{
static u16 cnt = 0;
static u16 senser_cnt = 10;
static u16 senser2_cnt = 50;
static u16 user_cnt = 10;
static u16 status_cnt = 15;
static u16 rcdata_cnt = 20;
static u16 motopwm_cnt = 20;
static u16 power_cnt = 50;
static u16 speed_cnt = 50;
static u16 sensorsta_cnt = 500;
static u16 omv_cnt = 100;
static u16 location_cnt = 500;
static u8 flag_send_omv = 0;
if((cnt % senser_cnt) == (senser_cnt-1))
f.send_senser = 1;
if((cnt % senser2_cnt) == (senser2_cnt-1))
f.send_senser2 = 1;
if((cnt % user_cnt) == (user_cnt-2))
f.send_user = 1;
if((cnt % status_cnt) == (status_cnt-1))
f.send_status = 1;
if((cnt % rcdata_cnt) == (rcdata_cnt-1))
f.send_rcdata = 1;
if((cnt % motopwm_cnt) == (motopwm_cnt-2))
f.send_motopwm = 1;
if((cnt % power_cnt) == (power_cnt-2))
f.send_power = 1;
if((cnt % speed_cnt) == (speed_cnt-3))
f.send_speed = 1;
if((cnt % sensorsta_cnt) == (sensorsta_cnt-2))
{
f.send_sensorsta = 1;
}
if((cnt % omv_cnt) == (omv_cnt-2))
{
flag_send_omv = 1;
}
if((cnt % location_cnt) == (location_cnt-3))
{
f.send_location = 1;
}
if(++cnt>1000) cnt = 0;
/
if(f.send_version)
{
f.send_version = 0;
ANO_DT_Send_Version(4,300,100,400,0);
}
else if(f.paraToSend < 0xffff)
{
ANO_DT_SendParame(f.paraToSend);
f.paraToSend = 0xffff;
}
///
else if(f.send_status)
{
f.send_status = 0;
ANO_DT_Send_Status(imu_data.rol,imu_data.pit,imu_data.yaw,wcz_hei_fus.out,(flag.flight_mode+1),flag.unlock_sta);
}
///
else if(f.send_speed)
{
f.send_speed = 0;
ANO_DT_Send_Speed(loc_ctrl_1.fb[Y],loc_ctrl_1.fb[X],loc_ctrl_1.fb[Z]);
}
///
else if(f.send_user)
{
f.send_user = 0;
ANO_DT_Send_User();
}
///
else if(f.send_senser)
{
f.send_senser = 0;
ANO_DT_Send_Senser(sensor.Acc[X],sensor.Acc[Y],sensor.Acc[Z],sensor.Gyro[X],sensor.Gyro[Y],sensor.Gyro[Z],mag.val[X],mag.val[Y],mag.val[Z]);
}
/
else if(f.send_senser2)
{
f.send_senser2 = 0;
ANO_DT_Send_Senser2(baro_height,ref_tof_height,sensor.Tempreature_C*10);//原始数据
}
/
else if(flag_send_omv)
{
flag_send_omv = 0;
if(f.send_omv_ct)
{
f.send_omv_ct = 0;
ANO_DT_SendOmvCt(opmv.cb.color_flag,opmv.cb.sta,opmv.cb.pos_x,opmv.cb.pos_y,opmv.cb.dT_ms);
}
else if(f.send_omv_lt)
{
f.send_omv_lt = 0;
ANO_DT_SendOmvLt(opmv.lt.sta, opmv.lt.angle, opmv.lt.deviation, opmv.lt.p_flag, opmv.lt.pos_x, opmv.lt.pos_y, opmv.lt.dT_ms);
}
}
/
else if(f.send_rcdata)
{
f.send_rcdata = 0;
s16 CH_GCS[CH_NUM];
for(u8 i=0;i<CH_NUM;i++)
{
if((chn_en_bit & (1<<i)))//(Rc_Pwm_In[i]!=0 || Rc_Ppm_In[i] !=0 )//该通道有值
{
CH_GCS[i] = CH_N[i] + 1500;
}
else
{
CH_GCS[i] = 0;
}
}
ANO_DT_Send_RCData(CH_GCS[2],CH_GCS[3],CH_GCS[0],CH_GCS[1],CH_GCS[4],CH_GCS[5],CH_GCS[6],CH_GCS[7],0,0);
}
/
else if(f.send_motopwm)
{
f.send_motopwm = 0;
#if MOTORSNUM == 8
ANO_DT_Send_MotoPWM(motor[0],motor[1],motor[2],motor[3],motor[4],motor[5],motor[6],motor[7]);
#elif MOTORSNUM == 6
ANO_DT_Send_MotoPWM(motor[0],motor[1],motor[2],motor[3],motor[4],motor[5],0,0);
#elif MOTORSNUM == 4
ANO_DT_Send_MotoPWM(motor[0],motor[1],motor[2],motor[3],0,0,0,0);
#else
#endif
}
/
else if(f.send_power)
{
f.send_power = 0;
ANO_DT_Send_Power(Plane_Votage*100,0);
}
else if(f.send_sensorsta)
{
f.send_sensorsta = 0;
ANO_DT_SendSensorSta(switchs.of_flow_on ,switchs.gps_on,switchs.opmv_on,switchs.uwb_on,switchs.of_tof_on);
}
else if(f.send_location)
{
f.send_location = 0;
ANO_DT_Send_Location(switchs.gps_on,Gps_information.satellite_num,(s32)Gps_information.longitude,(s32)Gps_information.latitude,123,456);
}
else if(f.send_vef)
{
ANO_DT_Send_VER();
f.send_vef = 0;
}
/
/
/
ANO_DT_Data_Receive_Anl_Task();
/
Usb_Hid_Send();
/
}
接下来才是正文
以发送版本号的函数为例了解匿名飞控收发协议。
匿名飞控的通信协议
与一些较为简单的通信协议相比,这个协议增加了发送设备地址,接收设备地址,功能字,数据长度和和校验部分。其中设备地址由用户定义用来区别不同设备。功能字用来区别这一帧传输了什么内容。数据长度则是计算用户实际传输的数据长度。最后增加了一字节和校验用来校验数据。
注意这个函数是发送用的,也就是封装这个帧。
void ANO_DT_Send_Version(u8 hardware_type, u16 hardware_ver,u16 software_ver,u16 protocol_ver,u16 bootloader_ver)
{
u8 _cnt=0;
data_to_send[_cnt++]=0xAA; //帧头
data_to_send[_cnt++]=MYHWADDR; //下位机地址
data_to_send[_cnt++]=SWJADDR; //上位机地址
data_to_send[_cnt++]=0x00; //功能字,表示此帧发送版本信息
data_to_send[_cnt++]=0; //len字节
//以下为数据部分
data_to_send[_cnt++]=hardware_type;
data_to_send[_cnt++]=BYTE1(hardware_ver);
data_to_send[_cnt++]=BYTE0(hardware_ver);
data_to_send[_cnt++]=BYTE1(software_ver);
data_to_send[_cnt++]=BYTE0(software_ver);
data_to_send[_cnt++]=BYTE1(protocol_ver);
data_to_send[_cnt++]=BYTE0(protocol_ver);
data_to_send[_cnt++]=BYTE1(bootloader_ver);
data_to_send[_cnt++]=BYTE0(bootloader_ver);
data_to_send[4] = _cnt-5; //计算数据长度
u8 sum = 0;
for(u8 i=0;i<_cnt;i++) //计算校验和
sum += data_to_send[i];
data_to_send[_cnt++]=sum;
ANO_DT_Send_Data(data_to_send, _cnt);
}
认识了这个那么其他函数都大同小异了,其中有一个函数ANO_DT_Send_RCData();
较为特殊是遥控器控制的发送,之后的文章中我会提到。
另外还有一个经典的函数不得不提,这个函数是校验数据用的,也就是解帧。注释如下
void ANO_DT_Data_Receive_Prepare(u8 data)
{
static u8 _data_len = 0;
static u8 state = 0;
if(state==0&&data==0xAA) //校验帧头0xAA,如果state为0表明刚开始解帧,如果第一个字节的数据为0xAA,说明帧头正确。
{
state=1; //如果帧头正确,state为1,可以进入下一字节
DT_RxBuffer[0]=data; //串口存入
}
else if(state==1&&data==0xAF) //数据源,0xAF表示数据来自上位机
{
state=2;
DT_RxBuffer[1]=data;
}
else if(state==2) //数据目的地
{
state=3;
DT_RxBuffer[2]=data;
}
else if(state==3) //功能字
{
state=4;
DT_RxBuffer[3]=data;
}
else if(state==4) //数据长度
{
state = 5;
DT_RxBuffer[4]=data;
_data_len = data;
DT_data_cnt = 0;
}
else if(state==5&&_data_len>0&&_data_len<80)
{
_data_len--;
DT_RxBuffer[5+DT_data_cnt++]=data;
if(_data_len==0)
state = 6;
}
else if(state==6)
{
state = 0;
DT_RxBuffer[5+DT_data_cnt]=data;
ano_dt_data_ok = 1;//ANO_DT_Data_Receive_Anl(DT_RxBuffer,DT_data_cnt+5);
}
else
state = 0;
}
如有错误还请不吝指正,欢迎交流,我的邮箱是jia_rc@163.com。
最后
以上就是潇洒自行车为你收集整理的ANO匿名飞控STM32代码解读(二)数据传输——Ano_DT.c的全部内容,希望文章能够帮你解决ANO匿名飞控STM32代码解读(二)数据传输——Ano_DT.c所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复