您的位置:首页 > 教育 > 锐评 > C# 一个串口通信的案例实现

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

2024/10/5 18:23:26 来源:https://blog.csdn.net/qq_41184334/article/details/139772767  浏览:    关键词: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;}}}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com