摘要:电阻上限的地址是 10 和 11 。这里有个让人想不明白的地方,读取电阻的地址是 02 、 03 ,设置的时候却是 03 单个寄存器,居然也能获取到正确的数据?真是让人有点懵圈。最后再把获取到的数据和变量连接起来:
以下咱们就拿永鹏的直流电阻仪器来做个例子,讲讲它的功能。
1,A801的设置
怎么在 AC801 里加上基于 485 的 modbus 通讯呢?A801 有一个 485 的接口(这资料是从官网的《AC801 智能机械可编程控制器用户手册》来的):
接下来说明如何在软件里面添加设备:
在 Device 里添加 Modbus Master ,把它当作基于 485 的 modbus 主站。然后再双击 Modbus Master ,来设置通讯格式:
接下来再点击 Network Configuration ,在右边的窗口里给 COM1(RS485) 下面添加 Modbus 设备,这样就能添加 Modbus 从站啦。
之后按照被连接设备的协议,来给设备做通讯设置,双击 modbus_protocol :首先得把站号设置好:
然后进行写入和读取寄存器的设置:
永鹏直流电阻仪器读取电阻数据的地址是 02 和 03 ;
锁定量程的地址是 05 ,设置档位的地址是 07 ,
电阻下限的地址是 08 和 09 ,
电阻上限的地址是 10 和 11 。这里有个让人想不明白的地方,读取电阻的地址是 02 、 03 ,设置的时候却是 03 单个寄存器,居然也能获取到正确的数据?真是让人有点懵圈。最后再把获取到的数据和变量连接起来:
AC801的连接就说明完成了。
二,AM500的设置
接下来要对 AM500 进行说明,下面是 AM500 在软件中建立连接的相关说明(这资料来自官网的《中型 PLC 编程软件使用手册》):
这里要把串口通信格式改成跟被连接设备相同的通信格式。
在这里进行寄存器的设置,是用%MW的寄存器来发送和接收数据。
%MW300是用来输入发送数据的字节数目,一旦输入了数值,马上就会以%MW301为起始地址,按照%MW300设置的字节数据进行发送;
%MW0是回传数据的字节长度,回传的数据会显示在以%MW1为起始地址的数据里。不过每次回采数据后,得把%MW0清零,要不然就会一直在%MW1后面不停地添加数据。这里不像 AC801 能自己读写程序,得在程序里面对%MW0和%MW300的数据进行处理。下面是对%MW0和%MW300数据连接的变量:
VAR_GLOBALEND_VARVAR_GLOBAL PERSISTENT RETAIN w_Read AT %MW0 : WORD ;//串口反馈的字节长度,需要及时清零,不然会一直在以MW1开始的地址进行累积 w_Read_Bit AT %MW1 : ARRAY [0..19] OF WORD ;//串口反馈的数据 w_Write AT %MW300 : WORD ;//写入串口的字节,输入字节长度,才会写入数据 w_Write_Bit AT %MW301 : ARRAY [0..19] OF WORD ;//以MV301为起始地址,写入串口的信息END_VAR接下来要对电阻仪器初始化设置的功能块进行操作,包括设置锁定以及设置档位。设置锁定量程的发送数据是这样的,比如设置电阻锁定量程为 01 10 00 05 00 01 02 00 01 67 c5 。其中 01 是站号,10 是写数据,00 05 是锁定量程的地址 05 ,00 01 表示锁定量程只有一个地址,02 表示发送两个字节,00 01 是发送的数据,67 c5 是 Modbus 协议的 CRC 校验码(推荐网址:http://www.ip33.com/crc.html)
设置档位的发送数据是 01 10 00 07 00 01 02 00 03 e7 e6 。01 是站号,10 是写数据,00 07 是设置档位的地址,00 01 代表设置的档位只有一个地址,02 表示发送两个字节,00 03 表示设定的档位是 3 (档位 0 是 0.001 千欧姆,档位 1 是 0.0001 千欧姆,档位 2 是 0.01 欧姆,档位 3 是 0.001 欧姆,档位 4 是 0.0001 欧姆,档位 5 是 0.01 毫欧姆),e7 e6 是 Modbus 协议的 CRC 校验码。
以下是设置初始化的代码:
//自由协议读取485讯息功能块//设置档位 设置上下限 锁定FUNCTION_BLOCK FB_Serial_SetParVAR_INPUT b_Start : BOOL ;//进行读取END_VARVAR_OUTPUT b_Busy : BOOL ;//On:正在读取中 b_Done : BOOL ;//On:执行完成 b_Error_UnConnect : BOOL ;//没有连接上直流电阻仪器END_VARVAR ui_Loop : UINT ;//读取的流程 Ton_Delay_unKeep : ARRAY[0..5] OF TON ;//读取信息的时间间隔 w_Level : WORD ;//档位0 0.001k欧姆 档位1 0.0001k欧姆 档位2 0.01欧姆 档位3 0.001欧姆 档位4 0.0001欧姆 档位5 0.01m欧姆 r_TRIG_Start : R_TRIG ;//启动运行触发上升沿 END_VAR以上是变量的设置,以下是程序:
//清除读取寄存器标志延时Ton_Delay_unKeep[0](IN:=Serial.w_Read=0, PT:=T#100MS);//等待回传数据延时Ton_Delay_unKeep[1](IN:=ui_Loop=400, PT:=T#500MS);//写入设置档位2延时Ton_Delay_unKeep[2](IN:=ui_Loop=1200, PT:=T#500MS); //写入锁定档位延时Ton_Delay_unKeep[3](IN:=ui_Loop=2200, PT:=T#500MS); //写入锁定档位延时Ton_Delay_unKeep[4](IN:=ui_Loop=3200, PT:=T#500MS); r_TRIG_Start(CLK:=b_Start);CASE ui_Loop OF 0://判定读取是否有开启 IF r_TRIG_Start.Q THEN b_Done R= TRUE; b_Busy S= TRUE; b_Error_UnConnect R= TRUE; IF NOT b_Done AND b_Busy AND NOT b_Error_UnConnect THEN ui_Loop := 100; END_IF END_IF 100://开始设置 Serial.w_Write_Bit[0]:=16#0301;//01代表串口站号1 03代表读取多个寄存器 Serial.w_Write_Bit[1]:=16#0200;//0002代表读取的起始地址,02 03是电阻的读取地址 Serial.w_Write_Bit[2]:=16#0200;//0002代表读取的个数,则读取02 03两个寄存器 Serial.w_Write_Bit[3]:=16#CB65;//CB65是01 03 00 02 00 02的CRC16 Modbus校验码 IF Serial.w_Write_Bit[0]=16#0301 AND Serial.w_Write_Bit[1]=16#0200 AND Serial.w_Write_Bit[2]=16#0200 AND Serial.w_Write_Bit[3]=16#CB65 THEN ui_Loop := 200; END_IF 200://将读取的寄存器清零 并且延时 Serial.w_Read:= 0; Serial.w_Read_Bit[0]:= 0; Serial.w_Read_Bit[1]:= 0; Serial.w_Read_Bit[2]:= 0; Serial.w_Read_Bit[3]:= 0; Serial.w_Read_Bit[4]:= 0; Serial.w_Read_Bit[5]:= 0; Serial.w_Read_Bit[6]:= 0; Serial.w_Read_Bit[7]:= 0; Serial.w_Read_Bit[8]:= 0; Serial.w_Read_Bit[9]:= 0; IF Serial.w_Read=0 AND Serial.w_Read_Bit[0]=0 AND Serial.w_Read_Bit[1]=0 AND Serial.w_Read_Bit[2]=0 AND Serial.w_Read_Bit[3]=0 AND Serial.w_Read_Bit[4]=0 AND Serial.w_Read_Bit[5]=0 AND Serial.w_Read_Bit[6]=0 AND Serial.w_Read_Bit[7]=0 AND Serial.w_Read_Bit[8]=0 AND Serial.w_Read_Bit[9]=0 AND Ton_Delay_unKeep[0].Q THEN ui_Loop := 300; END_IF 300://写入寄存器值赋8,开始读取 Serial.w_Write:= 8; ui_Loop := 400; 400://等待反馈数据延时 IF Ton_Delay_unKeep[1].Q THEN ui_Loop := 500; END_IF 500://判断读取数据的首个寄存器是否等于16#0301 IF Serial.w_Read_Bit[0]=16#0301 THEN ui_Loop := 2000; ELSE b_Error_UnConnect S= TRUE; b_Busy R= TRUE; IF b_Error_UnConnect AND NOT b_Busy THEN ui_Loop := 0; END_IF END_IF 2000://锁定档位 Serial.w_Write_Bit[0]:=16#1001;//01代表串口站号1 10代表写寄存器 Serial.w_Write_Bit[1]:=16#0500;//0007代表锁定量程的地址 Serial.w_Write_Bit[2]:=16#0100;//0001代表写入一个寄存器地址到0005 Serial.w_Write_Bit[3]:=16#0002;//低位02代表写入两个字节 高位00和下面的低位都是写入05的值 Serial.w_Write_Bit[4]:=16#6701;//低位01代表锁定档位 高位67和下面的低位都是CRC校验码 Serial.w_Write_Bit[5]:=16#00C5;//低位C5是CRC校验码 IF Serial.w_Write_Bit[0]=16#1001 AND Serial.w_Write_Bit[1]=16#0500 AND Serial.w_Write_Bit[2]=16#0100 AND Serial.w_Write_Bit[3]=16#0002 AND Serial.w_Write_Bit[4]=16#6701 AND Serial.w_Write_Bit[5]=16#00C5 THEN ui_Loop := 2100; END_IF 2100://写入锁定档位 Serial.w_Write:= 11; ui_Loop := 2200; 2200://写入锁定档位延时 IF Ton_Delay_unKeep[3].Q THEN ui_Loop := 2300; END_IF 2300://清除读取标志 Serial.w_Read:= 0; Serial.w_Read_Bit[0]:= 0; Serial.w_Read_Bit[1]:= 0; Serial.w_Read_Bit[2]:= 0; Serial.w_Read_Bit[3]:= 0; Serial.w_Read_Bit[4]:= 0; Serial.w_Read_Bit[5]:= 0; Serial.w_Read_Bit[6]:= 0; Serial.w_Read_Bit[7]:= 0; Serial.w_Read_Bit[8]:= 0; Serial.w_Read_Bit[9]:= 0; IF Serial.w_Read=0 AND Serial.w_Read_Bit[0]=0 AND Serial.w_Read_Bit[1]=0 AND Serial.w_Read_Bit[2]=0 AND Serial.w_Read_Bit[3]=0 AND Serial.w_Read_Bit[4]=0 AND Serial.w_Read_Bit[5]=0 AND Serial.w_Read_Bit[6]=0 AND Serial.w_Read_Bit[7]=0 AND Serial.w_Read_Bit[8]=0 AND Serial.w_Read_Bit[9]=0 AND Ton_Delay_unKeep[0].Q THEN ui_Loop := 1000; END_IF 1000://设置档03 Serial.w_Write_Bit[0]:=16#1001;//01代表串口站号1 10代表写寄存器 Serial.w_Write_Bit[1]:=16#0700;//0007代表档位的地址 Serial.w_Write_Bit[2]:=16#0100;//0001代表写入一个寄存器地址到0007 Serial.w_Write_Bit[3]:=16#0002;//低位02代表写入两个字节 高位00和下面的低位都是写入07的值 Serial.w_Write_Bit[4]:=16#E703;//低位03代表档位2 高位E7和下面的低位都是CRC校验码 Serial.w_Write_Bit[5]:=16#00E6;//低位E6是CRC校验码 IF Serial.w_Write_Bit[0]=16#1001 AND Serial.w_Write_Bit[1]=16#0700 AND Serial.w_Write_Bit[2]=16#0100 AND Serial.w_Write_Bit[3]=16#0002 AND Serial.w_Write_Bit[4]=16#E703 AND Serial.w_Write_Bit[5]=16#00E6 THEN ui_Loop := 1100; END_IF 1100://写入设置档位2 Serial.w_Write:= 11; ui_Loop := 1200; 1200://写入设置档位2延时 IF Ton_Delay_unKeep[2].Q THEN ui_Loop := 1300; END_IF 1300://清除读取标志 Serial.w_Read:= 0; Serial.w_Read_Bit[0]:= 0; Serial.w_Read_Bit[1]:= 0; Serial.w_Read_Bit[2]:= 0; Serial.w_Read_Bit[3]:= 0; Serial.w_Read_Bit[4]:= 0; Serial.w_Read_Bit[5]:= 0; Serial.w_Read_Bit[6]:= 0; Serial.w_Read_Bit[7]:= 0; Serial.w_Read_Bit[8]:= 0; Serial.w_Read_Bit[9]:= 0; IF Serial.w_Read=0 AND Serial.w_Read_Bit[0]=0 AND Serial.w_Read_Bit[1]=0 AND Serial.w_Read_Bit[2]=0 AND Serial.w_Read_Bit[3]=0 AND Serial.w_Read_Bit[4]=0 AND Serial.w_Read_Bit[5]=0 AND Serial.w_Read_Bit[6]=0 AND Serial.w_Read_Bit[7]=0 AND Serial.w_Read_Bit[8]=0 AND Serial.w_Read_Bit[9]=0 AND Ton_Delay_unKeep[0].Q THEN ui_Loop := 4000; END_IF 3000://设置档03 Serial.w_Write_Bit[0]:=16#1001;//01代表串口站号1 10代表写寄存器 Serial.w_Write_Bit[1]:=16#0800;//0007代表档位的地址 Serial.w_Write_Bit[2]:=16#0200;//0001代表写入一个寄存器地址到0007 Serial.w_Write_Bit[3]:=16#0004;//低位02代表写入两个字节 高位00和下面的低位都是写入07的值 Serial.w_Write_Bit[4]:=16#0300;//低位03代表档位2 高位E7和下面的低位都是CRC校验码 Serial.w_Write_Bit[5]:=16#00E8;//低位E6是CRC校验码 IF Serial.w_Write_Bit[0]=16#1001 AND Serial.w_Write_Bit[1]=16#0800 AND Serial.w_Write_Bit[2]=16#0200 AND Serial.w_Write_Bit[3]=16#0004 AND Serial.w_Write_Bit[4]=16#0300 AND Serial.w_Write_Bit[5]=16#00E8 THEN ui_Loop := 3100; END_IF 3100://写入设置档位2 Serial.w_Write:= 11; ui_Loop := 3200; 3200://写入设置档位2延时 IF Ton_Delay_unKeep[4].Q THEN ui_Loop := 3300; END_IF 3300://清除读取标志 Serial.w_Read:= 0; Serial.w_Read_Bit[0]:= 0; Serial.w_Read_Bit[1]:= 0; Serial.w_Read_Bit[2]:= 0; Serial.w_Read_Bit[3]:= 0; Serial.w_Read_Bit[4]:= 0; Serial.w_Read_Bit[5]:= 0; Serial.w_Read_Bit[6]:= 0; Serial.w_Read_Bit[7]:= 0; Serial.w_Read_Bit[8]:= 0; Serial.w_Read_Bit[9]:= 0; IF Serial.w_Read=0 AND Serial.w_Read_Bit[0]=0 AND Serial.w_Read_Bit[1]=0 AND Serial.w_Read_Bit[2]=0 AND Serial.w_Read_Bit[3]=0 AND Serial.w_Read_Bit[4]=0 AND Serial.w_Read_Bit[5]=0 AND Serial.w_Read_Bit[6]=0 AND Serial.w_Read_Bit[7]=0 AND Serial.w_Read_Bit[8]=0 AND Serial.w_Read_Bit[9]=0 AND Ton_Delay_unKeep[0].Q THEN ui_Loop := 4000; END_IF 4000:// b_Busy R= TRUE; b_Done S= TRUE; ui_Loop := 0;END_CASE接下来是电阻的不断读取设置:
读取电阻的发送数据是 01 03 00 02 00 02 65 cb 。01 是站号,03 表示读多个寄存器,00 02 是电阻的起始地址 02 ,00 02 代表连续的两个地址,也就是 02 和 03 ,65 cb 是 Modbus 协议的 CRC 校验码。所以说前面 AC801 读取起始地址是 03 就能获得正确的电阻数据,这实在是很奇怪,要学习的东西还有好多呢。
以下是读取电阻的代码:
//自由协议读取485讯息功能块//读取电阻FUNCTION_BLOCK FB_Serial_ReadOhmVAR_INPUT b_Start : BOOL ;//进行读取 b_Reset : BOOL ;//对读取的寄存器进行复位END_VARVAR_OUTPUT b_Busy : BOOL ;//On:正在读取中 b_ResetDone : BOOL ;//重置完成 w_Level : WORD ;//档位0 0.001k欧姆 档位1 0.0001k欧姆 档位2 0.01欧姆 档位3 0.001欧姆 档位4 0.0001欧姆 档位5 0.01m欧姆 dw_ShowOhm : DWORD ;//电子显示屏显示的数值 不包含小数点END_VARVAR ui_Loop : UINT ;//读取的流程 Ton_Delay_unKeep : TON ;//读取信息的时间间隔 Rtrg_Reset : R_TRIG ;//复位回采寄存器信号END_VAR以上是变量,以下是功能块代码:
Ton_Delay_unKeep(IN:=Serial.w_Read=0, PT:=T#100MS);Rtrg_Reset( CLK:=b_Reset);CASE ui_Loop OF 0://判定读取是否有开启 //进行电阻信号的读取 IF b_Start AND NOT b_Reset THEN b_Busy S= TRUE; IF b_Busy THEN ui_Loop := 100; END_IF END_IF //当不进行电阻信号的读取以及不进行复位回采的寄存器标志时候 //停止运行 IF NOT b_Start AND NOT b_Reset THEN b_Busy R= TRUE; END_IF //进行回采信号的重置 IF Rtrg_Reset.Q THEN ui_Loop := 1000; END_IF 100://开始设置 b_ResetDone R= TRUE; Serial.w_Write_Bit[0]:=16#0301;//01代表串口站号1 03代表读取多个寄存器 Serial.w_Write_Bit[1]:=16#0200;//0002代表读取的起始地址,02 03是电阻的读取地址 Serial.w_Write_Bit[2]:=16#0200;//0002代表读取的个数,则读取02 03两个寄存器 Serial.w_Write_Bit[3]:=16#CB65;//CB65是01 03 00 02 00 02的CRC16 Modbus校验码 IF Serial.w_Write_Bit[0]=16#0301 AND Serial.w_Write_Bit[1]=16#0200 AND Serial.w_Write_Bit[2]=16#0200 AND Serial.w_Write_Bit[3]=16#CB65 THEN ui_Loop := 200; END_IF 200://将读取的寄存器清零 并且延时 Serial.w_Read:= 0; IF Serial.w_Read=0 AND Ton_Delay_unKeep.Q THEN ui_Loop := 300; END_IF 300://写入寄存器值赋8,开始读取 Serial.w_Write:= 8; ui_Loop := 400; 400://处理数据 //回采数据第一个字节应该是16#0103,则01代表串口站号1 03代表读取多个寄存器 //回采数据第二个字节地位是字节的长度,高位是数组的档位 //档位0 0.001k欧姆 档位1 0.0001k欧姆 档位2 0.01欧姆 档位3 0.001欧姆 档位4 0.0001欧姆 档位5 0.01m欧姆 w_Level:=SWAP16(Serial.w_Read_Bit[1]AND(16#FF00)); //回采数据第三个字节以及第四个字节的低位是当前的显示值 dw_ShowOhm:=WORD_TO_DWORD(Serial.w_Read_Bit[2])+WORD_TO_DWORD(Serial.w_Read_Bit[3]AND(16#00FF)); ui_Loop := 0; 1000://重置前进行信号的处理 b_ResetDone R= TRUE; IF NOT b_ResetDone THEN ui_Loop := 1100; END_IF 1100://开始复位重置 Serial.w_Read:= 0; Serial.w_Read_Bit[0]:= 0; Serial.w_Read_Bit[1]:= 0; Serial.w_Read_Bit[2]:= 0; Serial.w_Read_Bit[3]:= 0; Serial.w_Read_Bit[4]:= 0; Serial.w_Read_Bit[5]:= 0; Serial.w_Read_Bit[6]:= 0; Serial.w_Read_Bit[7]:= 0; Serial.w_Read_Bit[8]:= 0; Serial.w_Read_Bit[9]:= 0; IF Serial.w_Read=0 AND Serial.w_Read_Bit[0]=0 AND Serial.w_Read_Bit[1]=0 AND Serial.w_Read_Bit[2]=0 AND Serial.w_Read_Bit[3]=0 AND Serial.w_Read_Bit[4]=0 AND Serial.w_Read_Bit[5]=0 AND Serial.w_Read_Bit[6]=0 AND Serial.w_Read_Bit[7]=0 AND Serial.w_Read_Bit[8]=0 AND Serial.w_Read_Bit[9]=0 AND Ton_Delay_unKeep.Q THEN ui_Loop := 1200; END_IF 1200://重置完成 b_ResetDone S= TRUE; ui_Loop := 0;END_CASE汇川AC801以及汇川AM500 基于485的Moudbus通讯 PLC论坛-全力打造可编程控制器专业技术论坛 -
来源:PLC技术玩