-----------------本文由「智御電子」提供,同時提供視頻移植教程,以便電子愛好者交流學習。----------------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); } } }
最後實際測試移植成功。