最近写C#串口通信程序,系统是B/S架构。SerialPort类有一个DataReceived事件,用来接收串口返回的数据,但这种方式在C/S架构下很好用,但B/S就不好处理了。所以写了一个同步模式接收返回数据的方法,不使用DataReceived事件。经过测试,可以正常使用。
一、MachineFactory类
为什么使用工厂类:售货机由不止一个厂家提供,接口协议都不一样。
using System; System.Collections.Generic; System.Linq; System.Text; System.Reflection; System.IO; System.IO.Ports; namespace IMachineDll { /// <summary> /// 售货机工厂类 </summary> public class MachineFactory { <summary> 货机接口缓存 </summary> private static Dictionary<string,IMachine> dicMachine = new Dictionary<(); 锁变量 static object _lock = new object(); 创建售货机类 </summary> <param name="path">DLL物理路径</param> <param name="dllName">DLL名称(不含扩展名),命名空间必须为DLL名称加“Dll”后缀,类名必须和DLL名称相同/// <param name="com">串口名称,如:COM1</param> static IMachine Create(string path,string dllName,1)">string com) { if (!dicMachine.ContainsKey(dllName) || dicMachine[dllName] == null) { using (FileStream fs = new FileStream(path + dllName + ".dll",FileMode.Open,FileAccess.Read)) { using (MemoryStream ms = new MemoryStream()) { byte[] byteArray = byte[4096]; while (fs.Read(byteArray,0,byteArray.Length) > 0) { ms.Write(byteArray, Assembly.Load(ms.ToArray()); dicMachine[dllName] = (IMachine)assembly.CreateInstance(dllName + Dll." + dllName,1)">false,BindingFlags.Default,1)">null,1)">object[] { com },1)">); } } } return dicMachine[dllName]; } } }
二、Machine类
1、变量与构造函数
<summary> 串口资源 </summary> private SerialPort serialPort = ; public Machine( com) { serialPort = new SerialPort(com,1)">9600,Parity.None,1)">81024; serialPort.WriteBufferSize = ; }
2、向串口发送数据,同步接收返回数据的方法:
向串口发送数据,读取返回数据 </summary> <param name="sendData">发送的数据</param> <returns>返回的数据</returns> byte[] ReadPort(byte[] sendData) { lock (MachineFactory._lock) { //打开连接 serialPort.IsOpen) serialPort.open(); 发送数据 serialPort.Write(sendData,sendData.Length); 读取返回数据 DateTime dt = DateTime.Now; while (serialPort.BytesToRead == ) { Thread.Sleep(1); if (DateTime.Now.Subtract(dt).TotalMilliseconds > 5000) 如果5秒后仍然无数据返回,则视为超时 { throw new Exception(主版无响应); } } Thread.Sleep(50); byte[] recData = [serialPort.BytesToRead]; serialPort.Read(recData,recData.Length); 关闭连接 if (serialPort.IsOpen) serialPort.Close(); recData; } }
优化版:
while (serialPort.BytesToRead < 2); } } List<byte> recList = new List<byte>(); int length = recData[1] + 3; 报文数据总长度 while (recList.Count < length) { if (serialPort.BytesToRead > ) { recData = [serialPort.BytesToRead]; serialPort.Read(recData,recData.Length); recList.AddRange(recData); } Thread.Sleep(); } recList.ToArray(); } }
3、发送联机指令:
联机 <param name="msg">传出错误信息联机是否成功bool Connect(out msg) { byte[] sendData = byte[] { 0x01,1)">0x00,1)">0x00 }; CommonUtil.CalCheckCode(sendData); byte[] recData = ReadPort(sendData); if (recData.Length >= 4 && recData[0] == 0x01 && recData[1] == 0x02 && recData[2] == 0x00 && CommonUtil.ValidCheckCode(recData)) { switch (recData[3]) { case : msg = 控制主板正在重启; return false; 0x01联机成功true0x02控制主板正在维护0x03控制主板收到的数据格式不正确default未知状态; } } else if (IsRunning(recData,1)">out msg) || !IsConnected(recData,1)">out msg)) { ; } else { 货机返回的数据格式不正确); } }
三、如何使用
1、Controller层代码(还不完善,仅测试,真实情况是根据硬件信息,确定调用哪个Dll使用哪个串口):
@H_179_502@
#region 创建售货机接口 创建售货机接口 private IMachine CreateMachine() { return MachineFactory.Create(Request.PhysicalApplicationPath + @"\bin\","Machine","COM1"); return MachineFactory.Create(@"D:\售药机代码\Reception\Machine\bin\Debug\",1)">MachineCOM1); } #endregion #region 联机 错误信息try { IMachine machine = CreateMachine(); DateTime dt1 =while (!machine.Connect(out msg)) 联机 { if (DateTime.Now.Subtract(dt1).TotalMilliseconds > 20000) { msg = 联机超时; } Thread.Sleep(catch (Exception ex) { msg = ex.Message; ; } } #region 单次联机 单次联机 public ActionResult Conn() { string msg = ; Dictionary<object> dic = ; CreateMachine(); if (machine.Connect(out msg)) 联机成功 { dic = object>(); dic[ok"] = ; dic[msg"] = 成功 Content(JsonConvert.SerializeObject(dic)); } { dic = 联机失败:" + msg; Content(JsonConvert.SerializeObject(dic)); } } (Exception ex) { dic = (); dic[; dic[错误: Content(JsonConvert.SerializeObject(dic)); } } #region 联机并使能硬纸币器 联机并使能硬纸币器 ActionResult ConnectEnable() { if (Connect(out msg) && machine.CoinEnable(out msg) && machine.PaperMoneyEnable(联机并使能硬纸币器成功 硬币器使能失败:#endregion
@{ ViewBag.Title = "货机接口测试"; Layout = null; } <!DOCTYPE html> <htmlhead> title>@ViewBag.Title</script type="text/javascript" src="~/Scripts/jquery-1.8.2.min.js"></script="~/Scripts/LongPolling.js"bodydiv style="padding: 20px;"> input ="button" value="联机" onclick="connect()" /> ="font-size: 20px; line-height: 30px;"> > span id="msg"> spandiv="text/javascript"> //联机 function connect() { commonAjax({ url: "@Url.Content("/MachineInterface/Conn) (data) { if (data.ok) { var html = 联机成功; $(#msg).html(html); } else { alert(data.msg); } } }); } >
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。