mavlink协议被大众知晓应该是PX4项目发起之后,随着开源飞控神器PX项目进入国内。本次就只分析移植过程中的问题,协议具体内容及其他知识只稍作带过,有时间再更新。
mavlink的源码有官方的代码生成器,或者从开源的px4或者px4flow(光流)的源代码中获得。目前版本只有v0.9和v1.0,0.9已经逐渐不更新了。要用1.0的。
1.如果从mavlink官网下载的生成器生成代码的话,需要额外的一些改动,下载的文件如下,需要py环境,歪果仁好像很喜欢py。
运行后的效果是这样的,通过xml文件定义数据结构,语言选C语言,就能生成标准的c代码了。
不大推荐这种方式,不过需要新的数据帧结构的话,用这种方式可以保证代码比较规矩一致。
2.px4或者光流的源码里的,和生成器的代码差别很小,要修改的地方只有一处。
简单分析一下代码文件的功能和结构。代码在A/mavlink/include/mavlink/v1.0下,A是源代码的位置。
checksum:校验和,用来在数据帧结尾加一个16bits校验码检查通讯出错。不需要改。
mavlink_conversions:一些常用的转换函数方法,四元数、矩阵、欧拉等等的转换,不用改。
mavlink_helpers:需要修改,翻到文件最下面,有注释说明了需要根据你使用的MCU重写字符发送的底层函数,常见的就是用串口,重写个串口发送单个字符函数就行。
MAVLINK_HELPER void _mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len)
{
#ifdef MAVLINK_SEND_UART_BYTES
/* this is the more efficient approach, if the platform
defines it */
MAVLINK_SEND_UART_BYTES(chan, (const uint8_t *)buf, len);
#else
/* fallback to one byte at a time */
uint16_t i;
for (i = 0; i < len; i++) {
comm_send_ch(chan, (uint8_t)buf[i]);
}
#endif
}
可以在其他函数中定义宏#define MAVLINK_SEND_UART_BYTES mavlink_send_uart_bytes,并重写mavlink_send_uart_bytes为自己的函数就行。
mavlink_types:定义了用到的各种数据结构,方法1生成的代码片段是这样的
MAVPACKED(
typedef struct __mavlink_message {
uint16_t checksum; ///< sent at end of packet
uint8_t magic; ///< protocol magic marker
uint8_t len; ///< Length of payload
uint8_t seq; ///< Sequence of packet
uint8_t sysid; ///< ID of message sender system/aircraft
uint8_t compid; ///< ID of the message sender component
uint8_t msgid; ///< ID of message in payload
uint64_t payload64[(MAVLINK_MAX_PAYLOAD_LEN+MAVLINK_NUM_CHECKSUM_BYTES+7)/8];
}) mavlink_message_t;
需要改成
typedef struct __mavlink_message {
uint16_t checksum; ///< sent at end of packet
uint8_t magic; ///< protocol magic marker
uint8_t len; ///< Length of payload
uint8_t seq; ///< Sequence of packet
uint8_t sysid; ///< ID of message sender system/aircraft
uint8_t compid; ///< ID of the message sender component
uint8_t msgid; ///< ID of message in payload
uint64_t payload64[(MAVLINK_MAX_PAYLOAD_LEN+MAVLINK_NUM_CHECKSUM_BYTES+7)/8];
} mavlink_message_t;
想要理解mavlink的设计思路的话,参照CANopen协议就行,后者的资料多,二者的思路我认为是极其类似的。