飞控串口通信接入linux

2023-05-16

1.串口设置

在这里插入图片描述

2.串口接入

在这里插入图片描述

3.消息传输

在这里插入图片描述

4.消息透传

在这里插入图片描述

5.mavlink解析

1.mavlink库

将mavlink库添加至项目包含目录

2.常用mavlink消息

mavlink_heartbeat_t 心跳包

mavlink_attitude_t 姿态角、角速度

mavlink_gps_raw_int_t gps信息

mavlink_battery_status_t 电池状态

mavlink_vfr_hud_t 空速地速高度

6.全部代码

com.c

include "com.h"
/*struct termios
{
    unsigned short c_iflag;   //输入模式标志
    unsigned short c_oflag;   //输出模式标志-
    unsigned short c_cflag;   //控制模式标志
    unsigned short c_lflag;   //本地模式标志-
    unsigned char c_line;     //线路规程-
    unsigned char c_cc[NCC];  //控制特性
    speed_t c_ispeed;         //输入速度-
    speed_t c_ospeed;         //输出速度-
}
*/
/****************************************/
/************打开串口函数****************/
/****************************************/
int open_port(int com_port)
{
    int fd;
    /* 使用普通串口 */
    //char *dev[] = {"/dev/ttySAC0","/dev/ttySAC1","/dev/ttySAC2","/dev/ttySAC3"};<br />    /* 使用 USB 转串口 */
    char *dev[] = {"/dev/ttyUSB3", "/dev/ttyUSB1", "/dev/ttyUSB2"};

    printf("open dev [%s]\n",dev[com_port]);
    //O_NDELAY 同 O_NONBLOCK。
    fd = open(dev[com_port], O_RDWR|O_NOCTTY);
    if (fd < 0)
    {
        perror("open serial port"); 
        return(-1); 
    }

com.h

#ifndef _COM_H_
#define _COM_H_
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
 
int set_com_config(int fd,int baud_rate,int data_bits, char parity, int stop_bits);
int open_port(int com_port);
 
#endif

main.c

#include "com.h" 
 
#define BUFFER_SIZE 1024      /*最大缓存区*/
 
//char *pstr[]={"NO1\n","NO2\n","NO3\n","NO4\n"}; 
int main(int argc, char *argv[])
{
	int fd;
	int i;
	char *read_buffer[BUFFER_SIZE];
	int read_buffer_size;
 
	//打开串口
	fd = open_port(0);
	//设置串口
    if(set_com_config(fd, 57600, 8, 'N', 1) < 0) /* 配置串口 */ 
    { 
        perror("set_com_config"); 
        return 1; 
    } 
 
	//发送数据
    do{
        for(i=0;i<1024;i++){
            sleep(1);
        }
	    do{
		    memset(read_buffer,0, BUFFER_SIZE);
	    	read_buffer_size = read(fd, read_buffer, BUFFER_SIZE);				
	    }while(!read_buffer_size);
		    printf("[0x%04x]\n",read_buffer[BUFFER_SIZE]);

	}while(1);
	close(fd);
	return 0;
}

test.c

#include <stdio.h>              // printf   
#include <fcntl.h>              // open   
#include <string.h>             // bzero   
#include <stdlib.h>             // exit   
#include <sys/times.h>          // times   
#include <sys/types.h>          // pid_t   
#include <termios.h>            //termios, tcgetattr(), tcsetattr()
#include <unistd.h>
#include <sys/ioctl.h>          // ioctl
 
#define TTY_DEV "/dev/ttyUSB3"   //端口路径
 
#define TIMEOUT_SEC(buflen,baud) (buflen*20/baud+2)  //接收超时   
#define TIMEOUT_USEC 0
 
//串口结构
typedef struct{
    char prompt;        //prompt after reciving data
    int  baudrate;      //baudrate
    char databit;       //data bits, 5, 6, 7, 8
    char debug;         //debug mode, 0: none, 1: debug
    char echo;          //echo mode, 0: none, 1: echo
    char fctl;          //flow control, 0: none, 1: hardware, 2: software
    char tty;           //tty: 0, 1, 2, 3, 4, 5, 6, 7
    char parity;        //parity 0: none, 1: odd, 2: even
    char stopbit;       //stop bits, 1, 2
    const int reserved; //reserved, must be zero
}portinfo_t;
typedef portinfo_t *pportinfo_t;
 
/**
 * 打开串口,返回文件描述符
 * pportinfo: 待设置的串口信息
*/
int PortOpen(pportinfo_t pportinfo);
 
/**
 * 设置串口
 * fdcom: 串口文件描述符, pportinfo: 待设置的串口信息
*/
int PortSet(int fdcom, const pportinfo_t pportinfo);
/**
 * 关闭串口
 * fdcom:串口文件描述符
*/
void PortClose(int fdcom);
 
/**
 * 发送数据
 * fdcom:串口描述符, data:待发送数据, datalen:数据长度
 * 返回实际发送长度
*/
int PortSend(int fdcom, char *data, int datalen);
 
/**
 * 接收数据
 * fdcom:串口描述符, data:接收缓冲区, datalen:接收长度, baudrate:波特率
 * 返回实际读入的长度
*/
int PortRecv(int fdcom, char *data, int datalen, int baudrate);
 
 
/******************************************* 
 *  获得端口名称 
********************************************/
char *get_ptty(pportinfo_t pportinfo)
{
    char *ptty;
 
    switch(pportinfo->tty){
        case '0':{
            ptty = TTY_DEV"0";
        }break;
        case '1':{
            ptty = TTY_DEV"1";
        }break;
        case '2':{
            ptty = TTY_DEV"2";
        }break;
    }
    return(ptty);
}
 
/******************************************* 
 *  波特率转换函数(请确认是否正确) 
********************************************/
int convbaud(unsigned long int baudrate)
{
    switch(baudrate){
        case 2400:
            return B2400;
        case 4800:
            return B4800;
        case 9600:
            return B9600;
        case 19200:
            return B19200;
        case 38400:
            return B38400;
        case 57600:
            return B57600;
        case 115200:
            return B115200;
        default:
            return B9600;
    }
}
 
/******************************************* 
 *  Setup comm attr 
 *  fdcom: 串口文件描述符,pportinfo: 待设置的端口信息(请确认) 
 * 
********************************************/
int PortSet(int fdcom, const pportinfo_t pportinfo)
{
    struct termios termios_old, termios_new;
    int     baudrate, tmp;
    char    databit, stopbit, parity, fctl;
 
    bzero(&termios_old, sizeof(termios_old));
    bzero(&termios_new, sizeof(termios_new));
    cfmakeraw(&termios_new);
    tcgetattr(fdcom, &termios_old);         //get the serial port attributions
 
    /*------------设置端口属性----------------*/
    //baudrates   
    baudrate = convbaud(pportinfo->baudrate);
    cfsetispeed(&termios_new, baudrate);        //填入串口输入端的波特率   
    cfsetospeed(&termios_new, baudrate);        //填入串口输出端的波特率   
    termios_new.c_cflag |= CLOCAL;              //控制模式,保证程序不会成为端口的占有者
    termios_new.c_cflag |= CREAD;               //控制模式,使能端口读取输入的数据
 
    // 控制模式:flow control
    fctl = pportinfo-> fctl;
    switch(fctl){
        case '0':{
            termios_new.c_cflag &= ~CRTSCTS;            //no flow control
        }break;
        case '1':{
            termios_new.c_cflag |= CRTSCTS;             //hardware flow control
        }break;
        case '2':{
            termios_new.c_iflag |= IXON | IXOFF |IXANY; //software flow control   
        }break;
    }
 
    //控制模式,data bits   
    termios_new.c_cflag &= ~CSIZE;      //控制模式,屏蔽字符大小位   
    databit = pportinfo -> databit;
    switch(databit){
        case '5':
            termios_new.c_cflag |= CS5;
        case '6':
            termios_new.c_cflag |= CS6;
        case '7':
            termios_new.c_cflag |= CS7;
        default:
            termios_new.c_cflag |= CS8;
    }
 
    //控制模式 parity check   
    parity = pportinfo -> parity;
    switch(parity){
        case '0':{
            termios_new.c_cflag &= ~PARENB;     //no parity check   
        }break;
        case '1':{
            termios_new.c_cflag |= PARENB;      //odd check   
            termios_new.c_cflag &= ~PARODD;
        }break;
        case '2':{
            termios_new.c_cflag |= PARENB;      //even check   
            termios_new.c_cflag |= PARODD;
        }break;
    }
 
    //控制模式,stop bits   
    stopbit = pportinfo -> stopbit;
    if(stopbit == '2'){
        termios_new.c_cflag |= CSTOPB;  //2 stop bits   
    }
    else{
        termios_new.c_cflag &= ~CSTOPB; //1 stop bits   
    }
 
    //other attributions default   
    termios_new.c_oflag &= ~OPOST;          //输出模式, 原始数据输出
    termios_new.c_cc[VMIN]  = 0;            //控制字符, 所要读取字符的最小数量
    termios_new.c_cc[VTIME] = 1;            //控制字符, 读取第一个字符的等待时间    unit: (1/10)second   
 
    tcflush(fdcom, TCIFLUSH);               //溢出的数据可以接收,但不读   
    tmp = tcsetattr(fdcom, TCSANOW, &termios_new);  //设置新属性,TCSANOW:所有改变立即生效
    //tcgetattr(fdcom, &termios_old);
 
    return(tmp);
}
 
/******************************************* 
 *  Open serial port 
 *  tty: 端口号 ttyS0, ttyS1, .... 
 *  返回值为串口文件描述符 
********************************************/
int PortOpen(pportinfo_t pportinfo)
{
    int  fdcom;  //串口文件描述符
    char *ptty;
 
    ptty = get_ptty(pportinfo);
    //fdcom = open(ptty, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);   
    fdcom = open(ptty, O_RDWR | O_NOCTTY | O_NONBLOCK);
 
    return (fdcom);
}
 
/******************************************* 
 *  Close serial port 
********************************************/
void PortClose(int fdcom)
{
    close(fdcom);
}
 
/******************************************** 
 *  send data 
 *  fdcom: 串口描述符,data: 待发送数据,datalen: 数据长度 
 *  返回实际发送长度 
*********************************************/
int PortSend(int fdcom, char *data, int datalen)
{
    int len = 0;
 
    len = write(fdcom, data, datalen);  //实际写入的长度   
    if(len == datalen){
        return (len);
  }
    else{
        tcflush(fdcom, TCOFLUSH);
        return -1;
    }
}
 
/******************************************* 
 *  receive data 
 *  返回实际读入的字节数 
 * 
********************************************/
int PortRecv(int fdcom, char *data, int datalen, int baudrate)
{
    int readlen, fs_sel;
    fd_set  fs_read;
    struct timeval tv_timeout;
 
    FD_ZERO(&fs_read);
    FD_SET(fdcom, &fs_read);
    tv_timeout.tv_sec  = TIMEOUT_SEC(datalen, baudrate);
    tv_timeout.tv_usec = TIMEOUT_USEC;
 
    fs_sel = select(fdcom + 1, &fs_read, NULL, NULL, &tv_timeout);
    if(fs_sel){
        readlen = read(fdcom, data, datalen);
        return(readlen);
    }
    else{
        return(-1);
    }
 
    //return (readlen);
}
 
//*************************Test*********************************   
int main(int argc, char *argv[]) {
    int fd = -1, SendLen = 0, RecvLen = 0;
    struct termios termios_cur;
    char RecvBuf[10] = {0};
    portinfo_t portinfo = {
            '0',                            // print prompt after receiving
            57600,                           // baudrate: 9600
            '8',                            // databit: 8
            '0',                            // debug: off
            '1',                            // echo: on
            '1',                            // flow control: hardware
            '0',                            // default tty: COM1
            '0',                            // parity: none
            '1',                            // stopbit: 1
             0                              // reserved
    };
 
    /*
     if(argc != 2){
         printf("Usage: <type 0 -- send 1 -- receive>\n");
         printf("   eg:");
         printf("        MyPort 0");
         exit(-1);
     }
    */
 
    fd = PortOpen(&portinfo);
    if (fd < 0) {
        printf("Error: open serial port error.\n");
        exit(1);
    }
 
    PortSet(fd, &portinfo);
    //char  *data = "hello world dhs!";
    char  data[9] = {0x11,0x22,0x33,0x11,0x22,0x33,0x11,0x22,0x88};
    //data[0] = 0xAA;
 
    int datalen = strlen(data);
    
    //send data
    //while (1)
    {
        for (int i = 0; i < 100; i++)
        {
            SendLen = PortSend(fd, data, 9);
            if (SendLen > 0) {
                printf("No %d send %d data.\n", i, SendLen);
            } else {
                printf("Error: send failed.\n");
            }
            sleep(1);
        }
    }
        PortClose(fd);
 
    /**
        for(;;)
        {
            RecvLen = PortRecv(fd, RecvBuf, 10, portinfo.baudrate);
            if(RecvLen>0){
                for(i=0; i<RecvLen; i++){
                    printf("Receive data No %d is %x.\n", i, RecvBuf[i]);
                }
                printf("Total frame length is %d.\n", RecvLen);
            }
            else{
                printf("E
                rror: receive error.\n");
            }
            sleep(2);
        }
    */
 
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

飞控串口通信接入linux 的相关文章

随机推荐

  • [RTOS]uCOS、FreeRTOS、RTThread、RTX等RTOS的对比之特点

    最近正好又重新回顾了一下这几款OS xff0c 心里一直有个疑问 xff0c 明明这几款RTOS是这么像 xff0c 为什么还要搞出这么多个来呢 xff0c 最后的结论就是 xff0c 管他呢 xff0c 反正哪个用的顺手用哪个 本篇博客就
  • git submodule

    此文已由作者张磊薪授权网易云社区发布 欢迎访问网易云社区 xff0c 了解更多网易技术产品运营经验 前言 submodule 目前对 git 仓库拆分的已有实现之一 环境 git version 2 7 4 windows 1 准备工作 首
  • FreeRTOS 通信方式

    文章目录 一 消息队列二 信号量三 互斥量四 事件五 通知 一 消息队列 消息队列是一种常用于任务间通信的数据结构 xff0c 队列可以在任务与任务间 中断和任务间传递信息 读写队列均支持超时机制 1 创建队列 QueueHandle t
  • 芯片、模组、开发板的区别与联系-结合ESP32浅谈

    1 从外形说起 xff1a 1 1芯片 没错 xff0c 这块黑色的小硅片就是 芯片 本体 xff08 通常比大拇指还小 xff0c 内部集成了实现特定功能的硬件集成电路 xff09 1 2模组 由上述芯片研发的模组是这样的 xff1a 从
  • 一文读懂局域网、广域网、WLAN、WiFi的联系与区别

    1 引言 最近总有小伙伴问我 xff0c 广域网 局域网的区别与联系 WLAN与WiFi的关系 xff0c 遂写此文 xff0c 以作解答 2 广域网与局域网 广域网 xff08 Wide Area Network xff09 xff0c
  • RTOS 和裸机系统的异同-基于 ESP32 学习双核 FreeRTOS 的使用

    Learning FreeRTOS with esp32 什么是 RTOS 其本质上是运行在小型嵌入式设备上的特殊软件 系统软件 如同手机的安卓系统软件 windows 系统软件 RTOS VS 裸机系统 传统的裸机系统 xff08 无操作
  • u盘打开之后就只有一个快捷方式

    我今天也出现了这种问题 xff0c 百度一下发 现都解决不了 xff0c 然后自己尝试了一个新的方法 xff1a 其实还有一个又简单又好用又快捷的方法就是 1 只要你记得你的U盘里的任何一个文件或者文件夹的名称 xff0c 2 然后搜索U盘
  • FreeRTOS 删除任务

    FreeRTOS 删除任务 概述 任务的删除使用的 API 为 xff1a void vTaskDelete TaskHandle t xTask 任务删除主要是两种情况 xff1a 自删除 xff0c 即在任务本身的 TaskCode 中
  • 使用 stream buffer 传递数据

    使用 stream buffer 传递数据 概述 如前所述 xff0c 队列虽然提供了任务之间传递数据的功能 xff0c 但没有对通知机制进行优化 xff0c 即不方便实现多次采集不同长度的数据 xff0c 然后触发一次通知接收的机制 特性
  • 使用 message buffer 传递数据

    使用 message buffer 传递数据 概述 MessageBuffer xff0c 即消息缓冲区 xff0c 是在流式缓冲区的基础上实现的针对离散消息的专用通信组件 xff0c 其进一步针对 消息 进行设计改进 在 StreamBu
  • FreeRTOS 任务间通信与同步总结

    FreeRTOS 任务任务同步与数据传递 xff08 通信 xff09 总结 概述 本章主要介绍了 RTOS 系统中数据传递的机制 根据数据传递的目的 xff0c 可以分为同步 消息通信两种 其中同步是指协调程序运行的先后顺序 xff0c
  • RTOS 中 Task 之间资源共享示例

    RTOS 中 Task 之间资源共享示例 什么是共享资源 大型项目往往需要创建多个任务 xff0c 任务之间协同合作完成一个大型的功能 在前述的章节中 xff0c 我们讲述了任务间的同步与通信 xff0c 但合作与竞争总是相辅相成的 任务
  • RTOS共享资源保护-优先级反转与解决策略

    RTOS 中的优先级反转与解决策略 概述 上节讲述了可以使用二值信号量实现任务 任务之间的共享资源的保护 二值信号量的确完成了保护共享资源的任务 但在一些情况下 这种策略会带来副作用 即优先级反转 优先级反转是如何产生的 理想情况下 按照我
  • RTOS 驱动开发篇-通过 RTOS 组件实现按键驱动-优化1

    RTOS 驱动开发篇 通过 RTOS 组件实现按键驱动 优化1 概述 一个好的驱动程序需要数据关系清晰 代码可复用性高 并且便于维护 如在 RTOS 驱动开发篇 通过 RTOS 组件实现按键驱动1 中所述的那样 当前的按键驱动代码只是为了让
  • RTOS 驱动开发篇-通过 RTOS 组件实现按键驱动-优化2

    RTOS 驱动开发篇 通过 RTOS 组件实现按键驱动 优化2 概述 一个好的驱动程序需要数据关系清晰 代码可复用性高 并且便于维护 如在 RTOS 驱动开发篇 通过 RTOS 组件实现按键驱动1 中所述的那样 基础版本的按键驱动代码只是为
  • 物联网应用选择 RTOS 还是 Linux?

    物联网应用选择 RTOS 还是 Linux Linux VS RTOS xff0c 我该选哪个 xff1f 引言 在开发设备或系统时 xff0c 您需要做出的最早和最关键的决定之一就是决定它将运行哪种类型的操作系统 操作系统是基于特定硬件的
  • 嵌入式编程中的 __attribute__ 到底是什么

    嵌入式编程中的 attribute 到底是什么 相信阅读嵌入式代码的老铁经常看到一些类型定义 变量 函数有 attribute 标识符 xff0c 这个标识符号到底是做什么的 xff1f 有哪些用法 xff0c 咱们今天就来聊一聊 attr
  • opengl之glTranslatef()函数和glRotatef()函数和glLoadIdentity()函数

    glLoadIdentity 将当前的用户坐标系的原点移到了屏幕中心 xff1a 类似于一个复位操作 1 X坐标轴从左至右 xff0c Y坐标轴从下至上 xff0c Z坐标轴从里至外 2 OpenGL屏幕中心的坐标值是X和Y轴上的0 0f点
  • 一文读懂大端、小端、字节序、MSB、LSB、MSBs、LSBs

    大端 小端 字节序 MSB LSB MSBs LSBs 5分钟完全理解上述嵌入式 物联网开发中很扯蛋的几个被玩坏概念 MSB LSB 对于涉及 bit 流的概念中 MSB xff08 Most Significant Bit xff09 x
  • 飞控串口通信接入linux

    1 串口设置 2 串口接入 3 消息传输 4 消息透传 5 mavlink解析 1 mavlink库 将mavlink库添加至项目包含目录 2 常用mavlink消息 mavlink heartbeat t 心跳包 mavlink atti