解析串口-接收完整数据帧

2023-05-16

在linux下编写串口通讯程序,采用select监听串口的可读事件,一旦可读,调用read。但是我们会发现,read一次得到的数据通常不是完整的一个数据帧。

比如完整数据帧为

这里写图片描述

但是实际上需要read多次才能完全读到。

程序实际运行情况:

两次读完:

这里写图片描述

四次读完:

这里写图片描述

为了解决不能接收完整数据帧的问题,借鉴了网友的例子,并进行了一些改动:

现在的效果:

这里写图片描述

下面是程序代码:

#include "smartlight.h"

int portfd = -1;
void print_frame(const char *desc,uint8_t *buf,int size);
void getCompleteFrame(uint8_t *inBuf,int inCnt,uint8_t *outBuf,int *destCnt,int *readStatus);
void *monitor_serial_readable(void *arg);

int main(int argc,char *argv[])
{
    int nret;
    pthread_t wtid;
    /* open serial port */
    portfd = open_port();
    /* set serial port */
    set_opt(portfd,57600);

    nret = pthread_create(&wtid,NULL,monitor_serial_readable,NULL);
    if(nret != 0)
    {
        DEBUG_ERR(create thread failed);
        exit(-1);
    }
    nret = pthread_join(wtid,NULL);
    if(nret != 0)
    {
        DEBUG_ERR(join thread failed);
        exit(-1);
    }
    close(portfd);

    return 0;
}

void getCompleteFrame(uint8_t *inBuf,int inCnt,uint8_t *outBuf,int *destCnt,int *readStatus)
{
    int i;
    for(i=0; i<inCnt; i++)
    {
        if(inBuf[i] == 0x11 && inBuf[i+2] == 0x00 && inBuf[i+3] == 0x00)//header
        {
            outBuf[(*destCnt)++] = inBuf[i];
            *readStatus = 1;
            //print_frame("header",dest,dest_cnt);
            continue;
        }
        if(*readStatus == 1)//body
        {
            outBuf[(*destCnt)++] = inBuf[i];    
            //print_frame("body",dest,dest_cnt);
        }
        if(*destCnt == outBuf[1])//tail
        {
            print_frame("tail",outBuf,*destCnt);
            *readStatus = 0;
            *destCnt = 0;
            memset(outBuf,-1,sizeof(outBuf));
            memset(inBuf,0,sizeof(inBuf));
            continue;
        }
    }
}

void *monitor_serial_readable(void *arg)
{
    int rc,i,nread=0;
    fd_set rset;
    struct timeval tv;
    uint8_t buf[1024] = {0};
    uint8_t dest[1024]={0};
    int read_status = 0;
    int dest_cnt = 0;

    while(1)
    {
        FD_ZERO(&rset);
        FD_SET(portfd,&rset);

        tv.tv_sec = 5;
        tv.tv_usec = 0;

        rc = select(portfd+1,&rset,NULL,NULL,&tv);
        if(rc == -1)
        {
            DEBUG_ERR(select error in thread);
            continue;
        }
        if(rc == 0)
        {
            DEBUG_INFO(select timeout in thread);
            continue;
        }
        else
        {
            nread = read(portfd,buf,sizeof(buf));   
            if(nread == -1)
            {
                perror("read");
                usleep(100*1000);
                continue;
            }
            if(nread == 0)
            {
                printf("nread==0\n");
                usleep(100*1000);
                continue;
            }
            printf("nread = %d\n",nread);
            getCompleteFrame(buf,nread,dest,&dest_cnt,&read_status);
        }
    }//END_while
}

void print_frame(const char *desc,uint8_t *buf,int size)
{
    int i;

    printf(RED"[%s] [LEN=%d]"COLOR_END,desc,size);
    for(i=0; i<size; i++)
    {
        printf(BLUE"[%.2x]"COLOR_END,buf[i]);
    }
    printf("\n");
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

解析串口-接收完整数据帧 的相关文章

随机推荐

  • ARM 7 三级 中断流水线

    ARM 7 在冯诺依曼 结构的 是三级流水线技术 分别是 取址 译码 执行 当有BL 的指令 执行时 流水线 也会被阻断 在分支指令执行的时候 其后第一条指令 被 解码 第二条 指令 被 取址 xff0c 当前的PC指针是 指在取址这的 x
  • S5PC100 I2C总线

    I2C 使用2根双向信号线来传递数据 SCL 时钟线 SDA 数据线 特点 半双功 xff0c 仅需要2根线 一般在PCU 上占2个PIN I2C 总线 上 都是 oc od 输出 xff0c 所以使用上拉电阻 当总线空闲的时候 都是输出
  • java代码自动生成一(freemarker)

    size 61 large 网上有很多代码自动生成工具 xff0c 如abator和hibernate xff0c 这些工具虽好 xff0c 却没有源码 xff0c 不能修改模板 xff0c 让人很不爽 我刚毕业的时候 xff0c 项目经理
  • linux内核 2.6.35下的驱动例子

    创建 设备节点 mknod dev hello c 字符设备 或者b xff08 块设备 xff09 250 1 查看 cat proc devices 当前设备节点 insmod 安装 rmmod 删除 编译 Makefile 1 需要配
  • E:Could not get lock /var/lib/apt/lists/lock - open (11: Resource temporarily unavailable)

    出现这个问题的原因可能是有另外一个程序正在运行 xff0c 导致资源被锁不可用 而导致资源被锁的原因 xff0c 可能是上次安装时没正常完成 xff0c 而导致出现此状况 解决方法 xff1a 输入以下命令 sudo rm var cach
  • shell 脚本中的引用问题

    原始代码如下 bin sh myvar 61 34 Hello world 34 echo myvar echo 34 myvar 34 echo 39 myvar 39 echo myvar echo Enter some test re
  • Linux内核的TCP源码入门(一)

    文章目录 前言一 TCP报文段结构1 报文段整体结构2 TCP首部 固定部分3 TCP首部 选项 options 二 TCP接收和发送数据1 TCP的 34 接口 34 2 发送数据3 接收数据3 1 ip层向上调用INET Socket层
  • 【API接口工具】postman-Windows版、Linux安装

    Windows安装 Postman 适用于 Windows 7 及更高版本 下载最新的 Postman 版本 选择并运行该 exe文件以安装 Postman Postman v9 4 是 Postman 的最后一个版本 xff0c 同时支持
  • 四轴飞控DIY调试起飞简明步骤

    四轴飞控DIY调试起飞简明步骤 调试起飞简明步骤Step1 xff1a 飞控配置Step2 xff1a 试飞目标测试内容坐标系 Step3 xff1a 试飞方法1 升降 xff08 Throttle xff09 2 偏航 xff08 yaw
  • PX4模块设计之二十七:LandDetector模块

    PX4模块设计之二十七 xff1a LandDetector模块 1 LandDetector模块简介2 模块入口函数2 1 主入口land detector main2 2 自定义子命令custom command 3 LandDetec
  • 穿越机用途和机架尺寸

    穿越机用途和机架尺寸 1 穿越机的用途2 穿越机的机架3 机架的类型3 1 正X型机架3 2 宽X型机架3 3 长X型机架3 4 Hybrid机架3 5 涵道机架 4 总结 1 穿越机的用途 穿越机按功能分 xff0c 主要分为竞速Race
  • 关于穿越机FPV视频果冻效应的讨论

    关于穿越机FPV视频果冻效应的讨论 1 名词定义2 摄像原理2 1 快门分类2 2 常见传感器2 3 卷帘拍摄 3 产生原因4 解决方法4 1 振动出处4 2 软件方法 辅助作用 4 3 硬件方法 直接办法 5 F450试验机FPV视频问题
  • 四轴飞控DIY Mark4 - 减震

    四轴飞控DIY Mark4 减震 1 DIY Mark42 改进事项2 1 Mark4 5 inches机架2 2 2205 2450KV 无刷电机2 3 电机与机架的TPU防震2 4 飞控防震垫圈2 5 三叶平衡桨 3 试飞效果3 1 视
  • Java的压力测试工具之Jmeter

    size 61 large Apache JMeter是Apache组织开发的基于Java的压力测试工具 用于对软件做压力测试 xff0c 它最初被设计用于Web应用测试但后来扩展到其他测试领域 它可以用于测试静态和动态资源例如静态文件 J
  • 四轴飞控DIY Mark4 - 整理&参数优化

    四轴飞控DIY Mark4 整理 amp 参数优化 1 历程2 参数优化2 1 固件BF4 3 12 2 动态怠速值2 3 滤波参数2 4 电调PWM频率2 5 GPS高度配置2 6 返航速度和高度2 7 线性推力修正2 8 图传频道调整
  • ArduPilot开源飞控系统之简单介绍

    ArduPilot开源飞控系统之简单介绍 1 源由2 了解 amp 阅读2 1 ArduPilot历史2 2 关于GPLv32 3 ArduPilot系统组成2 4 ArduPilot代码结构 3 后续3 1 DIY F4503 2 软件设
  • ArduPilot Kakute F7 AIO DIYF450 之GPS配置

    ArduPilot Kakute F7 AIO DIYF450 之GPS配置 1 源由2 步骤2 1 模块预测试2 2 物理连接2 3 UART配置2 4 Compass使能2 5 GPS使能2 6 校准Compass 3 GPS amp
  • ArduPilot之开源代码框架

    ArduPilot之开源代码框架 1 系统框架2 工程框架2 1 工程目录2 2 代码组成2 3 运行流程 4 硬件传感器总线4 1 I2C4 2 SPI4 3 UART4 4 CAN 5 软件设计概念6 总结7 参考资料 在研读ArduP
  • COPY 一种接近最优的导航网格生成算法以及基于导航网格的寻路算法

    提出背景 xff1a 长距离寻路会出现掉帧现象 xff0c 为了提高寻路速度 xff0c 并为3D环境中的寻路方案提供基础算法实现 目前状况 xff1a 由于3D游戏对帧率要求很高 xff0c 而在游戏中进行一次长距离的寻路可能要花费8 1
  • 解析串口-接收完整数据帧

    在linux下编写串口通讯程序 xff0c 采用select监听串口的可读事件 xff0c 一旦可读 xff0c 调用read 但是我们会发现 xff0c read一次得到的数据通常不是完整的一个数据帧 比如完整数据帧为 但是实际上需要re