linux c串口应用编程,参照golang里面的json.Marshal/json.Unmarshal

news/2024/12/5 17:07:44/

protocol.h代码:

root@iZwz99zhkxxl5h6ecbm2xwZ:~/serial-ipc# cat protocol.h 
#ifndef __PROTOCOL_H__
#define __PROTOCOL_H__#include <stdint.h>
#include <stdbool.h>enum PACKAGE_TYPE {TYPE_HEART_BEAT = 0x01,TYPE_SOMKE = 0x02,
};typedef struct __package {uint8_t type;                // 命令类型uint8_t waterNum;            // 流水号,递增,避免命令重传时重复执行uint8_t checksum;            // crcuint8_t len;                 // 内容长度//void * content;uint8_t content[256];        256byte足够串口使用,如果高波特率,请用上面的*content和malloc/free
} uart_pack;extern bool marshal(uint8_t * buf, uint8_t len, uart_pack * packObj);
extern bool unmarshal(uint8_t * buf, uint8_t len, uart_pack * packObj);
extern void packageSchedule(uart_pack * packObj);#endifroot@iZwz99zhkxxl5h6ecbm2xwZ:~/serial-ipc#

protocol.c 代码,实现二进制流序列化、反序列化。

root@iZwz99zhkxxl5h6ecbm2xwZ:~/serial-ipc# cat protocol.c 
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "protocol.h"bool marshal(uint8_t * buf, uint8_t len, uart_pack * packObj)
{/*if (len < sizeof(uart_pack) + packObj->len) {printf("package head fail\r\n");return false;}*/buf[0] = packObj->type;buf[1] = packObj->waterNum;buf[2] = packObj->checksum;buf[3] = packObj->len;if (packObj->len) {memcpy(&buf[4], packObj->content, packObj->len);}return true;
}bool unmarshal(uint8_t * buf, uint8_t len, uart_pack * packObj)
{/*if (len < sizeof(uart_pack) + packObj->len) {return false;}*/packObj->type = buf[0];packObj->waterNum = buf[1];packObj->checksum = buf[2];packObj->len = buf[3];if (packObj->len) {memcpy(packObj->content, &buf[4], packObj->len);}return true;
}void packageSchedule(uart_pack * packObj)
{switch (packObj->type) {case TYPE_HEART_BEAT:printf("received one heart beat package\r\n");break;case TYPE_SOMKE:printf("received one smoke package\r\n");break;default:break;}
}root@iZwz99zhkxxl5h6ecbm2xwZ:~/serial-ipc#

main.c代码:

root@iZwz99zhkxxl5h6ecbm2xwZ:~/serial-ipc# cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
#include <signal.h>
#include <sys/select.h>#include "protocol.h"#define SERIAL_PORT "/dev/ttyUSB0"  // 替换为您的串口设备
//#define SERIAL_PORT "/dev/ttyCH341USB0"  // 替换为您的串口设备
#define BUFFER_SIZE 256volatile sig_atomic_t stop = 0;void sigint_handler(int signum) {stop = 1;
}int main() {int serial_fd;struct termios serial_options;fd_set rfds;struct timeval tv;int retval;char buffer[BUFFER_SIZE];int n;// 打开串口serial_fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);if (serial_fd == -1) {perror("Failed to open serial port");return -1;}// 配置串口选项tcgetattr(serial_fd, &serial_options);		// 读取串口默认配置cfsetispeed(&serial_options, B115200);		// set io speedcfsetospeed(&serial_options, B115200);//serial_options.c_cflag |= (CLOCAL | CREAD);serial_options.c_cflag &= ~CSIZE;serial_options.c_cflag |= CS8;serial_options.c_cflag &= ~PARENB;serial_options.c_cflag &= ~CSTOPB;// 设置最少字符和等待时间serial_options.c_cc[VMIN] = 1;     // 读数据的最小字节数serial_options.c_cc[VTIME]  = 0;   //等待第1个数据,单位是10sserial_options.c_cflag &= ~CRTSCTS;serial_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);serial_options.c_iflag &= ~(IXON | IXOFF | IXANY);serial_options.c_oflag &= ~OPOST;tcsetattr(serial_fd, TCSANOW, &serial_options);signal(SIGINT, sigint_handler);while (!stop) {FD_ZERO(&rfds);FD_SET(serial_fd, &rfds);tv.tv_sec = 5;tv.tv_usec = 0;// 使用 select 等待串口可读retval = select(serial_fd + 1, &rfds, NULL, NULL, &tv);if (retval == -1) {perror("Select error");break;}else if (retval) {	printf("Data is available now.\n");/* FD_ISSET(0, &rfds) will be true. */if (FD_ISSET(serial_fd, &rfds)) {n = read(serial_fd, buffer, BUFFER_SIZE);if (n > 0) {buffer[n] = '\0';printf("Received: %s\n", buffer);write(serial_fd, "ack:", 3);write(serial_fd, buffer, n);uart_pack packObj;bool ret = unmarshal(buffer, n, &packObj);if (ret) {packageSchedule(&packObj);}}}}else {printf("No data within five seconds.\n");		}}// 关闭串口close(serial_fd);return 0;
}
root@iZwz99zhkxxl5h6ecbm2xwZ:~/serial-ipc#

Makefile

root@iZwz99zhkxxl5h6ecbm2xwZ:~/serial-ipc# cat Makefile .PHONY:allall:gcc -g main.c protocol.c -o uart-ipcclean:rm -rf uart-ipc
root@iZwz99zhkxxl5h6ecbm2xwZ:~/serial-ipc# 

http://www.ppmy.cn/news/1551281.html

相关文章

C语言实现冒泡排序:从基础到优化全解析

一、什么是冒泡排序&#xff1f; 冒泡排序&#xff08;Bubble Sort&#xff09;是一种经典的排序算法&#xff0c;其工作原理非常直观&#xff1a;通过多次比较和交换相邻元素&#xff0c;将较大的元素“冒泡”到数组的末尾。经过多轮迭代&#xff0c;整个数组会变得有序。 二…

架构-微服务-服务配置

文章目录 前言一、配置中心介绍1. 什么是配置中心2. 解决方案 二、Nacos Config入门三、Nacos Config深入1. 配置动态刷新2. 配置共享 四、nacos服务配置的核心概念 前言 服务配置--Nacos Config‌ 微服务架构下关于配置文件的一些问题&#xff1a; 配置文件相对分散。在一个…

【计算机操作系统】操作系统引论(学习笔记)

目录 操作系统的目标和作用 目标 作用 操作系统的发展过程 单道批 多道批 分时系统 实时系统 微机操作系统 嵌入式操作系统​编辑 网络操作系统​编辑 分布式操作系统 操作系统的基本特性 并发 共享 虚拟 异步 操作系统的运行环境 操作系内核​ 处理机的双…

你的网站真的安全吗?如何防止网站被攻击?

你的网站被黑客攻击过&#xff0c;很可能不止一次&#xff01; 这可不是危言耸听。微软最近发布了《2024 年微软数字防御报告》&#xff0c;报告中写到&#xff1a;“Windows 用户每天面临超过 6 亿次网络犯罪和国家级别的攻击&#xff0c;涵盖了从勒索软件到网络钓鱼再到身份…

DevExpress的web Dashboard应用

本文旨在从零开始创建一个包含dashboard的应用 一、前期准备 1、语言&#xff1a;C# 2、软件&#xff1a;Visual Studio 2019 3、框架&#xff1a;DevExpress19.2(付费)、ASP.NET(Web) 4、组件&#xff1a;dashboard 二、创建ASP.NET Web窗体仪表板应用程序 1、创建一个空的w…

istio中wasm插件是做什么的?

在 Istio 中&#xff0c;WASM 插件 是用来扩展和自定义数据平面&#xff08;即 Envoy Proxy&#xff09;行为的一种机制。它允许用户以更灵活、更高效的方式增强流量处理能力&#xff0c;而不需要修改 Envoy 的源码。以下是它的主要功能和应用场景&#xff1a; 1. 增强 Envoy …

Ubuntu WiFi检测

ubuntu检测到多个同名wifi&#xff0c;怎么鉴别假冒的wifi&#xff1f; 在Ubuntu中&#xff0c;如果检测到多个同名的Wi-Fi网络&#xff0c;可能存在假冒的Wi-Fi&#xff08;例如“蜜罐”攻击&#xff09;。以下是一些鉴别假冒Wi-Fi的方法&#xff1a; 检查信号强度&#xff1a…

Spring Cloud Gateway API 网关

Spring Cloud Gateway API 网关 一、Spring Cloud Gateway1.API 网关2.Gateway 核心概念3.工作流程 二、Gateway 路由1.断言 Predicate(1) 定义与作用(2) Route Predicate 工厂 2.动态路由 三、Gateway 过滤器1.局部过滤器(1) GatewayFilter 工厂 2.全局过滤器 一、Spring Clou…