SerialPort实现对串口COM的操作(有些纠结)
这段时间做了一个小型贷款软件,包括客户管理,交易管理,存折管理和打印,统计分析等模块,其中要求结合存折读卡器一起使用,比如添加存折的时候,存折号要求刷完卡后读出来,刷卡后可以显示客户信息等,和银行的刷卡机差不多。
客户买的刷卡机器提前没给我说一声,商家没有提供动态库,接口之类的,所以只能自己写一个对串口操作的,一般对CoM操作的程序要么用js写,要么就是写一个ActiveX组建,因为主要是对本机的串口操作的,所以保证读卡程序在客户端执行,这两个是很好的选择,这里我用的是后者,用C#写了一个ActiveX组件,在实现的过程中也遇到了很多问题,刚开始自己写了一个C/S结构的,可以正常读取,可是B/S确出了一些问题
我才用了微软提供的SerialPort类,大概的流程是这样的:
首先,找到计算机中可用的COM名称,代码如下
{
//获取可用的串号
{
serialPort1.Close();
}
//若串口可以打开说明可以用,否则继续查找可用的串口
if (serialPort1.IsOpen)
{
serialPort1.PortName = com;
break;
}
}
其次,设置串口的参数,包括波特率,协议,数据长度等,代码如下
serialPort1.BaudRate = 9600;
serialPort1.Parity = 0;
serialPort1.DataBits = 8;
然后,打开串口,发送命令,,这个时候设备的灯会亮,等待你的刷卡
{
serialPort1.Open();
}
byte[] data = new byte[2];
data[0] = 0x1b;
data[1] = 0x5d;
serialPort1.Write(data, 0, 2);
再次,调用SerialPort的DataReceived事件执行刷卡后的动作,比如刷完卡后就让卡号独到页面的文本框中,这里面需要ActiceX去调用页面的JavaScript
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的时候(这个事件却是可以触发,测试过了),就是传不过去卡号,而且还报有异常和错误:指定的转化无效,很是郁闷,也咨询了高手,自己也查了资料,就是不知道是什么原因,在这里,希望知道原因的朋友给予指导,谢谢了
没办法,就换了一个方式,完成了
打开页面的时候,打开串口,初始化串口参数,发送命令,然后开始刷卡,刷卡完成后,本来想放个按钮获得卡号的,可是感觉客户操作起来可能不太方便,就用键盘代替,按下回车键获取卡号,按下空格键重启设备,总的来说,这样也可以,只是没有立刷立获数据的效果完美吧,等以后有时间在研究其他的办法去解决….
代码下载: