SerialPort实现对串口COM的操作(有些纠结)

     这段时间做了一个小型贷款软件,包括客户管理,交易管理,存折管理和打印,统计分析等模块,其中要求结合存折读卡器一起使用,比如添加存折的时候,存折号要求刷完卡后读出来,刷卡后可以显示客户信息等,和银行的刷卡机差不多。

     客户买的刷卡机器提前没给我说一声,商家没有提供动态库,接口之类的,所以只能自己写一个对串口操作的,一般对CoM操作的程序要么用js写,要么就是写一个ActiveX组建,因为主要是对本机的串口操作的,所以保证读卡程序在客户端执行,这两个是很好的选择,这里我用的是后者,用C#写了一个ActiveX组件,在实现的过程中也遇到了很多问题,刚开始自己写了一个C/S结构的,可以正常读取,可是B/S确出了一些问题

我才用了微软提供的SerialPort类,大概的流程是这样的:

首先,找到计算机中可用的COM名称,代码如下

  foreach (string com in System.IO.Ports.SerialPort.GetPortNames())
            {
                 //获取可用的串号    
            if (serialPort1.IsOpen)
                {
                    serialPort1.Close();
                }
                //若串口可以打开说明可以用,否则继续查找可用的串口
                if (serialPort1.IsOpen)
                {
                    serialPort1.PortName = com;
                    break;
                }
            }

其次,设置串口的参数,包括波特率,协议,数据长度等,代码如下

   serialPort1.BaudRate = 9600;

            serialPort1.Parity = 0;

            serialPort1.DataBits = 8;

然后,打开串口,发送命令,,这个时候设备的灯会亮,等待你的刷卡

 if (!serialPort1.IsOpen)
            {
                serialPort1.Open();
            }
            byte[] data = new byte[2];
            data[0] = 0x1b;
            data[1] = 0x5d;
            serialPort1.Write(data, 02);

再次,调用SerialPortDataReceived事件执行刷卡后的动作,比如刷完卡后就让卡号独到页面的文本框中,这里面需要ActiceX去调用页面的JavaScript

serialPort1.DataReceived+=new System.IO.Ports.SerialDataReceivedEventHandler(serialPort1_DataReceived);
  void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            try
            {
                Thread.Sleep(50);/
                int bytes = serialPort1.BytesToRead;
            
                byte[] buffer = new byte[bytes];
          
                serialPort1.Read(buffer, 0, bytes);
                string strbuffer = Encoding.ASCII.GetString(buffer);
                string romovestartChar = strbuffer.Substring(2);
                string rightInfo = romovestartChar.Substring(0, romovestartChar.IndexOf('?'));
                temphtml.execScript(functionstr + "('" + rightInfo + "')""JScript");   
                if (serialPort1.IsOpen)
                {
                    serialPort1.Close();
                }
            }
            catch (Exception ex)
            {
                if (serialPort1.IsOpen)
                {
                    serialPort1.Close();
                }
                MessageBox.Show(ex.Message);
            }
        }

其中, temphtml.execScript(functionstr + "('" + rightInfo + "')", "JScript");   就是调用页面的js函数的,这里简答的说一下关于ActiveX是如何调用Js

首先,我们要加入micsoft.mshtml引用

using mshtml;

 

        private IHTMLWindow2 temphtml = null;

        private string functionstr = "";

 

        public void RegJs(object win, string fuc)

        {

            temphtml = (IHTMLWindow2)win;

            if (temphtml != null && !string.IsNullOrEmpty(fuc))

            {

                functionstr = fuc;

            }

            else

            {

                temphtml = null;

                functionstr = "";

                MessageBox.Show("注册脚本失败");

            }

        }

加载页面的时候,页面就调用RegJs完成传值,把窗体和js函数传到activeX

 <script type="text/javascript">

        window.onload = function () {

            document.getElementById("Object1").RegJs(window, "Show"); //将页面对象,和所需调用的js方法名传给activex

}  

//activex调用的js方法,将卡号转到页面的文本框中

 function Show(str) {

            document.getElementById("text1").value = str;

        }

 

然后在ActiveX就可以调用temphtml.execScript(functionstr + "('" + rightInfo + "')", "JScript");就可以完成调用赋值了

 

接着上面的说说,自己也用按钮测试了,当点击按钮的时候确实可以把值传过去,也就是说,只要在ActiveX触发事件,都可以实现传值,但是问题就出现在这里了,当我触发刷卡事件serialPort1.DataReceived的时候(这个事件却是可以触发,测试过了),就是传不过去卡号,而且还报有异常和错误:指定的转化无效,很是郁闷,也咨询了高手,自己也查了资料,就是不知道是什么原因,在这里,希望知道原因的朋友给予指导,谢谢了

没办法,就换了一个方式,完成了

打开页面的时候,打开串口,初始化串口参数,发送命令,然后开始刷卡,刷卡完成后,本来想放个按钮获得卡号的,可是感觉客户操作起来可能不太方便,就用键盘代替,按下回车键获取卡号,按下空格键重启设备,总的来说,这样也可以,只是没有立刷立获数据的效果完美吧,等以后有时间在研究其他的办法去解决….

 

代码下载:

     Demo源码下载

原文地址:https://www.cnblogs.com/shuang121/p/2532660.html