《Direct I/O in DOSBOX for COMM serial communications with QBasic, TBasic or Pbasic》笔记中记录了在DOSBOX砂箱下,对串口编程的DOS程序和WINx16程序,以及让WINx16位程序在WINx64下直接运行的方法。接下来是分离DOS程序与主机通讯程序,让它们互相配合,各尽其职,将边缘计算与现代化展现与网络结合起来,从而形成可发挥作用的系统。
对于局部控制,ISA是优秀的工业标准总线,它不需要所谓高速SerDes串并转换,硬件控制非常透明,是老一代工业系统开发者的优选。基于ISA总线的SBC卡、CPU卡、ADC、DAC、DIO、COUNTERS、FREQUENCY、PWM、NETWORK、PC-CARDS等等,几乎是应有尽有,非常完善。如果把它们聚集到母板上,将DOS和其下的串口直接端口操作程序放上去,再通过串行总线与WIN64、LINUX64按指令交互,就是基本的简单系统。为了让它更清晰,不妨把它放在一个壳子里,让黑壳子开机就自己运行,无需显示等任何其它辅助设备。
全套局部系统的组成应包括:
1. 传感器和执行机构
2. 配线架和端子接入箱
3. 信号处理箱
4. 用户终端、桌面。
局部系统之间可以通过工业总线联网,RS485、HART、CAN、PROFIBUS、ETHERNET等等。这类总线几十种,我们国家也制订有相应的总线,就连现在的汽车中也使用标准总线,就不细述了,它本身就是一套值得研究和发展的领域,国内目前做得还不够好,努力空间很广阔。
有了SCADA分布式系统,只是过程处理的自动化和简单的智能化,还达不到智慧工厂要求。所以,要通过物联网将不同城市间的SCADA系统连起来,再与管理运营与生结合起来。
工业控制开发人员在工厂智慧化上的作用是非常大的,主要是在系统系统层级发力,而其它两个维度要既懂技术又清楚管理的总监,才能共同完成智慧工厂建设和之后的持续改进。《Direct I/O in DOSBOX for COMM serial communications with QBasic, TBasic or Pbasic》主要是硬件通讯内核的筑助,用户层的通讯内核也有,
典型方式:WINDOWS API, MSCOMM, SERIALPORT
当发送完指令后,往往要等待寄存器数据准备好后才能读取,否则数据无效。一些控件在发送和接收时做了处理,对字节进行组装,如果在组装过程中线路中断,用户很难处理这类错误,程序就不动了。
解决方法1. 最好就是用BYTE发送、BYTE接收,自己组装指令和数据。
解决方法2. 程序死锁往往是单线程序,可在主进程中设置FLAG1,在线路数据处理部分清除FLAG1。主线程发现FLAG1很长时间或很多次不清时,则关闭通讯口,然后再打开通讯口,强制处理通讯口异常。
解决方法3. 发送数据前也设置FLAG2,接收成功后清除FLAG2,FLAG2不清除就能再发送数据。主发送和接收在FLAG2握手下进行,避免Overwrite发生。
MSCOMM是WINx32自带的ActiveX COM组件,VB、XE、C++Builder等,都可以Import了使用它,采取上述措施后还是宜用的。
SerialPort是VS自带的,在NET平台上直接可用,注意事项是一样的。
值得一提的是Lazarus带的SerialPort组件,还是要用它,不要费劲的调用其它COM组件,因为Lazarus是跨平台编译的,用了平台相关组件就失去了程序跨平台编译能力,是很可惜的事情。唯一遇到的问题是进程死锁产生超时错误,中断了程序运行。
找到PAS文件的237行,将ProcessMessage这个循环提前两行开始,问题就解了。
原来它是发出结束进程就在那ProcessMessage死等结束标记,不如再发结束指令再读结束标记。就像我们手工关闭窗体,一次关不了就多点几个次关闭,不要点一次就等到晚。
9600下发指令、收指令加校验,几十次至上百次指令与数据交互,稳定、迅速,中间断线断电后自动恢复交互。串口,用好了出奇迹,用不好出麻烦,是个既让人爱又让人恨的悠久存在。
A. 因为MSCOMM.VBX的引入,退出主程序前必须先关闭它,而且要在窗体关闭前先关闭串口。做法是将它放在FormCloseQuery里面,而不是其它地方!
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
Comm1.PortOpen := False;
end;
A. 放在FORM_Unload里面。VB3简化了窗体关闭过程,如此放置不会出异常的。VB4和VB6与VB3放的位置相同。
Sub Form_Unload (Cancel As Integer)
' Close the serial port.
Comm1.PortOpen = False
End Sub
A. VB.NET不像以前那么粗放,放在Dispose里同窗体一同消毁。
Private Sub Form1_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
SerialPort1.Close()
End Sub
A. 放到Form的Designer.cs的Dispose里
Private Sub Form1_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
SerialPort1.Close()
End Sub
A. 放在FormCloseQuery里
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)
{
if (MSComm1->PortOpen == true) {
MSComm1->PortOpen = False;}
Timer1->Enabled = false;
}
A. 同 Embarcadero XE,放在FormCloseQuery里
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: boolean);
begin
CanClose := True;
if LazSerial1.Active then
LazSerial1.Active := False; //Close serial port
end;
不论是Import的MSCOMM组件,还是自带的串口控件,均要在程序结束之前关闭串口,时序错了主程序关不掉、出现异常错误。另外特别注意,发送/接收时用For/Next,而不用Do/Loop,否则断线了进入死循环,失去自我恢复机能。不论MSCOMM还是SerialPort组件,用对了都好用。