zoukankan      html  css  js  c++  java
  • C# 串口通信总结

    在C#串口通信开发过程中有的产家只提供通信协议,这时候开发人员要自己根据协议来封装方法,有的产家比较人性化提供了封装好的通信协议方法供开发人员调用。

    1、只提供通信协议(例如,今年早些时候开发的出钞机):

    QQ截图20141113095538

    QQ截图20141113095519

    如:

    /// <summary>
       /// 出钞 DISPENSE(0x45)
       /// </summary>
       public void Chuchao()
       {
           log("出钞设备出钞");
           if (!sp.IsOpen)
           {
               sp.Open();
           }
           try
           {

               var send = new byte[] { Eot, Id, Stx, Dipsense, 48, 51, Etx, 0x01 };
               int bcc = 0;
               for (int i = 0; i < send.Length - 1; i++)
                   bcc ^= send[i];
               send[send.Length - 1] = (byte)bcc;
               sp.Write(send, 0, send.Length);
               log("操作命令:" + GetBytesString(send, 0, send.Length, " "));
               for (int i = 0; i < 3; i++)
               {
                   var r = sp.ReadByte();
                   log("发送命令,收到的反馈。" + r);
                   if (r != Ack)
                   {
                       sp.Write(send, 0, send.Length);
                   }
                   else
                   {
                       break;
                   }
               }

               byte[] recive = new byte[14];

               for (int i = 0; i < 3; i++)
               {
                   bcc = 0;
                   recive = GetData(recive.Length);
                   for (int j = 0; j < recive.Length - 1; j++)
                   {
                       bcc ^= recive[j];
                   }
                   if (bcc != recive[recive.Length - 1])
                   {
                       sp.Write(new byte[] { Nck }, 0, 1);
                       log("收到信息:" + GetBytesString(recive, 0, recive.Length, " ") + ",接收标识:NCK:失败");
                   }
                   else
                   {
                       sp.Write(new byte[] { Ack }, 0, 1);
                       log("收到信息:" + GetBytesString(recive, 0, recive.Length, " ") + ",接收标识:ACK:成功");
                       break;
                   }
               }
               Error errorCode = new Error();
               errorCode.Code = recive[9];
               log("接收到的命令:" + recive[3] + ",接收到的错误码:" + errorCode.Code + "--" + errorCode.ErrorMsg);
               if (recive[3] != Dipsense || errorCode.Code > 0x31)
               {
                   throw new Exception("出钞出错");
               }
           }
           catch (Exception e)
           {
               log(e.ToString());
               //throw;
           }
           finally
           {
               if (sp.IsOpen)
               {
                   sp.Close();
               }
           }
       }

    2、产家提供通信协议方法(例如,今年早些时候开发的银行卡支付机):

    这时候你只要在你的项目bin/Debug下面添加产家提供的dll,然后,再这样:

             /// <summary>
            /// 打开串口
             /// </summary>
            /// <param name="port">串口号字符串</param>
            /// <returns>
            /// 串口文件句柄
            /// 备注:必须先调用此函数,获得指定串口的串口文件句柄,才可调用其他函数。
            /// 可以同时打开多个串口,获得多个串口文件句柄,但不能多次打开同一个串口。
            /// 使用完毕后,必须调用CommClose()关闭串口。
            /// </returns>
            [DllImport("CRT_310.dll", EntryPoint = "CommOpen", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr CommOpen(string port);
    
            /// <summary>
            /// 按指定的波特率打开串口 (该函数完成的功能= CommOpen 函数+ CommSetting 函数)
            /// </summary>
            /// <param name="port">串口号字符串</param>
            /// <param name="data">指定波特率
            /// 波特率=1200,2400,4800,9600,19200,38400。
            /// 例如:CommOpen("Com1",9600);
            /// </param>
            /// <returns>串口文件句柄
            /// 备注:必须先调用此函数,获得指定串口的串口文件句柄,才可调用其他函数。
            /// 可以同时打开多个串口,获得多个串口文件句柄,但不能多次打开同一个串口。
            /// 使用完毕后,必须调用CommClose()关闭串口。</returns>
            [DllImport("CRT_310.dll", EntryPoint = "CommOpenWithBaut", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr CommOpenWithBaut(string port, uint data);
    
    

    然后就可以像这样调用了:

    public string CardBoxPositionToRead()
            {
                var comHandle = new IntPtr();
                var cardStates = new byte[2];
                var recordInfo = new byte[200];
                int? data;
                try
                {
                    comHandle = PackageK100Dll.M100A_CommOpenWithBaud(ComPort, BaudRate);
                    if (comHandle.ToInt32() == 0)
                    {
                        PackageK100Dll.M100A_CommClose(comHandle);
                        return "打开串口失败!";
                    }
                    data = PackageK100Dll.M100A_CheckCardPosition(comHandle, false, 0, cardStates, recordInfo);
                    if (data != 0)
                    {
                        PackageK100Dll.M100A_CommClose(comHandle);
                        return "读取卡片位置失败";
                    }
                    switch (cardStates[0])
                    {
                        //通道无卡
                        case 48:
                            break;
                        case 49:
                        case 50:
                            data = PackageK100Dll.M100A_MoveCard(comHandle, false, 0, 0x34, recordInfo);
                            if (data != 0)
                            {
                                PackageK100Dll.M100A_CommClose(comHandle);
                                return "移动卡片位置失败";
                            }
                            break;
                        //通道有卡
                        default:
                            PackageK100Dll.M100A_CommClose(comHandle);
                            return "请取走卡片或者业务正在办理,请稍候!";
                    }
                    switch (cardStates[1])
                    {
                        case 48:
                            PackageK100Dll.M100A_CommClose(comHandle);
                            return "卡箱无卡";
                        default:
                            //将卡槽卡片移动到读写卡位置
                            data = PackageK100Dll.M100A_MoveCard(comHandle, false, 0, 0x30, recordInfo);
                            if (data != 0)
                            {
                                PackageK100Dll.M100A_CommClose(comHandle);
                                return "移动卡片位置失败";
                            }
                            PackageK100Dll.M100A_CommClose(comHandle);
                            return "true";
                    }
    
                }
                catch (Exception)
                {
                    PackageK100Dll.M100A_CommClose(comHandle);
                    return "发生异常";
                }
            }
    
  • 相关阅读:
    Ubuntu杂记——Ubuntu自带拼音输入发杂乱不堪
    数据库随笔——数据库设计原则(转)
    Java学习笔记——回调函数
    Android随笔之——静默安装、卸载
    Hibernate学习之——搭建log4j日志环境
    Hibernate学习之——Hibernate环境搭建
    Android随笔之——闹钟制作铺垫之AlarmManager详解
    Android随笔之——Android时间、日期相关类和方法
    Nyoj 天下第一(spfa)
    hdu 最大三角形(凸包+旋转卡壳)
  • 原文地址:https://www.cnblogs.com/zhangwei595806165/p/4094197.html
Copyright © 2011-2022 走看看