-----------------本文由“智御电子”提供,同时提供视频移植教程,以便电子爱好者交流学习。----------------python
MAVLink是一种针对微型飞行器,推出的轻量化,仅由头文件信息编码而成的软件通讯协议库。git
MAVLink遵循一种混合发布和点对点设计模式:主要的信息能够做为主数据流向多个目标目标进行发送,而一些子协议如(mission protocol或者parameter protocol)能够采用点对点通讯模式,利用重传机制进行可靠的数据传输。github
MAVLink的信息包(各类数据包类型的组合如姿态信息包、GPS信息包)都是定义在XML格式的原始文件中。利用这个XML文件能够生成以下支持语言的MAVLink源代码。针对不一样的的应用场合,XML文件也被定义了多种。好比针对绝大多数的地面站系统和自动驾驶系统,这样一些系统所须要的信息包类型就被定义一种取名为“common.xml”文件中。windows
MAVLink最先是在2009年由Lorenz Meier发布的初版本,而且有有一群贡献者参与其中。设计模式
由于MAVLink不须要额外的设计框架要求,因此它很是适合在一些通讯带宽有限的程序中使用。好比用XML文件生产的C语言源代码很是适合用在RAM或者flash受限制的嵌入式系统中。目前MAVLink已经在许多的产品中被用来做为不一样设备制造商之间通讯的接口而获得应用和验证。框架
支持生成的语言分布式
MAVLink2 能够生成以下语言函数
- C
- C++11
- Python
MAVLink1能够生成以下语言工具
- C
- C#
- Objective C
- Java
- JavaScript
- Lua
- Swift
- Python
XML文件种类:oop
- common.xml
- ardupilotmega.xml
- ASLUAV.xml
- autoquad.xml
- icarous.xml
- matrixpilot.xml
- minimal.xml
- paparazzi.xml
- python_array_test.xml
- slugs.xml
- standard.xml
- test.xml
- ualberta.xml
- uAvionix.xml
本文依据官方开发文档,一步步完成MAVLink的开发。从获取文档、生产源代码到最后的代码工程实例(STM32 KEIL C工程)。
2.1 安装MAVLink工具链
首先须要安装MAVLink相关的工具链:包括XML信息文件、GUI/命令行工具。利用这些工具来获取到MAVLink的源代码。
使用到的工具链以下:
安装步骤:
安装windows版本Python 2.7+ or 3.3+ (Python for Windows)
根据本身的电脑版本下载版本,本文下载Python3.6.五、64bit、version号为“Windows x86-64 executable installer”安装文件进行安装。以下图所示
到安装程序的页面时,勾选上“Add Python 3.6 to PATH”,将path的路径添加到系统的环境变量中。后面直接就直接下一步便可。
安装future模块
键盘输入“win+R”调出“运行”界面,输入“CMD”调出命令行界面。
接着输入“pip install future”命令。会发现开始安装这个模块,通常安装完便可。以下图所示
若是出现以下图所示的提示,按照其推荐的命令“python -m pip install --upgrade pip”输入便可。
安装Git
Git是目前世界上最早进的分布式控制版本系统,主要是代码管理。咱们这边主要是利用这个Git工具将MAVLink的代码及生成器下载下来。Git官方点击下载
选择本身合适的电脑版本,进行一路安装,注册帐户便可。新建一个文件夹,在文件夹中右击鼠标出现以下图标。点击Git GUI Here.
在出现的命令行中输入“git clone https://github.com/mavlink/mavlink.git --recursive”。此时git从远程代码仓库中下载代码。以下图所示
最终获得以下的源代码。
添加MAVLink文件夹路径
将下载好的源代码所在的文件夹路径添加到python环境变量中。 打开windows命令行,输入以下命令。
set PYTHONPATH=C:\your_path_to_mavlink_clone
生成须要的语言代码
在下载好的GIT源代码中,能够发现MAVLink生成器“mavgenerate.py”,它是一个GUI图形界面。咱们能够操做这个图像界面获取到想到的语言代码。
在windows命令行中继续输入以下命令,用来执行“mavgenerate.py”脚本。出现以下的GUI。
python -m mavgenerate
根据本身的目标应用场景选择目标XML文件。本文选择“mavlink\message_definitions\v1.0\common.xml”
设置out保存路径;选择C语言,协议2.0。点击生成便可。到相应的out目录就会发现生成好的C语言代码。
KEIL工程移植
本文利用STM32F4的控制板的PX4控制板,而且利用cubeMX进行工程配置来实现MAVLink的移植。最终实现PX4控制板与QGC上位机的通讯,以此来验证MAVLink是否成功移植。
1.由于转换的C语言代码都是以.h的文件夹实现的,因此把上图的文件包含到工程路径中,而且包含以下的头文件便可包含所有实现的
#include <mavlink/mavlink.h>
接着利用cubeMx进行串口的配置,咱们使用中断DMA接收与普通轮询模式发送。不是本文重点,不作描述,可百度,亦可有兴趣观看视频。
接着咱们能够在keil工程里面全局编译一下,会发现好多的错误。这个错误跟编译器有关。一种方式是直接修改每个错误,能够自行百度“mavlink移植 ”;固然还有一种方法,是在工程配置中加入以下配置:
--no_strict --gnu
目的是想让MAVLink这段代码采用gun的格式进行编译,可是要注意其余的代码须要保证是使用的keil的默认编译器__CC_ARM进行编译。再次编译会发现没有错误。
2.接着就是实现发送、接收数据的底层函数。
C MAVLink库的实现的多通道的数据流,一样的程序能够在不一样的独立通道流上进行传输。若是只存在一个MAVLink数据流,channel 0默认被用来进行数据传输(MAVLINK_COMM_0)
接收数据的处理函数是在MAVLink的 mavlink_helpers.h:mavlink_parse_char()
函数里面实现的。这个函数实际上须要在每次接收到一个字节数据的时候调用它来解析的信息,直到一个完整的数据包被解析完成。
发送数据能够用mavlink_msg_*_pack()
这些函数,而后调用mavlink_helpers.h:mavlink_msg_to_send_buffer()
进行序列化。同时,为了方便,MAVLink为每一种类型的传输数据都定义了一个函数,例如mavlink_msg_raw_imu_send
。想要发送IMU数据调用这个函数便可。
那咱们移植须要关系的是这些函数最后是调用什么的底层硬件接口进行真正的数据传送的。其实最后是调用的_mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len)
这个函数。在这个函数里面有2种底层方式进行数据传送:多字节和单字节。咱们来实现多字节。
首先,定义宏
#define MAVLINK_USE_CONVENIENCE_FUNCTIONS
// 移植必需要设定这个宏,详见代码
#define MAVLINK_SEND_UART_BYTES mavlink_send_uart_bytes
//mavlink_send_uart_bytes是咱们用户本身须要实现的底层代码。
void mavlink_send_uart_bytes(mavlink_channel_t chan, const uint8_t *ch, int length) { HAL_UART_Transmit(&huart8, (uint8_t *)ch, length, 2000); }
3.到这边基本移植都差很少了。本文在main中作了一个mavlink_test()
测试函数用于发数据给上位机,
void mavlink_test(void) { static uint16_t test_count=0; mavlink_message_t lastmsg; test_count++; //5hz if((test_count%100)==0) { mavlink_test_heartbeat2(1,1,&lastmsg); } if((test_count%50)==0) { mavlink_test_raw_imu2(1,1,&lastmsg); } }
同时利用ringbuffer接收数据,而后在main中实时解析Loop_Mavlink_Parse()
上位机发送过来的数据。
void Loop_Mavlink_Parse(void) { if(Mavlink_RB_IsOverFlow()) { Mavlink_RB_Clear(); } while(Mavlink_RB_HasNew()) { uint8_t read = Mavlink_RB_Pop(); if(mavlink_parse_char(MAVLINK_COMM_0, read, &msg, &status)) { //信号处理函数 Mavlink_Msg_Handle(msg); //printf("Received message with ID %d, sequence: %d from component %d of system %d", msg.msgid, msg.seq, msg.compid, msg.sysid); } } }
最后实际测试移植成功。