用C解析和读取数据帧?

2023-12-15

我正在编写一个从Linux上的串口读取数据的程序。 数据由另一台设备发送,帧格式如下:

|start | Command | Data               | CRC  | End |
|0x02  | 0x41    | (0-127 octets)     |      | 0x03|
----------------------------------------------------

数据字段包含 127 个八位位组,如图所示,八位位组 1,2 包含一种类型的数据;八位位组 3,4 包含另一个数据。我需要获取这些数据

我知道如何在Linux中向串行端口写入和读取数据,但这只是写入和读取一个简单的字符串(例如“ABD”)

我的问题是我不知道如何解析上述格式的数据帧,以便我可以:

  • 获取数据字段中八位字节 1,2 中的数据
  • 获取Data字段中八位字节3,4的数据
  • 获取CRC字段的值来检查数据的一致性

下面是在 Linux 中从串行端口读取和写入简单字符串的示例片段代码:

int writeport(int fd, char *chars) {
    int len = strlen(chars);
    chars[len] = 0x0d; // stick a <CR> after the command
    chars[len+1] = 0x00; // terminate the string properly
    int n = write(fd, chars, strlen(chars));
    if (n < 0) {
        fputs("write failed!\n", stderr);
        return 0;
    }
    return 1;                                                                                                           
}

int readport(int fd, char *result) {
    int iIn = read(fd, result, 254);
    result[iIn-1] = 0x00;
    if (iIn < 0) {
        if (errno == EAGAIN) {
            printf("SERIAL EAGAIN ERROR\n");
            return 0;
        } else {
            printf("SERIAL read error %d %s\n", errno, strerror(errno));
            return 0;
        }
    }                    
    return 1;
}

有人有什么想法吗?


result是一个数组chars,1 个八位位组宽。

读取八位字节n use:

char octet_n = result[n];

因此,要做你想做的事,你需要:

// skip the start and command fields
char *data_field = result + 2; 

int octet_1_2 = data_field[1] | (data_field[2] << 8);
int octet_3_4 = data_field[3] | (data_field[4] << 8);

// crc is at byte 128 + 2 = 130
int crc = result[130];

Edit:这一行的解释:

int octet_1_2 = data_field[1] | (data_field[2] << 8);

您想要将两个连续的八位字节读入一个 16 位字:

            1
       bits 5        8 7       0
            --------------------
octet_1_2 = | octet 2 | octet 1|
            --------------------

所以你想取出八位字节 1 的位 7:0 并将它们放入octet_1_2:

octet_1_2 = data_field[1];

然后你想取出八位位组 2 的位 7:0 并将它们放入八位位组 2 的位 15:8 中octet_1_2。您可以通过将八位字节 2 8 位向左移动来完成此操作,并且OR将结果代入octet_1_2:

octet_1_2 |= data_field[2] << 8;

这两行可以合并为一行,就像我上面所做的那样。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用C解析和读取数据帧? 的相关文章

随机推荐

  • log4net.ThreadLogicalContext 和 log4net.ThreadContext 有什么区别

    不太明白官方文档的解释 逻辑线程可以从一个托管线程跳转到另一个托管线程 ThreadContext 和 ThreadLogicalContext 有什么区别 有人可以详细说明一下吗 Thanks 我应该回去并将其添加到我自己的问题中 Ste
  • 无法导入/配置 Qt 项目

    我已将以下 GitHub 项目克隆到我的硬盘上 https github com leozide leocad 我还安装了 Qt Creator 4 5 0 但是 当我尝试在 Qt Creator 中加载项目时 它说没有有效的 套件 并且不
  • 实现 PCIe Linux 设备驱动程序(想要从内核驱动程序访问我的卡寄存器)

    我正在编写一个设备驱动程序来访问 PCIe 卡上 FPGA 中的内存 该卡启动并被探测 发现 proc iomem 80000000 840fffff PCI Bus 03 80000000 83ffffff 0000 03 00 0 84
  • 也许使用 JOIN 选择 65 年内的日期范围?

    我正在尝试在 PHP 发布脚本上提取查询 该脚本将提取信息 SELECT id FROM leads WHERE status Passed AND campaign id 22d0cf4f 0f81 28b1 d8dc 4f046bd1d
  • 移动菜单打开和关闭按钮在 Chrome 中显示,但在 Safari 中不显示

    我们的移动菜单在 Pixel 5 上的 Chrome 和 Firefox 中运行良好 在 iPhone 5s 我唯一的 iPhone iPad Mini 2 和较旧的 iPad 上 汉堡菜单打开和关闭图标不显示 在 Chrome 和 Fir
  • 如何从 Android Studio 手动重启 ADB

    我之前在 Android Studio 上开发过 Android 应用程序 一切正常 我在真实设备上工作 Android Studio 可以毫无问题地识别它 突然 当我退出 android studio 并断开连接并重新连接我的设备时 它不
  • 使用鼠标位置旋转玩家的功能是基于鼠标距离而不是位置

    我遵循了 Unity 论坛上关于如何根据鼠标位置旋转对象的答案 该代码可用于更改旋转 但它使用一些其他参数来旋转对象 如您在本记录中看到的 这是我的鼠标检测和位置编辑代码 来自Game cs s update 功能 playerLocati
  • java.lang.illegalargumentexception url 中存在非法字符

    我想请求网络服务我的参数是这样的 urlString http ip autodownload andro php key apps apk 2 bla bla bla public void getRequest String Url T
  • 如何在不改变IGrouping类型的情况下对它进行排序?

    我有一个 IGrouping 类型的对象 并且希望在不更改对象类型的情况下对组内的元素进行排序 换句话说 我有 var tmp group OrderBy x gt x with group存在类型IGrouping
  • 从 Firebase 中删除特定用户

    有没有办法从 firebase 获取特定用户帐户然后将其删除 例如 I need a means of getting a specific auth user var user firebase auth getUser uid Note
  • Objective-C 中的鼠标按下事件

    我知道这个问题以前被问过很多次 但对我来说没有任何作用 下面的代码根本不会做任何事情 void mouseDown NSEvent event NSLog It worked 我尝试了很多不同的方法来使其发挥作用 包括创建自定义NSEven
  • typedef 模板声明的替代方案

    我正在努力实现 namespace NTL typedef std valarray vector 通过标准 C 我知道这是不允许的 但我需要一种快速且简单的方法 无需重新实现所有函数 运算符 重载等 来获取模板 typedef 我现在正在
  • 如何使用 C# 从 URL 下载 ZIP 文件?

    我想从某个网址下载 ZIP 文件 当我打开浏览器并输入 URL 时 浏览器会直接开始下载 ZIP 文件 但是我想要的是使用 C 代码自动执行此操作 我尝试过以下代码 private void btnDownload Click object
  • python 绘制多重图

    我尝试使用 graphviz 在 Python 中绘制多重图 现在我可以用 Python 绘制常用的图表 如下所示 import pygraphviz as pgv G pgv AGraph G add node a G add node
  • 空手道-如何仅在失败的情况下自动重新运行[重复]

    这个问题在这里已经有答案了 空手道中是否有任何方法可以在同一执行中自动仅重新运行 UI 测试自动化失败的场景 甚至在 API 中 我使用 gradle 作为构建工具 这是我这边的要求 如果任何测试失败 应该再次重试 如果我们可以在每个功能场
  • Firestore - 使用数组添加对象

    一整天都在这里用这个东西自杀 我正在上两门课 系和文章 export class Department articals Artical moms number id string constructor and export class
  • 如何使用 jQuery 获取、操作和替换文本节点?

    这是我的代码 li class det price a href designer customize 278258 dpid 1 Printing a from 10 li 我在任何给定页面上都有大约十五个这样的块 我想获取文本节点 来自
  • 从 ANT 启动 Eclipse 运行配置

    我正在将 Orion 服务器用于基于 Java 的 Web 应用程序 我有一个运行配置 可以使用正确的类路径和所有必要的配置启动 Orion 我还有几个 ANT 脚本用于将文件复制到构建路径 我想创建一个 ANT 脚本来关闭 Orion 复
  • 如何用Python从LDA模型生成词云?

    我正在对报纸文章进行一些主题建模 并使用 Python3 中的 gensim 实现了 LDA 现在我想为每个主题创建一个词云 使用每个主题的前 20 个单词 我知道我可以打印单词 并保存 LDA 模型 但是有没有办法只保存每个主题的顶部单词
  • 用C解析和读取数据帧?

    我正在编写一个从Linux上的串口读取数据的程序 数据由另一台设备发送 帧格式如下 start Command Data CRC End 0x02 0x41 0 127 octets 0x03 数据字段包含 127 个八位位组 如图所示 八