微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C#串口通信—向串口发送数据,同步接收返回数据

    最近写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];
        }
    }
}
View Code

    二、Machine类

    1、变量与构造函数

<summary>
 串口资源
</summary>
private SerialPort serialPort = ;

public Machine( com)
{
    serialPort = new SerialPort(com,1)">9600,Parity.None,1)">81024;
    serialPort.WriteBufferSize = ;
}
View Code

    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;
    }
}
View Code

优化版:

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();
    }
}
View Code

    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
    {
        货机返回的数据格式不正确);
    }
}
View Code

    三、如何使用

    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
View Code

    2、前台代码

@{
    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">&nbsp;spandiv="text/javascript">
    //联机
    function connect() {
        commonAjax({
            url: "@Url.Content("/MachineInterface/Conn) (data) {
                if (data.ok) {
                    var html = 联机成功;
                    $(#msg).html(html);
                }
                else {
                    alert(data.msg);
                }
            }
        });
    }
>
View Code

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐