----最近一段时间,由于工作上的原因,接触到了PC机与PLC编程口通信方面的开发。开发过程也走过不少的弯路,由于编程口通信协议未被三菱公司公开,所以很难找到一个系统的教材,在网上搜集了许多这方面的资料。最开始在VB上调试的时候非常顺利,按照其通信协议发送了一个字符串"ABCD1234" ,然后在PLC中收到。 当时以为向嵌入式Linux移植会很顺利,但是在定义了数据结构后,往端口发送数据PLC没有收到。对此进行了比较系统的分析。 ----首先想到的是VB字符串与C字符串的差别。VB中运行时每一个英文字符都是双字节的Unicode字符,通过Lenb(ch* ar)=2可以看出是双字节。然后就转而去研究Unicode编码问题,对字符进行Unicode编码还是不行。后来查到了VB串行口通信编码方面的资料,才知道VB中运行时字符会自动转换为Unicode,但是在输出时却又转为ASCII(指英文字符),VB真是个大骗子,上了一次大当。既然不是编码问题的话那肯定就是端口设置问题,或者就是别的什么未知问题。然后就去检查各个设置参数。VB里面打开COM1采用 Open "COM1:9600:N:1"的方式来打开串口,打开超级终端监视器,发现无论怎么调节其中的打开参数,都可以正确接收!至少在这里可以说明VB中指定的参数设置也是骗人的。然后就检查Linux程序里关于端口的设置并和通信协议进行比较,突然发现奇偶校验不对,其编程口为偶校验。修改完以后,运行程序,PLC指示灯亮了! ---- 通过以上的经历,总结了以下的经验: 1.VB中的字符编码是在内部自动转换的,所以不要在VB内部去测试其发送的数据。可以采用COM1,2端口用连线跳接的方式直接捕获其二进制值,这样才能清晰的看到VB发送了什么数据。(如果你还没有应用成功,处于调试阶段) 2.要保证每一个端口初始化参数的正确性,任何一个和编程口的设置不一样都不能成功通信。
如下是我的代码 Dim keyin$ Dim SXD$ Dim RXD$
Private Sub Command1_Click() keyin$ = InputBox$("输入通信命令)", "输入对话框", "") MsgBox keyin$ If keyin$ = "" Then GoTo null_keyin ENQ$ = c h *r$(5) T$ = keyin$ Sum$ = chksum(T$) SXD$ = ENQ$ + T$ + Sum$ Text1.Text = SXD$ RXD$ = send_recieve(SXD$) Text2.Text =RXD$ Text3.Text = Sum$ null_keyin: End Sub
Sub Option1_Click() MSComm1.PortOpen = True End Sub
Private Sub delay(delay_N%) For i% = 1 To delay_N% For J% = 1 To 30 xa! = 10 * Sin(10 * J% / 20) Next J% Next i% End Sub
Private Function chksum$(T$) L = Len(T$) a = 0 For J = 1 To L a = Asc(m i* d$(T$, J, 1)) + a Next J Sum$ = Hex$(a) If Len(Sum$) = 1 Then Sum$ = "0" + Sum$ chksum$ = Right$(Sum$, 2) End Function
Private Function resp_length%(SXD$) comx$ = m i* d$(SXD$, 2, 1) bytelenth% = CInt(m i* d$(SXD$, 8, 1)) If CInt(comx$) = 0 Then L% = bytelenth% * 2 + 4 If CInt(comx$) = 1 Then L% = 1 If CInt(comx$) = 7 Then L% = 1 If CInt(comx$) = 8 Then L% = 1 resp_length% = L% End Function
Private Sub Form_Load() Form1.Caption = "FX2 VB" Text1.Text = "": Text2.Text = "" MSComm1.CommPort = 1 MSComm1.Settings = "9600,e,7,1" MSComm1.RTSEnable = True Option1.Value = True End Sub
Private Sub Option2_Click() MSComm1.PortOpen = False End Sub
Private Function send_recieve(SXD$) MSComm1.Output = SXD$ Call delay(1000) resp_len% = resp_length%(SXD$) MSComm1.InputLen = resp_len% RXD$ = MSComm1.Input send_recieve = RXD$ End Function
|