C# 一个串口通信的案例实现

通信规格书:

指定页读取规范:

HOST:<LF>RPP1<CR>
Reader:<LF>R<FAIL> <CR><LF> // 读取失败
Reader:<LF>R12345678<CR><LF>// 读取成功

Example:
HOST:0A 52 50 50 31 0D
Reader:0A 52 30 31 32 33 34 35 59 54 0D 0A // 成功
Reader:0A 52 46 41 49 4C 0D 0A // 失败

  1. HOST发送指令

    • HOST通过串口向RFID读写器发送指定页读取的命令。
    • 命令格式为 <LF>RPP1<CR>,其中:
      • <LF> 表示换行符,ASCII码为 0x0A。
      • <CR> 表示回车符,ASCII码为 0x0D。
      • RPP1 表示指定读取第一页的数据。
  2. 读写器响应

    • 如果读写器成功读取了数据,会返回如下格式的响应:
      • <LF>R12345678<CR><LF>,其中:
        • R 是固定的标识符,表示读取操作。
        • 12345678 是具体的数据内容。
        • <LF> 表示换行符。
        • <CR> 表示回车符。
    • 如果读取失败,读写器返回如下格式的响应:
      • <LF>RFAIL<CR><LF>,其中:
        • RFAIL 表示读取失败。

指定页写入规范:

HOST:<LF>WPP1,12345678<CR>
Reader:<LF>W<FAIL> <CR><LF> //写入失败
Reader:<LF>W<OK> <CR><LF> // 写入成功

Example:
HOST:0A 57 50 50 31 2C 31 32 33 34 35 36 37 38 0D
Reader:0A 57 4F 4B 0D 0A // 写入成功
Reader:0A 57 46 41 49 4C 0D 0A // 写入失败

  1. HOST发送指令

    • HOST通过串口向RFID读写器发送指定页写入的命令。
    • 命令格式为 <LF>WPP1,12345678<CR>,其中:
      • <LF> 表示换行符,ASCII码为 0x0A。
      • <CR> 表示回车符,ASCII码为 0x0D。
      • WPP1,12345678 表示写入数据到第一页,数据为 12345678
  2. 读写器响应

    • 如果写入操作成功,读写器会返回如下格式的响应:
      • <LF>W<OK><CR><LF>,其中:
        • W 是固定的标识符,表示写入操作。
        • <OK> 表示写入成功。
        • <LF> 表示换行符。
        • <CR> 表示回车符。
    • 如果写入操作失败,读写器会返回如下格式的响应:
      • <LF>W<FAIL><CR><LF>,其中:
        • W 是固定的标识符,表示写入操作。
        • <FAIL> 表示写入失败。

实现代码类: 

    public class RfidCls : IDisposable{private SerialPort port;private Thread initThread;private readonly object mylock = new object();private string portName = "COM2";private int baudRate = 9600;public bool IsLink { get; private set; }public void Start(string portname, int baudrate){portName = portname;baudRate = baudrate;initThread = new Thread(InitializePort);initThread.Start();}private void InitializePort(){try{if (string.IsNullOrEmpty(portName))throw new ArgumentException("串口参数未设置,请检查!");port = new SerialPort(portName, baudRate){StopBits = StopBits.One,DataBits = 8,Parity = Parity.None};port.Open();if (port.IsOpen){IsLink = true;LogInfo("RFID连接成功");}else{throw new Exception("串口未能成功打开!");}}catch (Exception ex){LogError($"串口连接失败:{ex.Message}");}}public void Close(){try{if (port != null && port.IsOpen){port.Close();LogInfo("RFID连接已关闭");}}catch (Exception ex){LogError($"关闭RFID连接失败:{ex.Message}");}}public bool ReadRFID(int pageIndex, out string pageInfo){pageInfo = null;try{lock (mylock){if (port == null || !port.IsOpen)throw new InvalidOperationException("RFID端口未打开或已关闭");string command = $"RPP{pageIndex + 1}";byte[] commandBytes = ConstructCommand(command, "");port.Write(commandBytes, 0, commandBytes.Length);byte[] responseBytes = ReadResponse();if (responseBytes != null && responseBytes.Length >= 4){byte[] Bytes = responseBytes.Skip(2).Take(responseBytes.Length - 4).ToArray();string response = Encoding.Default.GetString(Bytes);if (response.StartsWith("R")){if (response == "RFAIL"){LogError("读取RFID失败");return false;}else{pageInfo = response.Substring(1);LogInfo($"读取RFID成功:{pageInfo}");return true;}}}LogError("读取RFID未知响应");return false;}}catch (Exception ex){LogError($"读取RFID出错:{ex.Message}");return false;}}public bool WriteRFID(int pageIndex, string hexValue){try{lock (mylock){if (port == null || !port.IsOpen)throw new InvalidOperationException("RFID端口未打开或已关闭");string command = $"WPP{pageIndex + 1},{hexValue}";byte[] commandBytes = ConstructCommand(command, "");port.Write(commandBytes, 0, commandBytes.Length);byte[] responseBytes = ReadResponse();if (responseBytes != null && responseBytes.Length >= 4){byte[] Bytes = responseBytes.Skip(2).Take(responseBytes.Length - 4).ToArray();string response = Encoding.Default.GetString(Bytes);if (response.StartsWith("W")){if ( response == "WOK"){LogInfo("写入RFID成功");return true;}else {LogError("写入RFID失败");return false;}}}LogError("写入RFID未知响应");return false;}}catch (Exception ex){LogError($"写入RFID出错:{ex.Message}");return false;}}private byte[] ConstructCommand(string command, string hexValue){StringBuilder commandHex = new StringBuilder();foreach (char c in command){commandHex.Append(Convert.ToString(c, 16));}string dataHex = hexValue;string fullHex = $"0A{commandHex}2C{dataHex}0D";byte[] commandBytes = new byte[fullHex.Length / 2];for (int i = 0; i < fullHex.Length; i += 2){commandBytes[i / 2] = Convert.ToByte(fullHex.Substring(i, 2), 16);}return commandBytes;}private byte[] ReadResponse(){DateTime startTime = DateTime.Now;byte[] buffer = new byte[1024];int totalBytes = 0;while (DateTime.Now.Subtract(startTime).TotalSeconds < 3){int bytesToRead = port.BytesToRead;if (bytesToRead > 0){if (totalBytes + bytesToRead > buffer.Length)Array.Resize(ref buffer, totalBytes + bytesToRead);totalBytes += port.Read(buffer, totalBytes, bytesToRead);if (totalBytes >= 2&& buffer[totalBytes - 2] == 0x0D&& buffer[totalBytes - 1] == 0x0A){Array.Resize(ref buffer, totalBytes);return buffer;}}else{Thread.Sleep(100);}}return null;}private void LogInfo(string message){// 实现信息日志记录,例如使用日志框架记录到文件或其他存储介质Console.WriteLine($"信息:{message}");}private void LogError(string message){// 实现错误日志记录,例如使用日志框架记录到文件或其他存储介质Console.WriteLine($"错误:{message}");}public void Dispose(){Close();if (initThread != null){initThread.Join(); // 确保线程已终止initThread = null;}if (port != null){port.Dispose(); // 释放串口资源port = null;}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/32141.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WordPress插件:子比zibll主题插件 炙焰美化全开源插件V3.2

在网络世界中&#xff0c;开源内容管理系统&#xff08;CMS&#xff09;已经成为了网站构建的关键工具之一。WordPress&#xff0c;作为最受欢迎的开源CMS之一&#xff0c;其广泛的应用及其灵活性使得它成为了创建和管理各种类型网站的理想选择。而Zibll主题插件&#xff0c;作…

IOS Swift 从入门到精通:闭包 第一部分

文章目录 创建基本闭包在闭包中接受参数从闭包返回值闭包作为参数尾随闭包语法 创建基本闭包 Swift 允许我们像使用字符串和整数等其他类型一样使用函数。这意味着您可以创建一个函数并将其分配给一个变量&#xff0c;使用该变量调用该函数&#xff0c;甚至可以将该函数作为参…

【Android WebView】WebView基础

一、简介 WebView是一个基于webkit引擎、展现web页面的控件。Android的Webview在低版本和高版本采用了不同的webkit版本内核&#xff0c;4.4后直接使用了Chrome。 二、重要类 以WebView类为基础&#xff0c;WebSettings、WebViewClient、WebChromeClient为辅助共同完成安卓段加…

2024年【T电梯修理】免费试题及T电梯修理考试总结

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 T电梯修理免费试题参考答案及T电梯修理考试试题解析是安全生产模拟考试一点通题库老师及T电梯修理操作证已考过的学员汇总&#xff0c;相对有效帮助T电梯修理考试总结学员顺利通过考试。 1、【多选题】TSGT7005-2012《…

【Java】已解决java.nio.channels.ClosedChannelException异常

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.nio.channels.ClosedChannelException异常 在Java的NIO&#xff08;New I/O&#xff09;编程中&#xff0c;java.nio.channels.ClosedChannelException是一个常见的异常…

XTDrone-多无人机精准降落-配置教程

1 编译AprilTag_ROS AprilTag是一个视觉基准系统&#xff0c;可用于机器人&#xff0c;增强现实和相机校准等。 根据AprilTag可以可靠地计算标签相对于相机的3D位置&#xff0c;方向和ID号。这里我们使用AprilTag的ROS库来实现位姿估计与ID号计算。 编译命令如下&#xff1a; …

python测试工程师 之 python基础大全【13万字总结】

python基础大全【13万字】 Day011、Python概述2、Python解释器和pycharmIDE工具3、Python中的注释4、变量5、标识符的命名规范 ★6、变量的使用7、Python中的数据类型 ★8、Python中的bug和调试9、字符串的格式化及输出 ★10、转译字符 day021、转译字符2、f-string ★3、数据类…

【windows|008】DNS服务详解

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 ​ &#x1f3c5;阿里云ACE认证高级工程师 ​ &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社…

【LinuxC语言】线程重入

文章目录 前言线程重入是什么线程重入实现示例代码总结前言 在并发编程中,我们经常需要处理多个线程同时访问和修改共享资源的问题。这可能会导致数据竞争和状态不一致,从而使程序的行为变得不可预测。为了解决这个问题,我们引入了一种称为“线程重入”的机制。线程重入,或…

家用洗地机哪个品牌好用?四款性价比高的洗地机推荐

还在为下班赶回家打扫卫生而烦恼&#xff1f;曾经的我也是这样&#xff0c;日复一日手动清洁&#xff0c;疲惫不堪。直到有一天&#xff0c;我决定相信现代科技&#xff0c;深入研究了市面上的各种洗地机评测&#xff0c;从此踏入了智能清洁家电的新世界。洗地机作为现代家居的…

Google Earth Engine(GEE)——checkbox的使用

结果 函数: ui.Checkbox(label, value, onChange, disabled, style) A checkbox with a label. Arguments: label (String, optional): The checkboxs label. Defaults to an empty string. value (Boolean, optional): Whether the checkbox is checked. A nu

LangChain 介绍

In recent times, you would probably have heard of many AI applications, one of them being chatpdf.com. 在最近&#xff0c;你可能听说过很多的AI应用&#xff0c;chatpdf.com就是其中的一个。 On this website, you can upload your own PDF. After uploading, you ca…

【面试题】 操作系统面试题 (第一篇)

1.volatile原理 volatile的底层原理主要涉及到多线程环境中共享变量的可见性和有序性。以下是关于volatile底层原理的详细解释&#xff1a; 可见性&#xff1a; 当一个变量被volatile修饰后&#xff0c;它会保证此变量对所有线程都是可见的。这里的“可见性”意味着当一个线程…

CinemachineFreelook相机鬼畜抖动的解决方法

又是培训机构的出品。。。。。。 2020.3.27 发现跟随时抖动的原因了&#xff0c;其实应该按照传统相机的跟随逻辑放在late update里执行&#xff0c;但是由于开发cinemachine的开发组很坑地把cinemachine freelook里的三个轨道Damping值默认给了3&#xff0c;于是相机会以每0.7…

Aquila-Med LLM:开创性的全流程开源医疗语言模型

​论文链接&#xff1a;https://arxiv.org/pdf/2406.12182 开源链接&#xff1a;https://huggingface.co/BAAI/AquilaMed-RL http://open.flopsera.com/flopsera-open/details/AquilaMed_SFT http://open.flopsera.com/flopsera-open/details/AquilaMed_DPO 近年来&#xf…

P10552 [THUPC2024] 警钟长鸣

题目描述 一年两度的 THUPC 又到来了&#xff0c;小 Z 也掏出了他的传统艺能——压轴的整活签到题。对于往年来说&#xff0c;签到题总是能被选手们在刚开场便迅速通过&#xff0c;而这次&#xff0c;小 Z 决定整点不一样的——”如果我把签到题刻意搞得很谜语人&#xff0c;让…

Java比较运算符

关系运算符和比较运算符适用于条件判断类型。 相当于布尔值&#xff0c;只有True和False两个 符号 说明ab,判断a的值是否等于b的值&#xff0c;条件成立为true,不成立为false ! a!b,判断a和b的值是否不相等&#xff0c;条件成立为true,不成立为false > …

MS17-010(Eternal blue永恒之蓝)漏洞利用+修复方法

目录 一、漏洞简介 漏洞原理 影响版本 二、漏洞复现 三、复现过程 1、扫描局域网内的C段主机&#xff08;主机发现&#xff09; 扫描结果&#xff1a; 2.使用MSF的永恒之蓝漏洞模块 3.对主机进行扫描&#xff0c;查看其是否有永恒之蓝漏洞 4.准备攻击 四、漏洞利用 …

C#健康体检信息管理系统成品源码,医院体检中心管理系统

健康体检信息管理系统覆盖体检中心的所有业务&#xff0c;完成从预约、登记、收费、检查、检验、出报告、分析、报表等所有工作&#xff0c;规范了体检流程&#xff0c;提高了工作效率。 体检系统开发环境&#xff1a; 技术架构&#xff1a;C/S架构 开发语言&#xff1a;C# …

k8s volcano + deepspeed多机训练 + RDMA ROCE+ 用户权限安全方案【建议收藏】

前提&#xff1a;nvidia、cuda、nvidia-fabricmanager等相关的组件已经在宿主机正确安装&#xff0c;如果没有安装可以参考我之前发的文章GPU A800 A100系列NVIDIA环境和PyTorch2.0基础环境配置【建议收藏】_a800多卡运行环境配置-CSDN博客文章浏览阅读1.1k次&#xff0c;点赞8…