1 EDA远端测控模块指令介绍
EDA9033模块是一智能型电参数数据采集模块,可测量三相三线制或三相四线制电路中的三相电流、电压的真有效值、功率、功率因素和电度数。当主机发送读数据命令,模块便将采集的数据回送主机(其它模块也是根据上位机所发送的不同的指令提供不同的数据给上位机)。它有2种通信协议:ASCII码协议和十六进制LC-01协议。下面介绍ASCII码协议的读数据指令,指令的格式如下:
*命令:#(Addr)A<CR> (注:<CR>为回车键)
*响应:>(Data Ua) (Data Ia) (Data Ub) (Data Ib) (Data Uc) (Data Ic)
(Data P) (Data Q) (Data COSФ) <CR>,
*Data:其数值为标称满量程的百分数,例如电流标称满量程为5A,若输出数据为 0.8000,则实际电流值= 0.8000×5A= 4.0000A。
下面举一个具体的例子,设标称电流量程I0=5A,电压量程U0=100V。
*命令:#01A<CR>
*响应:> 1.0000 0.6000 1.0000 0.6000 1.0000 0.6000 0.6000 0.0000 1.0000<CR>
则测量的数值分别为:
Ua=Ub=Uc= 1.0000×U0=100.00V,
Ia=Ib=Ic= 0.6000×I0=3.0000A,
P= 900.00W,Q=0Var,COSФ= 1.0000。
其它的EDA测控模块的工作方式和指令格式与EDA9033模块类似。
2 Delphi串口通信简介
要用Delphi编写串口通信程序,需要借助各种通信控件,MSComm通信控件就是其中之一。Microsoft Communication Control(简称为MSComm)是Microsoft公司提供的Windows下的串口通信编程的ActiveX控件。MSComm通信控件具有丰富的与串口通信密切相关的属性及事件,提供了一系列标准通信命令的接口,可以用它创建全双工的、事件驱动的、高效实用的通信程序。
MSComm通信控件提供下列两种处理通信的方式:
(1) 事件驱动通信是处理串行端口交互作用的一种非常有效的方法。在许多情况下,在事件发生时需要得到通知,例如,在Carrier Detect(CD)或Request To Send(RTS)信号线上一个字符到达或一个变化发生时。在这些情况下,可以利用MSComm控件的OnComm事件捕获并处理这些通信事件。OnComm事件还可以检查和处理通信错误。
(2) 在程序的每个关键功能之后,可以通过检查CommEvent属性的值来查询事件和错误。它没有对每接收一个字符都产生事件,这种方法有时是更可取的。下面都采用这种处理通信的方式。
3 串口通信中出现的问题及其解决方案
下面只是对EDA远端测控模块的Delphi串口通信中出现的问题给予总结、归纳,并给出其解决方案。至于EDA远端测控模块串口通信的应用可参考文献[3]。
3.1 问题一及其解决方案
(1) 问题一:EDA9050模块的读数据指令$046<CR>有时出现乱码,得不到期望的数据。简单地说,该模块有时能得到期望的数据,有时得不到。
(2) 问题一的分析:给EDA9050模块发读数据指令$046<CR>时,期望得到的数据是:!007F00<CR>,感叹号后两位00是EDA9050的输出状态,接下来的两位7F是其输入状态,其它的位是固定的。图1是EDA模块的测试软件界面,从图1中我们可以发现这样一条规律:当收到的数据正确时,后面的2个零都存在。
(3) 问题一的解决方案:从上面的分析我们知道关键点是后面的2个零。一收到数据,我便把中间的六位数保存在数组A504中,通过判断数组A504的最后两位是否同时为零,如果最后两位同时为零,说明收到的数据是正确的,这时可以根据数据中间的两位状态进入相应的处理程序。否则说明收到的数据是错误的,这时必须重发一条EDA9050模块的读数据指令$046<CR>。这种方案有点像计算机网络中的自动重发机制。程序如下:
procedure TT_BLDJ_3_F.MSComm1Comm(Sender: TObject);
var
i,iReceived:integer;
begin
if MSComm1.CommEvent=2 then
//收到Rthreshold个字符产生的事件
begin
iReceived:=MSComm1.InBufferCount;
//接收缓冲区中的字符数
A:=VarArrayCreate([0,iReceived-1],varByte);
if flagiR8=1 then
begin
if iReceived=8 then
begin
A:=MSComm1.Input; //返回接收缓冲区
//中的数据
A504:=VarArrayCreate([0,5],varByte);
for i:=0 to 5 do
begin
A504:=A[i 1];//取数据中间的六位数
end;
if (A504[4]=48)and(A504[5]=48)then
//判断数组A504的最后两位是否同时为零
begin
if (A504[2]=54)and(A504[3]=55)then
begin
………………//Do something
end;
end
else
begin
flagiR8:=1;
TSendCom1('$046'#13);//重发指令
//$046<CR>
end;
end;
end;
end;
end;
其它的属性设置如下:
MSComm1.PortOpen:=true; //打开串口
MSComm1.RThreshold:=1; //每次接收到字符 //便产生OnComm事件
MSComm1.OutBufferCount:=0; //清空发送缓冲区
MSComm1.InputMode:=1; //数据通过Input属 //性以二进制形式取回
MSComm1.InBufferCount:=0; //清空接收缓冲区
MSComm1.SThreshold:=0; //发送不产生 //OnComm事件
MSComm1.InputLen:=0;//Input读取整个缓冲区的内容
注:TSendCom1(A:string)是自定义的过程,其功能是清空发送缓冲区和接收缓冲区后,然后往发送缓冲区发送数据(这里指的是指令)。
3.2 问题二及其解决方案
(1) 问题二:串口通信中数据的“冲突”问题
(2) 问题二的分析:当程序正在处理所需的数据时用户或程序又发送指令,这时串口的接收缓冲区既有前一次的数据也有刚发送指令所返回的数据,那么读出的数据就不正确。这将导致读出的数据没有意义,程序将无法正常进行下去。
(3) 问题二的解决方案:程序并不立即响应用户所发送的指令,而只是给所发送的指令设置了一个标志位,当程序处理完数据后通过判断标志位的值(这有点类似于单片机中的中断标志位),从而执行相应的指令,直到没有指令执行为止。
3.3 问题三及其解决方案
(1) 问题三:顺序闭合控制继电器的两种方法。
(2) 问题三的分析:在一些测试项目中要求按一定的顺序闭合各个继电器,为插件提供各种信号;否则插件不能够正常工作。例如对ZXZ8型照明信号综合保护器测试时要先加电源,然后顺序地再加上两个测试信号。EDA9050模块可以同时控制8个通道继电器的闭合和关断,也可以只控制1个通道继电器的闭合和关断。因此,顺序闭合控制继电器有两种方法
(3) 问题三的解决方案:EDA9050模块有两种控制继电器闭合和关断的指令。
EDA9050模块写数据指令的格式如下:
命令:#(Addr)(Order)(Data)<CR> (注:<CR>为回车键)
响应:> <CR>,
(Order):是用来指示置所有通道还是单一通道。向所有通道写入时,2个字符应该等于“0”(即(Order)=00)。向单一通道写入时,第一个字符是1,第二个字符表示通道号,其范围可以从“0”到“7”。
(Data):是代表数字量输出值的十六进制数。当向单一通道写入时,第一个字符总是“0”,第二个字符的值或者是“0”,或者是“1”。当向所有通道写入时,2个字符都有意义(范围00-FF)。数字等于二位十六进制表示的通道值。
当向所有通道写入时,这条指令可以同时控制多个继电器的闭合和关断。当向单一通道写入时,这条指令只能控制一个继电器的闭合和关断。因此有两种解决的方法。第一种方法:采用同时控制多个继电器的闭合和关断的方法。
第一种方法的程序如下:
TSendCom1('#040002'#13);//给插件加电源
TSendCom1('#040003'#13);//加测试信号1
TSendCom1('#040023'#13);//加测试信号2
第二种方法:采用只能控制一个继电器的闭合和关断的方法。第二种方法的程序如下:
TSendCom1('#041101'#13);//给插件加电源
TSendCom1('#041001'#13);//加测试信号1
TSendCom1('#041501'#13);//加测试信号2
可以看出,两种方法在顺序闭合或关断继电器中使用的语句是一样多的,功能也一样。但在同时控制多个继电器的时候,第一种方法所使用的语句是比较简单的,可读性也比较强。因此,建议采用第一种方法即同时控制多个继电器的闭合和关断的方法。
3.4 问题四及其解决方案
(1) 问题四:执行语句MSComm1.PortOpen:=true;出错,提示“串口已打开”。
(2) 问题四的分析:同一串口同时只能被打开一次,如果程序里有很多的Form,其中有一个Form已经打开串口,那么当另一个Form没有把串口关闭就执行语句MSComm1.PortOpen:=true;时,程序将出现“串口已打开”的错误。
(3) 问题四的解决方案:在设计综合保护器测试软件时,为了使各个型号的插件互不影响,实现模块化,我在每一个测试的Form里都有一个MSComm控件,在调用另一个测试Form前,关闭串口,然后在调用另一个测试Form时打开串口。另外一种方案是程序中只用了一个MSComm控件,所有的Form共用该MSComm控件,详细介绍请参考文献[1]。
上面的问题在EDA远端测控模块Delphi串口通信中是比较重要的,而且也是比较容易出错的地方。当然,在EDA远端测控模块Delphi串口通信中还有许多问题如报表的预览及打印等,对于这些问题可以参考相关的文献资料,这类问题一般可以迎刃而解。另外,有时会出现“设备未打开”的问题,解决的方法是重新启动计算机。
1楼
0
0
回复
EDA9033模块是一智能型电参数数据采集模块,可测量三相三线制或三相四线制电路中的三相电流、电压的真有效值、功率、功率因素和电度数。当主机发送读数据命令,模块便将采集的数据回送主机(其它模块也是根据上位机所发送的不同的指令提供不同的数据给上位机)。它有2种通信协议:ASCII码协议和十六进制LC-01协议。下面介绍ASCII码协议的读数据指令,指令的格式如下:
*命令:#(Addr)A<CR> (注:<CR>为回车键)
*响应:>(Data Ua) (Data Ia) (Data Ub) (Data Ib) (Data Uc) (Data Ic)
(Data P) (Data Q) (Data COSФ) <CR>,
*Data:其数值为标称满量程的百分数,例如电流标称满量程为5A,若输出数据为 0.8000,则实际电流值= 0.8000×5A= 4.0000A。
下面举一个具体的例子,设标称电流量程I0=5A,电压量程U0=100V。
*命令:#01A<CR>
*响应:> 1.0000 0.6000 1.0000 0.6000 1.0000 0.6000 0.6000 0.0000 1.0000<CR>
则测量的数值分别为:
Ua=Ub=Uc= 1.0000×U0=100.00V,
Ia=Ib=Ic= 0.6000×I0=3.0000A,
P= 900.00W,Q=0Var,COSФ= 1.0000。
其它的EDA测控模块的工作方式和指令格式与EDA9033模块类似。
2 Delphi串口通信简介
要用Delphi编写串口通信程序,需要借助各种通信控件,MSComm通信控件就是其中之一。Microsoft Communication Control(简称为MSComm)是Microsoft公司提供的Windows下的串口通信编程的ActiveX控件。MSComm通信控件具有丰富的与串口通信密切相关的属性及事件,提供了一系列标准通信命令的接口,可以用它创建全双工的、事件驱动的、高效实用的通信程序。
MSComm通信控件提供下列两种处理通信的方式:
(1) 事件驱动通信是处理串行端口交互作用的一种非常有效的方法。在许多情况下,在事件发生时需要得到通知,例如,在Carrier Detect(CD)或Request To Send(RTS)信号线上一个字符到达或一个变化发生时。在这些情况下,可以利用MSComm控件的OnComm事件捕获并处理这些通信事件。OnComm事件还可以检查和处理通信错误。
(2) 在程序的每个关键功能之后,可以通过检查CommEvent属性的值来查询事件和错误。它没有对每接收一个字符都产生事件,这种方法有时是更可取的。下面都采用这种处理通信的方式。
3 串口通信中出现的问题及其解决方案
下面只是对EDA远端测控模块的Delphi串口通信中出现的问题给予总结、归纳,并给出其解决方案。至于EDA远端测控模块串口通信的应用可参考文献[3]。
3.1 问题一及其解决方案
(1) 问题一:EDA9050模块的读数据指令$046<CR>有时出现乱码,得不到期望的数据。简单地说,该模块有时能得到期望的数据,有时得不到。
(2) 问题一的分析:给EDA9050模块发读数据指令$046<CR>时,期望得到的数据是:!007F00<CR>,感叹号后两位00是EDA9050的输出状态,接下来的两位7F是其输入状态,其它的位是固定的。图1是EDA模块的测试软件界面,从图1中我们可以发现这样一条规律:当收到的数据正确时,后面的2个零都存在。
(3) 问题一的解决方案:从上面的分析我们知道关键点是后面的2个零。一收到数据,我便把中间的六位数保存在数组A504中,通过判断数组A504的最后两位是否同时为零,如果最后两位同时为零,说明收到的数据是正确的,这时可以根据数据中间的两位状态进入相应的处理程序。否则说明收到的数据是错误的,这时必须重发一条EDA9050模块的读数据指令$046<CR>。这种方案有点像计算机网络中的自动重发机制。程序如下:
procedure TT_BLDJ_3_F.MSComm1Comm(Sender: TObject);
var
i,iReceived:integer;
begin
if MSComm1.CommEvent=2 then
//收到Rthreshold个字符产生的事件
begin
iReceived:=MSComm1.InBufferCount;
//接收缓冲区中的字符数
A:=VarArrayCreate([0,iReceived-1],varByte);
if flagiR8=1 then
begin
if iReceived=8 then
begin
A:=MSComm1.Input; //返回接收缓冲区
//中的数据
A504:=VarArrayCreate([0,5],varByte);
for i:=0 to 5 do
begin
A504:=A[i 1];//取数据中间的六位数
end;
if (A504[4]=48)and(A504[5]=48)then
//判断数组A504的最后两位是否同时为零
begin
if (A504[2]=54)and(A504[3]=55)then
begin
………………//Do something
end;
end
else
begin
flagiR8:=1;
TSendCom1('$046'#13);//重发指令
//$046<CR>
end;
end;
end;
end;
end;
其它的属性设置如下:
MSComm1.PortOpen:=true; //打开串口
MSComm1.RThreshold:=1; //每次接收到字符 //便产生OnComm事件
MSComm1.OutBufferCount:=0; //清空发送缓冲区
MSComm1.InputMode:=1; //数据通过Input属 //性以二进制形式取回
MSComm1.InBufferCount:=0; //清空接收缓冲区
MSComm1.SThreshold:=0; //发送不产生 //OnComm事件
MSComm1.InputLen:=0;//Input读取整个缓冲区的内容
注:TSendCom1(A:string)是自定义的过程,其功能是清空发送缓冲区和接收缓冲区后,然后往发送缓冲区发送数据(这里指的是指令)。
3.2 问题二及其解决方案
(1) 问题二:串口通信中数据的“冲突”问题
(2) 问题二的分析:当程序正在处理所需的数据时用户或程序又发送指令,这时串口的接收缓冲区既有前一次的数据也有刚发送指令所返回的数据,那么读出的数据就不正确。这将导致读出的数据没有意义,程序将无法正常进行下去。
(3) 问题二的解决方案:程序并不立即响应用户所发送的指令,而只是给所发送的指令设置了一个标志位,当程序处理完数据后通过判断标志位的值(这有点类似于单片机中的中断标志位),从而执行相应的指令,直到没有指令执行为止。
3.3 问题三及其解决方案
(1) 问题三:顺序闭合控制继电器的两种方法。
(2) 问题三的分析:在一些测试项目中要求按一定的顺序闭合各个继电器,为插件提供各种信号;否则插件不能够正常工作。例如对ZXZ8型照明信号综合保护器测试时要先加电源,然后顺序地再加上两个测试信号。EDA9050模块可以同时控制8个通道继电器的闭合和关断,也可以只控制1个通道继电器的闭合和关断。因此,顺序闭合控制继电器有两种方法
(3) 问题三的解决方案:EDA9050模块有两种控制继电器闭合和关断的指令。
EDA9050模块写数据指令的格式如下:
命令:#(Addr)(Order)(Data)<CR> (注:<CR>为回车键)
响应:> <CR>,
(Order):是用来指示置所有通道还是单一通道。向所有通道写入时,2个字符应该等于“0”(即(Order)=00)。向单一通道写入时,第一个字符是1,第二个字符表示通道号,其范围可以从“0”到“7”。
(Data):是代表数字量输出值的十六进制数。当向单一通道写入时,第一个字符总是“0”,第二个字符的值或者是“0”,或者是“1”。当向所有通道写入时,2个字符都有意义(范围00-FF)。数字等于二位十六进制表示的通道值。
当向所有通道写入时,这条指令可以同时控制多个继电器的闭合和关断。当向单一通道写入时,这条指令只能控制一个继电器的闭合和关断。因此有两种解决的方法。第一种方法:采用同时控制多个继电器的闭合和关断的方法。
第一种方法的程序如下:
TSendCom1('#040002'#13);//给插件加电源
TSendCom1('#040003'#13);//加测试信号1
TSendCom1('#040023'#13);//加测试信号2
第二种方法:采用只能控制一个继电器的闭合和关断的方法。第二种方法的程序如下:
TSendCom1('#041101'#13);//给插件加电源
TSendCom1('#041001'#13);//加测试信号1
TSendCom1('#041501'#13);//加测试信号2
可以看出,两种方法在顺序闭合或关断继电器中使用的语句是一样多的,功能也一样。但在同时控制多个继电器的时候,第一种方法所使用的语句是比较简单的,可读性也比较强。因此,建议采用第一种方法即同时控制多个继电器的闭合和关断的方法。
3.4 问题四及其解决方案
(1) 问题四:执行语句MSComm1.PortOpen:=true;出错,提示“串口已打开”。
(2) 问题四的分析:同一串口同时只能被打开一次,如果程序里有很多的Form,其中有一个Form已经打开串口,那么当另一个Form没有把串口关闭就执行语句MSComm1.PortOpen:=true;时,程序将出现“串口已打开”的错误。
(3) 问题四的解决方案:在设计综合保护器测试软件时,为了使各个型号的插件互不影响,实现模块化,我在每一个测试的Form里都有一个MSComm控件,在调用另一个测试Form前,关闭串口,然后在调用另一个测试Form时打开串口。另外一种方案是程序中只用了一个MSComm控件,所有的Form共用该MSComm控件,详细介绍请参考文献[1]。
上面的问题在EDA远端测控模块Delphi串口通信中是比较重要的,而且也是比较容易出错的地方。当然,在EDA远端测控模块Delphi串口通信中还有许多问题如报表的预览及打印等,对于这些问题可以参考相关的文献资料,这类问题一般可以迎刃而解。另外,有时会出现“设备未打开”的问题,解决的方法是重新启动计算机。