现在在做一个煤矿的集成项目,这个系统里不仅有我们家的设备(这个好做),而且还有其他两家的设备也要融入我们的系统.
如果知道其他两家的设备的通信协议,这事并不困难.往往感觉容易的事情总会出现意外,造意外的原因有可能是:一.干活不认真,二.的确是一个意外.
下面我分三步介绍一个以下内容:
1.其他家的通信协议
2.遇到的问题
3.解决办法
具体内容:
一、其他家的通信协议,大家参考
1、第一个厂家的。
读实时数据命令:1100 0000+设备地址
返回实时数据:下位机(仪表)每次向上位机(PC机)传送16个字节,其中包括15个数据和1个累加和。
2、第二个厂家的。
读实时数据命令:要实现与仪表通信,主机需向仪表分两步发送控制命令字。然后通过通信中断处理仪表响应数据。
分两次发送数据,不同的校验位,中间延时sleep(10);
(1) 先把通信协议设置为:Baud_Rate,m,8,1 //校验位是MARK
通过串口发送 Address -> 仪表
延时(0.01s)
(2) 接着把通信协议设置为:Baud_Rate,S,8,1 //校验位是SPACE
通过串口发送以下数据到仪表:
CommandCode FunCode Data0 Data1 Data2 Data3 Crc_Code ->仪表
注:具体协议解析就不介绍了。
二、遇到的问题
协议解析还不是最重要的问题,遇到的具体问题是,如何动态改变串口的校验位?
我分别用三个动态库进行操作的
1、用的是JustinIO,这个类其实感觉写的不怎么好,后来对一些内容进行了改进。
但是用这个类库,并没有完成动态改变串口校验位的功能,具体代码如下:
public Parity ParityBit
{
set
{
if(hComm!=INVALID_HANDLE_VALUE)
{
this.Parity =(byte)value;
DCB dcb=new DCB ();
GetCommState(hComm, ref dcb);
dcb.Parity =(byte)value;
if (!SetCommState(hComm, ref dcb))
{
throw(new ApplicationException("非法操作,不能打开串口!"));
}
}
}
get
{
DCB dcb=new DCB ();
GetCommState(hComm, ref dcb);
return (Communicate.Parity)dcb.Parity ;
}
}
每次设置完新的Parity ,再获得Parity ,还是NONE.这让我很困惑,以我的判断很可能是DCB的事,但是具体是什么问题,还不太清楚,只能先完成工作再说了。
2、第二个我用的是SerialPort,应用在VS2003下的,不如VS2005的功能多。但是基本差上差 不多。最后也没有完成动态改变串口校验位的功能。
SerialPort.Parity = System.IO.Ports.Parity.Mark ;
SerialPort.Write (addr,0,addr.Length );
System.Threading .Thread .Sleep (10);
SerialPort.Parity = System.IO.Ports.Parity.Space ;
SerialPort.Write (cmd,0,cmd.Length );
从代码上看是可以改变串口的校验位的,但是设备并没有返回数据,所以我判断内部并没有真正改变。这个宣告失败。
3、第三个是用MSCommLib,最后成功了,代码如下:
//打开串口
io2.CommPort =4;
io2.InputMode =MSCommLib.InputModeConstants .comInputModeBinary ;
io2.Settings ="1200,n,8,1";
io2.OutBufferCount =0;
io2.OutBufferSize =1024;
io2.InBufferCount =0;
io2.InBufferSize =1024;
io2.InputLen =0;
io2.PortOpen =true;
//发送数据
io2.Settings ="1200,m,8,1";
io2.Output =addr;
System.Threading .Thread .Sleep (10);
io2.Settings ="1200,s,8,1";
io2.Output =cmd;
三,解决办法,MSCommLib应用
“项目”-》“引用”-》“添加引用”-》“COM”选卡-》“MICROSOFT COMM CONTROL 6.0”
private static MSCommLib.MSComm io2=new MSCommLib.MSCommClass ();
private static void InitCom()
{
try
{
io2.CommPort =4;
io2.InputMode =MSCommLib.InputModeConstants .comInputModeBinary ;
io2.Settings ="1200,n,8,1";
io2.OutBufferCount =0;
io2.OutBufferSize =1024;