移植Mavlink协议到STM32F103详细教程
环境配置win10系统+STM32F103ZET6步骤参考MAVLINK官网1.安装python3.6以上的版本,我安装的是python3.8Python3.8下载地址详细安装步骤可参考:python3.8下载及安装步骤详解安装完成后,使用win+R打开运行窗口,输入cmd命令,进入终端使用python命令即可在终端打开python,使用exit()命令可退出python环境2.在终端中使用pip
环境配置
win10系统+STM32F103ZET6
步骤
1.安装python3.6以上的版本
,我安装的是python3.8
Python3.8下载地址
详细安装步骤可参考:python3.8下载及安装步骤详解
安装完成后,使用win+R打开运行窗口,输入cmd命令,进入终端
使用python命令即可在终端打开python,使用exit()命令可退出python环境
2.在终端中使用pip3 install future命令安装future模块

这里是提示我已经安装过future模块了,警告是说我安装的不是最新版的future,无伤大雅
3.下载mavlinkgenerator
·在git 命令窗口中执行方式:git clone https://github.com/mavlink/mavlink
如果系统没有安装git包的可以参考Windows系统Git安装教程,超详细的安装过程!附软件资料~
如果下载失败的话可以考虑换个网再试一下
·进入文件夹:cd mavlink
此处我的mavlink下载到了C盘用户目录下,由于python安装在D盘,我就把mavlink文件夹复制到了D盘,和python在同一个目录下
在终端中切换到mavlink文件夹下
关于如何切换到D盘可参考:windows系统下使用cd命令切换到D盘的方法
·更新子模块:git submodule update --init --recursive
一定要更新子模块,不然后续运行会出错
4.执行mavgenerate.py,这是用Python语言编写的MAVLink的图形用户界面代码生成器。
python mavgenerate.py
如果没有更新子模块这一步就会出错
启动界面如下图所示
XML:选择\message_definitions\v1.0\common.xml
Out :自己选择一个目录存储
Language:选择自己需要的语言
点击Generate则可.
5.在out目录下可看到文件夹mav,具体内容如下图所示

6.打开正点原子例程:实验4 串口实验

新建文件夹MAVLINK,将第五步mav文件夹下的内容复制进去
7. 打开工程新建分组,将所有拷贝过来的文件和头文件目录添加好


8.新建manlink_avoid_errors.h用来解决报错,尽量将更改添加到这个文件,方便以后移植。
后面内容主要参考[移植mavlink到stm32详细教程,后面附快速移植方法]
上面参考文章中提供的代码有部分缺少空格,如下图蓝色方框内代码
正确代码如下所示:
/** @file mavlink_avoid_errors.h
* @简介:本文件是由624668529添加,用来统一解决mavlink报错信息
* @see QQ624668529
*/
#ifndef MAVLINK_AVOID_ERRORS_H
#define MAVLINK_AVOID_ERRORS_H
/*解决..\MAVLINK\common\../mavlink_types.h(53): error: #20: identifier "pack" is undefined*/
#define MAVPACKED( __Declaration__ ) __Declaration__
/*解决..\MAVLINK\common\../mavlink_types.h(53): error: #3092: anonymous unions are only supported in --gnu mode, or when enabled with #pragma anon_unions*/
#pragma anon_unions
#define inline __INLINE
#ifndef memset//由624668529添加 2018-08-24
static inline void*memset(void*dest,int data,size_t length)
{
uint32_t i;
int*point = dest;
for(i=0; i<length; i++) point[i]= data;
return dest;
}
#endif
#ifndef memcpy//由624668529添加 2018-08-24
void*memcpy(void*dest,const void*src,size_t n)
{
unsigned char*pout =(unsigned char*)dest;
unsigned char*pin =(unsigned char*)src;
while(n-->0)*pout++=*pin++;
return dest;
}
#include"mavlink_types.h"
#define MAVLINK_USE_CONVENIENCE_FUNCTIONS
#define MAVLINK_SEPARATE_HELPERS
//mavlink_system_t mavlink_system = {0,0};
mavlink_system_t mavlink_system ={1,1};// System ID, 1-255, Component/Subsystem ID, 1-255
void comm_send_ch(mavlink_channel_t chan,uint8_t buf)
{
chan=chan;
USART_SendData(USART1, buf);//向串口1发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
}
#endif
#include"mavlink.h"
#include"mavlink_helpers.h"
#endif//AVLINK_AVOID_ERRORS_H
9.修改main.c中代码为:
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include"mavlink_avoid_errors.h"
/************************************************
ALIENTEK精英STM32开发板实验4
串口 实验
技术支持:www.openedv.com
淘宝店铺:http://eboard.taobao.com
关注微信公众平台微信号:"正点原子",免费获取STM32资料。
广州市星翼电子科技有限公司
作者:正点原子 @ALIENTEK
************************************************/
int main(void)
{
mavlink_heartbeat_t packet_in ={963497464,17,84,151,218,3};
mavlink_heartbeat_t packet1;
memset(&packet1,0,sizeof(packet1));
packet1.custom_mode = packet_in.custom_mode;
packet1.type = packet_in.type;
packet1.autopilot = packet_in.autopilot;
packet1.base_mode = packet_in.base_mode;
packet1.system_status = packet_in.system_status;
packet1.mavlink_version = packet_in.mavlink_version;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init();//延时初始化
uart_init(115200);//串口初始化波特率为115200
LED_Init();//初始化与LED连接的硬件接口
while(1)
{
mavlink_msg_heartbeat_send(MAVLINK_COMM_1 , packet1.type , packet1.autopilot , packet1.base_mode , packet1.custom_mode , packet1.system_status );
delay_ms(1000);
}
}
10.将mavlink_conversions.h更改这一部分代码为:
可解决错误“declaration may not appear after executable statement in block”
MAVLINK_HELPER void mavlink_dcm_to_quaternion(const float dcm[3][3], float quaternion[4])
{
int i,dcm_i,dcm_j,dcm_k;
float s;
float tr = dcm[0][0] + dcm[1][1] + dcm[2][2];
if (tr > 0.0f) {
s = sqrtf(tr + 1.0f);
quaternion[0] = s * 0.5f;
s = 0.5f / s;
quaternion[1] = (dcm[2][1] - dcm[1][2]) * s;
quaternion[2] = (dcm[0][2] - dcm[2][0]) * s;
quaternion[3] = (dcm[1][0] - dcm[0][1]) * s;
} else {
/* Find maximum diagonal element in dcm
* store index in dcm_i */
dcm_i = 0;
for (i = 1; i < 3; i++) {
if (dcm[i][i] > dcm[dcm_i][dcm_i]) {
dcm_i = i;
}
}
dcm_j = (dcm_i + 1) % 3;
dcm_k = (dcm_i + 2) % 3;
s = sqrtf((dcm[dcm_i][dcm_i] - dcm[dcm_j][dcm_j] -
dcm[dcm_k][dcm_k]) + 1.0f);
quaternion[dcm_i + 1] = s * 0.5f;
s = 0.5f / s;
quaternion[dcm_j + 1] = (dcm[dcm_i][dcm_j] + dcm[dcm_j][dcm_i]) * s;
quaternion[dcm_k + 1] = (dcm[dcm_k][dcm_i] + dcm[dcm_i][dcm_k]) * s;
quaternion[0] = (dcm[dcm_k][dcm_j] - dcm[dcm_j][dcm_k]) * s;
}
}
11.将mavlink_helpers.h中更改这一部分代码为:
可解决错误“declaration may not appear after executable statement in block”
MAVLINK_HELPER uint16_t mavlink_msg_to_send_buffer(uint8_t *buffer, const mavlink_message_t *msg)
{
uint8_t *ck;
memcpy(buffer, (const uint8_t *)&msg->magic, MAVLINK_NUM_HEADER_BYTES + (uint16_t)msg->len);
ck = buffer + (MAVLINK_NUM_HEADER_BYTES + (uint16_t)msg->len);
ck[0] = (uint8_t)(msg->checksum & 0xFF);
ck[1] = (uint8_t)(msg->checksum >> 8);
return MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)msg->len;
}
12.屏蔽mavlink_types.h中这一部分代码:
//// Macro to define packed structures
//#ifdef __GNUC__
// #define MAVPACKED( __Declaration__ ) __Declaration__ __attribute__((packed))
//#else
// #define MAVPACKED( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) )
//#endif
13.将common.h中更改这一部分代码为:
可解决错误literal treated as "long long"和“enumeration value is out of “int” range”
MAV_SYS_STATUS_EXTENSION_USED=(int)2147483648u, /* 0x80000000 Extended bit-field are used for further sensor status bits (needs to be set in onboard_control_sensors_present only) | */
MAV_SYS_STATUS_SENSOR_ENUM_END=(int)2147483649u, /* | */
HIL_SENSOR_UPDATED_RESET=(int)2147483648u, /* Full reset of attitude/position/velocities/etc was performed in sim (Bit 31). | */
HIL_SENSOR_UPDATED_FLAGS_ENUM_END=(int)2147483649u, /* | */
14.编译

15.下载到开发板打开串口调试助手
成功接收到数据,如图,表示移植成功
下图解释了每个数据位的含义
此处还有个小插曲:单片机通过usb连接到电脑后电脑无法试别,检查ch340驱动,无可卸载,预安装成功,正在束手无策之时,换了根usb线,电脑可识别了!

思考
mavlink作为一个非常可靠(至少两字节校验)、支持类型丰富(message ID、component ID等)的通信协议,每次通信时,除了payload以外,还要占用至少8个字节的冗余信息。因此在使用mavlink之前需要考虑,在硬件资源非常有限的情况下,是否有必要牺牲效率来换取可靠性?
更多推荐


所有评论(0)