Linux串口断帧和连帧处理

Linux环境下使用interrupt方式操作UART 本文介绍Linux环境下使用interrupt方式操作UART的方法,实现了串口打开,关闭,发送数据,接收数据功能,还编写测试代码,验证该功能。 阅读详情

报文格式:

字段长度(字节)说明
STX        1开始控制字符 0x02
数据长度2传输时需要转换成INTEL序(高字节在前)数据体部分长度。最大允许值为:4096
数据体不定由数据长度决定
校验字节1校验字节是报文中除通信控制字符之外所有数据的校验和
ETX1结束控制字符 0x03

断帧和连帧处理:

通过宏BROKEN_FRAME可以控制断帧测试或是连帧测试 ,代码中有详细注释说明

#include <stdio.h>
#include <string.h>
#include <stdint.h>

//最大缓存区
#define MAX_BUFFER_SIZE 4096

//帧格式
typedef struct {
    unsigned char start;
    unsigned short length;
    unsigned char data[MAX_BUFFER_SIZE/4];
    unsigned char checksum;
    unsigned char end;
} Frame;

//定义缓存区和缓存区当前索引
unsigned char buffer[MAX_BUFFER_SIZE];
int bufferIndex = 0;

//打印hex数据
void print_mesg(char *head, unsigned char *data, int len)
{
        printf("%s", head);
        for(int i=0; i<len; i++)
        {
                printf("%02X ",data[i]);
        }
        printf("\n");
}

/**
 * 返回单字节校验和
 */
unsigned char GetCheckSum(unsigned char *data, uint32_t data_size)
{
        int i = 0;
        uint32_t temp = 0;
        uint8_t sum = 0;
        for(i = 0;i<data_size;i++)
        {
                temp += *(data+i);
        }
        sum = temp&0xff;
        return sum;
}

//接收数据处理
void processFrame(Frame frame) {
    // 在这里处理接收到的帧数据
    // 可以根据具体需求对数据进行解密、校验等操作
    // 例如,可以打印数据体内容
    print_mesg("Received data:", frame.data, frame.length);
}

//接收数据放到缓存区
void addToBuffer(unsigned char *data, int data_len) {
    // 将帧数据添加到缓存区
        if((bufferIndex+data_len) > MAX_BUFFER_SIZE)
        {
                bufferIndex = 0;
                memset(buffer, 0, MAX_BUFFER_SIZE);
                return;
        }
    memcpy(&buffer[bufferIndex],data, data_len);
    bufferIndex += data_len;
}

//解析帧
void parseFrame(unsigned char* data, int length) {
    printf("length=%d\n",length);
    print_mesg("Received:", data, length);
    Frame frame;
    memset(&frame, 0, sizeof(Frame));
    addToBuffer(data, length);

    int dataIndex = 0;
    while (bufferIndex > 5) {
        if (buffer[dataIndex] != 0x02) {
            // 数据起始标志错误,丢弃当前帧
                        dataIndex++;
                        continue;
        }
        printf("dataIndex=%d\n",dataIndex);

        if (bufferIndex - dataIndex < 5) {
            // 数据长度不足,无法解析帧
            break;
        }

        frame.start = buffer[dataIndex];
        frame.length = (buffer[dataIndex + 1] << 8) | buffer[dataIndex + 2];

        if (bufferIndex - dataIndex < frame.length + 5) {
            // 数据长度不足,无法解析帧
            break;
        }

        memcpy(frame.data, buffer + dataIndex + 3, frame.length);
        frame.checksum = buffer[dataIndex + frame.length + 3];
        frame.end = buffer[dataIndex + frame.length + 4];

        // 检查校验和
        unsigned char checksum = GetCheckSum(&buffer[dataIndex+1], frame.length+2);
                printf("checksum:%02X\n",checksum);
                printf("frame.checksum:%02X\n",frame.checksum);
                printf("frame.end:%02X\n",frame.end);
                print_mesg("data:", frame.data, frame.length);

        if (checksum != frame.checksum || frame.end != 0x03) {
            // 校验和或控制字符错误,丢弃帧
            dataIndex++;
            continue;
        }

        processFrame(frame);

        dataIndex += frame.length + 5;
        bufferIndex -= dataIndex;
        memmove(buffer,buffer+dataIndex,bufferIndex);
        dataIndex=0;
    }
}

//是否断帧
#define BROKEN_FRAME 1

int main() {
    //0xFF为干扰字符
    unsigned char receivedData1[] = {0xFF,0x02, 0x00, 0x13, 0x10, 0x02, 0x00, 0x01, 0x32, 0x30, 0x32, 0x33, 0x31, 0x31, 0x30, 0x32, 0x31, 0x39, 0x35, 0x38, 0x30, 0x33, 0x02, 0xED, 0x03};
    //0xFF为干扰字符
    unsigned char receivedData2[] = {0x02, 0x00, 0x13, 0x10, 0x02, 0x00, 0x01, 0x32, 0x30, 0x32, 0x33, 0x31, 0x31, 0x30, 0x32, 0x31, 0x39, 0x35, 0x38, 0x30, 0x33, 0x02, 0xED, 0x03, 0xFF, 0x02, 0x00, 0x13, 0x50, 0x01, 0x00, 0x01, 0x62, 0x77, 0x74, 0x32, 0x31, 0x30, 0x38, 0x38, 0x32, 0x30, 0x34, 0x30, 0x31, 0x01, 0x00, 0xad, 0x03, 0x02, 0x00, 0x13, 0x50, 0x01, 0x00, 0x01, 0x62, 0x77, 0x74, 0x32, 0x31, 0x30, 0x38, 0x38, 0x32, 0x30, 0x34, 0x30, 0x31, 0x01, 0x00, 0xad, 0x03};

    int receivedLength1 = sizeof(receivedData1) / sizeof(receivedData1[0]);
    int receivedLength2 = sizeof(receivedData2) / sizeof(receivedData2[0]);
#if BROKEN_FRAME  //断帧处理
    parseFrame(receivedData1, receivedLength1-10);
    parseFrame(receivedData1+receivedLength1-10, 5);
    parseFrame(receivedData1+receivedLength1-5, 5);
#else            //连帧处理
    parseFrame(receivedData2, receivedLength2);
#endif
    return 0;
}

如果不需要连帧处理,仅仅简单的断帧处理可参考下面博文

Linux串口断帧处理-优快云博客

Linux 8250串口控制器 阅读详情

相关推荐

linux中断的实现

linux中断的实现

hqb_newfarmer的博客 837

Linux:TTY串口接收中断

Linux:TTY串口接收中断

xikangsoon的博客 2726

arm板linux串口数据接收一帧

linux系统下串口数据接收一帧,采用select接收,超时检测,为保证准确性发送间隔必须大于20ms(数据量越大间隔必须越大),实测没发现问题,如发现问题欢迎交流指正

linux 中串口操作之中断 读取

1.windows端使用虚拟串口,通过串口工具发送消息。工具:vspd ,eclipse,串口调试助手。2.linux端,使用此代码读取。

m0_59824404的博客 1455

winpcap无法安装提示新版本已经安装解决办法

问题显示如下该问题会导致ensp里的云识别不到网卡可能是因为之前安装了npcap,而且安装时勾选了第四个选项导致无法安装,需要完全卸载npcap解决办法:办法一:在控制面板的程序与卸载里面卸载npcap和winPcap,然后再安装winPcap,如果搜不到往下看办法二:在C:\Windows\SysWOW64目录下搜索wpcap.dll和packet.dll并重命名为wpcap.dll.old和packet.dll.old办法三:如果搜不到这两个文件需要安装win10Pcap才能找到这两个文件下载地址:Wi

qq_73202377的博客 3万+

【XR硬件介绍】PICO Space Pro(Project Swan)深度解析:字节 2026 旗舰 MR 头显延期背后

内部代号 Project Swan 的 PICO 年度旗舰 MR 头显正式定名PICO Space Pro,原本计划 2026 年 9 月对外发布,官方官宣推迟至 2026 年第四季度上市。硬件层面已经完成 FCC 认证,硬件成熟度较高,延期核心目标是打磨 PICO OS 6 空间操作系统,补齐空间计算软件能力。本文从产品背景、硬件架构、软件生态、延期逻辑、行业竞争格局几个维度拆解这款国产高端 MR 设备,分析它对国内 XR 产业的意义与待解的问题。

houdou112358的博客 1166

QCustomPlot实时曲线优化-子线程渲染与采集线程解耦

在ARM无GPU环境下,18通道实时曲线因QCustomPlot同步重绘导致卡顿、线条坑洼与数据尖刺。解决方案:将渲染解耦为子线程QImage绘制+GUI线程贴图,实现帧级合并;启用抗锯齿与圆角连接优化视觉;并将串口采集链移至独立线程,通过时间戳隔离数据与界面,彻底消除UI卡顿对数据流的污染,显著提升流畅性与稳定性。

小王的博客 322

【论文笔记】Reaching agreement in the presence of faults (EIG)

1 问题定义 2 交互一致性 3 单点故障 m=1 n=4 4 多点故障(n&amp;gt;=3m+1) 计算过程 m=2 n=7 5 n&amp;lt;3m+1不能达成协定 6 带认证的算法 7 总结 这篇论文在1980年发表,是1982年著名的拜占庭将军问题论文的前身。作者Leslie Lamport是2013图灵奖得主,两篇论文引用次数分别为5000+和2000+。该论文提出的算法现在被...

zjwreal 2993

树莓派+CAN总线读取汽车VIN码实战指南

VIN码是车辆唯一身份标识,其获取本质是基于CAN总线的底层诊断协议交互。理解OBD-II协议栈(物理层、数据链路层、网络层、应用层)与ISO 15031/SAE J1979标准,是实现稳定读取的前提。技术价值在于摆脱云端依赖和蓝牙狗不确定性,通过SocketCAN直接操控CAN帧,达成零丢帧、低延迟、高兼容的确定性通信。典型应用场景包括车队VIN自动录入、二手车真伪校验及车载协议逆向分析。本文聚焦Linux嵌入式环境下的VIN读取全链路实现,涵盖硬件选型(MCP2515)、内核配置、手写CAN帧、三帧拼接

weixin_34284188的博客 377

V-REP(Cooprliesim EDU)自学笔记 实现UR5机械臂末端按轨迹移动

V-REP(Cooprliesim EDU)自学笔记 实现UR5机械臂末端按轨迹移动

xu_white的博客 7583

微信内置浏览器抓包全攻略:从ADB配置到Chrome调试(附常见问题解决)

本文提供了一套完整的微信内置浏览器抓包与调试解决方案。从ADB工具的深度配置与稳定性连接开始,详细讲解了如何开启X5内核调试开关,并利用Chrome DevTools建立远程连接。文章重点剖析了Network面板进行网络请求抓取、性能分析和问题定位的实战技巧,并附带了设备连接失败、无网络请求等常见问题的排查指南,帮助开发者高效解决微信H5页面调试难题。

gitlab7runner的博客 541

linux串口帧过滤,【HAL库】串口数据帧接收与分析处理算法

基于对串口FIFO的通信数据帧进行接收和分析处理(关于串口FIFO使用可以参见作者另一篇博文)算法流程:串口中断函数接收数据到FIFO。根据通信协议GetInterUARTMessage()函数对数据帧进行判断获取。根据通信协议AnalyzeInterUARTMessage()函数对数据帧进行分类处理。重点分析:memcmp()函数:对数据帧类别进行判断,并做后续处理。变量ucInterHead ...

weixin_36104484的博客 520

矢量网络分析仪(矢网)组成和原理简介

一、概述 矢量网络分析仪是一种常见的射频测量仪器,主要用来测量高频器件、电路及系统的性能参数,如线性参数、非线性参数、变频参数等。 1.1 分类 矢量网络分析仪一般以频率来划分,截止频率越高,价格也越贵; 根据测试端口的数量可分为:双端口、 3 端口、 4 端口、 6 端口; 常见的厂家有:美国的安捷伦( Agilent)、德国的罗德与施瓦茨( R&S) , 国内的有南京普纳和中电 41 所。 1.2 常用功能 常用的测试器件有:功分器、合路器、滤波器、衰减器、天线、电缆、放大器、混频器、双工器、耦

大音希声 5万+

Linux串口信号中断

/使能数据接收和本地模式。信号处理函数,设备wait_flag=FASLE。//2.备份现有的串口配置。//1.打开串口设备文件。//5.设置控制标志。//7.设置阻塞模式。//8.使能配置生效。

weixin_51971725的博客 798

漏洞挖掘之工具配置

本文主要讲解burp工具的插件安装。

qq_64775230的博客 3273

基于物联网设计的蜂箱智能监测系统设计

为解决传统养蜂业依赖人工、管理效率低下、干扰蜂群等问题,本项目设计并实现了一套基于物联网(IoT)的蜂箱智能监测系统。

682

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

在linux下编写串口通讯程序,采用select监听串口的可读事件,一旦可读,调用read。但是我们会发现,read一次得到的数据通常不是完整的一个数据帧。比如完整数据帧为但是实际上需要read多次才能完全读到。程序实际运行情况:两次读完:四次读完:为了解决不能接收完整数据帧的问题,借鉴了网友的例子,并进行了一些改动:现在的效果:下面是程序代码:#include "smartlight.h"int

lucifer_凡 2万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

linux 串口 帧头,串口有帧头帧尾的解码

串口有帧头帧尾的解码发布时间:2018-11-13 00:53,浏览次数:463<>AT指令编解码-有帧头帧尾的编解码参考:https://www.cnblogs.com/chucklu/p/6428615.html#include #include #define MAX_SIZE 1024 int bw_getFrame(unsigned char *buf, int len)...

weixin_35897916的博客 963

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Linux应用层例程4 串口应用编程

在串口终端的原始模式下,使用串口进行数据传输,包括通过串口发送数据、以及读取串口接收到的数据,并将其打印出来。循环,这是对用户传参进行了解析,我们这个应用程序设计的时候,允许用户传入相应的参数,譬如用户可以指定串口终端的设备节点、串口波特率、数据位个数、停止位个数、奇偶校验等,具体的使用方法,大家可以看一看 show_help()同理,串口也作为系统的标准输入设备,用户通过串口与 Linux。

internetv的博客 5221

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

linux串口通信协议编程详解

linux串口通信协议编程详解: 1.

sword_fish 1万+

Linux 下串口编程(中断)

Linux 下串口编程的文章网上是满天飞,但大都是出自一篇文章,而且写的都是些基本的操作,像控制 RTS/CTS 等串口引脚状态,接收发送二进制数据等,都没有很好的说明,我在使用中遇到了些问题,写出来,希望能对大家有所帮助,少走弯路,呵呵!       我使用的操作系统是 Redhat9 , gcc 版本是 3.2.2       其实在 linux 下对串口的设置主要是通过 termios 这个

dongliqiang2006的专栏 4028

通用:单片机串口接收如何断帧

串口接收中断断帧是很重要的,那么该如何判断一帧数据是否接受完成呢?常用的两种方法是:时间断帧,我们可以通过在定时器里对两帧数据的时间进行比较,一帧数据里边两个数据的时间差是很短的,如果超过一定时间之后仍旧无心的数据被接收到,那么我们就可以判断为一帧数据结束。协议断帧,这就好比我么两个人约定好数据大致长度,或某个字符出现即为一帧数据的结束,由此可以来进行断帧,判断为一帧数据的接收完成。...

qq_33780106的博客 2712

STM32 RS232串口接收数据帧被拆分问题排查记录

串口通讯主要的难点在于命令帧之间的区分和应答的及时性,此文章就针对这两点进行处理探讨。

weixin_44124535的博客 3277

串口接收中断+空闲中断实现多个数据帧接收与处理

串口不定长度报文接收方法

久久的学习之路 2762
上一篇: QT实现的一个MVP设计模式demo
下一篇: windows上yolov5 opencv dnn c++部署 cuda加速
我是谁??
博客等级 码龄11年 242粉丝 183原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值