因为项目需要,想打通板载计算机与飞控之间的通信,最初计划利用mavlink通信协议ROS消息发布机制来解决,网上资料不全,无果,于是决定曲线救国用最原始的串口通信先将消息传送过去再做进一步的处理。网上教程大多比较古早,固件迭代太多次了。于是借鉴网上相关教程做一个汇总。
先交代一下所使用的飞控硬件为pixhawk2.4.8如上图 ,同时给出上边各个端口对应的串口号图以及各个口的具体线序。
准备工作结束,接下来是具体代码实现。首先在Firmware/src/modules
中添加一个新的文件夹,命名为rw_uart
,并创建C文件rw_uart.c。代码如下:包含了接收消息并通过话题发布出去我后续需要在另一个地方来订阅这个消息。
/*
* 串口读取函数
* rw_uart.c
*/
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <stdbool.h>
#include <errno.h>
#include <drivers/drv_hrt.h>
#include <string.h>
#include <systemlib/err.h>
//#include <systemlib/systemlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <uORB/topics/my_uorb_test.h> // 包含生成的uORB消息头文件
#include <uORB/uORB.h>
__EXPORT int rw_uart_main(int argc, char *argv[]);
//static int uart_init(char * uart_name);
static int set_uart_baudrate(const int fd, unsigned int baud);
static int uart_init(const char *uart_name);
int set_uart_baudrate(const int fd, unsigned int baud)
{
int speed;
switch (baud) {
case 9600: speed = B9600; break;
case 19200: speed = B19200; break;
case 38400: speed = B38400; break;
case 57600: speed = B57600; break;
case 115200: speed = B115200; break;
default:
warnx("ERR: baudrate: %d\n", baud);
return -EINVAL;
}
struct termios uart_config;
int termios_state;
/* 以新的配置填充结构体 */
/* 设置某个选项,那么就使用"|="运算,
* 如果关闭某个选项就使用"&="和"~"运算
* */
tcgetattr(fd, &uart_config); // 获取终端参数
/* clear ONLCR flag (which appends a CR for every LF) */
uart_config.c_oflag &= ~ONLCR;// 将NL转换成CR(回车)-NL后输出。
/* 无偶校验,一个停止位 */
uart_config.c_cflag &= ~(CSTOPB | PARENB);// CSTOPB 使用两个停止位,PARENB 表示偶校验
/* 设置波特率 */
if ((termios_state = cfsetispeed(&uart_config, speed)) < 0) {
warnx("ERR: %d (cfsetispeed)\n", termios_state);
return false;
}
if ((termios_state = cfsetospeed(&uart_config, speed)) < 0) {
warnx("ERR: %d (cfsetospeed)\n", termios_state);
return false;
}
// 设置与终端相关的参数,TCSANOW 立即改变参数
if ((termios_state = tcsetattr(fd, TCSANOW, &uart_config)) < 0) {
warnx("ERR: %d (tcsetattr)\n", termios_state);
return false;
}
return true;
}
int uart_init(const char * uart_name)
{
int serial_fd = open(uart_name, O_RDWR | O_NOCTTY);
/*Li