在VB中訪問NETLINK并讀寫S7300 PLC數據
無錫市北辰自動化技術有限公司 張鵬 2007-10-16
一、概述
Hilscher NETLINK用于將西門子MPI協議轉換為以太網TCP/IP協議,并提供公開的無需授權的驅動函數庫。
NETLINK有三種應用:
1、對于僅僅需要STEP7編程監控和WINCC監控,安裝IBHNET127驅動即可,該驅動安裝后將在控制面板的Set PG/PC Interface中添加IBHNet MPI/PPI/Profibus三個驅動連接;將STEP7(S7 ONLINE)和WINCC(MPI)的訪問點指向以上驅動連接即可。
2、對于第三方組態軟件(如KingView、iFix等)通過NETLINK訪問PLC,選擇我公司開發的OPCServer。
3、對于VB或者VC++(6.0以上版本)的自行開發界面,有兩種方法實現通訊:
l 調用Hilscher提供的IP Driver驅動函數庫進行通訊;
l 使用winsock控件進行通訊;
本文對在VB6.0中通過Hilscher IP Driver驅動庫讀寫S7300/400 PLC數據的基本開發步驟作簡要描述,具體資料可以參考NETLINK光盤netDEVICE System Software中的Nlmpi_pie.pdf和Drv_Ip.pdf文件,該光盤可到 http://www.sharifulalam.com/co/beichen-automation/index_download.asp 頁面中下載。
二、平臺和配置
1、平臺:WINDOW2000+SP4,Microsoft VB6.0;
2、軟件和驅動安裝:Hilscher SYCON軟件和IP Driver;
3、硬件要求:NETLINK電纜一根,西門子S7300 CPU一臺(如CPU314),以太網交換機一臺(如TP-LINK),以太網電纜;
4、系統配置:如下圖所示
三、NETLINK參數配置
如上圖所示,將計算機網卡的IP地址配置為192.168.1.10,將NETLINK的RJ45端口鏈接到交換機端口上,另一端插入CPU314的MPI通訊口,NETLINK是由CPU314的MPI口供電的。如果CPU上已經連接了其他監控設備如觸摸屏,則可以選用西門子帶編程口的網絡插頭。
在NETLINK鏈接到MPI端口后的三分鐘內(上電三分鐘內)運行[開始]-[程序]-[Hilscher IP Driver]-[NetIdent Demo Program],點擊[Start Poll]按鈕自動查找網絡上的NETLINK,找到后將會顯示NETLINK信息,NETLINK出廠默認IP地址為0.0.0.0,選擇顯示的NETLINK并點擊[Set IP]按鈕,設置IP地址為192.168.1.88;如果軟件找不到NETLINK,請用PING命令檢查網絡是否鏈接正確。
注意1:通過NetIdent設定的IP地址是臨時的,在NETLINK再次上電后將自動恢復到原來的IP地址;
注意2:NETLINK上電的三分鐘內允許通過NetIdent設定其IP地址,三分鐘后設定將被拒絕;
設定好NETLINK的IP地址后運行[開始]-[程序]-[SyCon System Configurator],新建項目并添加NETLINK設備,雙擊NETLINK并設定網絡參數,IP地址設為192.168.1.88,選擇自動檢測接口和自動速率識別,NETLINK的MPI地址設定為1(注意不要和MPI網絡上其他站點地址沖突);設定好參數后將其下載到NETLINK。(具體可以參考《NetLINK和IBHNet驅動在SIEMENS STEP7 WINCC中的使用說明.doc》中的描述)
注意3:通過SYCON軟件設定的IP地址是永久固定的,在NETLINK再次上電后不會改變;
四、IP Driver參數配置
運行[開始]-[程序]-[Hilscher IP Driver]-[IP Driver Setup],在Connection 0中輸入NETLINK的IP地址:192.168.1.88、1099、TCP、Client、5000;
運行[開始]-[程序]-[Hilscher IP Driver]-[IP Driver Test],在菜單[Connection select]中選擇Connection 0,連接后進行其他菜單的測試,如[Driver Info]等,如果測試正常說明IP Driver已連接到NETLINK。
五、VB應用
應用舉例:
1、 按下[循環啟動]按鈕后周期性讀取MW0的數值(間隔100ms),直到按下[停止]按鈕。
2、 按下[寫入新值]按鈕命令將新值寫入MW0。
3、 [復位NETLINK]按鈕初始化NETLINK。
演示界面如下圖所示:
開發步驟:
1、 新建VB EXE工程,將NETLINK光盤中Api\Demo\VBASIC32\CIFUSER.BAS模板文件復制到VB工程中并取消只讀屬性;然后添加到工程中,打開CIFUSER.BAS模板,加入以下常數申明:
'新增常數
Public Const TASK_TDT_UINT8 = 5
Public Const TASK_TFC_READ = 1
Public Const TASK_TFC_WRITE = 2
2、 新建模塊Module1,添加以下公共變量和API函數:
Public Const usSize = 288 '消息長度常數=288
Public SndMsgRead As MSG_STRUC '讀取MW0數據的消息
Public SndMsgWrite As MSG_STRUC '寫MWO數據的消息
Public SndMsgReset As MSG_STRUC '復位NETLINK的消息
Public RcvMsg As MSG_STRUC '接收消息
'內存拷貝API
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
3、 在Form1代碼窗口中添加讀寫控制變量、三個消息初始化函數、NETLINK鏈接和讀寫函數(請參考Nlmpi_pie.pdf文件):
Dim bNetLink_Connected As Boolean 'NETLINK鏈接標記
Dim bStartRead As Boolean '開始循環讀取標記
Dim bWrite As Boolean '寫數據標記
'初始化讀MW0數據的消息
Private Function Initial_SndMsgRead()
SndMsgRead.rx = 3 '接收號=3
SndMsgRead.tx = 255 '發送號=255
SndMsgRead.ln = 8 '讀數據長度=8
SndMsgRead.nr = 0 '消息號
SndMsgRead.a = 0 '應答號=0
SndMsgRead.f = 0 '錯誤號=0
SndMsgRead.b = 0 '命令碼=16#33(M區數據)
SndMsgRead.e = 0 '擴展號=0
SndMsgRead.data(0) = 2 'S7300 CPU的MPI地址=2
SndMsgRead.data(1) = 0 '數據區=0
SndMsgRead.data(2) = 0 'M區起始地址=0(起始地址 MOD 256)
SndMsgRead.data(3) = 0 'M區起始地址=0(起始地址 / 256)
SndMsgRead.data(4) = 0 '數據索引=0(僅用于DB區)
SndMsgRead.data(5) = 2 '讀取的字節數=2 (MW0)
SndMsgRead.data(6) = TASK_TDT_UINT8 '數據類型=TASK_TDT_UINT8(字節)
SndMsgRead.data(7) = TASK_TFC_READ '功能號=TASK_TFC_READ(讀數據)
End Function
'初始化寫MW0數據的消息
Private Function Initial_SndMsgWrite()
SndMsgWrite.rx = 3 '接收號
SndMsgWrite.tx = 255 '發送號
SndMsgWrite.ln = 10 '寫數據長度=10
SndMsgWrite.nr = 0 '消息號
SndMsgWrite.a = 0 '應答號=0
SndMsgWrite.f = 0 '錯誤號=0
SndMsgWrite.b = 0 '命令碼=16#33(M區數據)
SndMsgWrite.e = 0 '擴展號=0
SndMsgWrite.data(0) = 2 'S7300 CPU的MPI地址=2
SndMsgWrite.data(1) = 0 '數據區=0
SndMsgWrite.data(2) = 0 'M區起始地址=0(起始地址 MOD 256)
SndMsgWrite.data(3) = 0 'M區起始地址=0(起始地址 / 256)
SndMsgWrite.data(4) = 0 '數據索引=0(僅用于DB區)
SndMsgWrite.data(5) = 0 '要寫的字節數=2 (MW0)
SndMsgWrite.data(6) = TASK_TDT_UINT8 'TASK_TDT_UINT8
SndMsgWrite.data(7) = TASK_TFC_WRITE 'TASK_TFC_WRITE
SndMsgWrite.data(8) = 0 '待寫數據低字節=0
SndMsgWrite.data(9) = 0 '待寫數據高字節=0
End Function
'初始化復位NETLINK消息
Private Function Initial_SndMsgReset()
SndMsgReset.rx = 0 '接收號=0(NETLINK 系統)
SndMsgReset.tx = 255 '發送號
SndMsgReset.ln = 1 '數據長度
SndMsgReset.nr = 1 '消息號
SndMsgReset.a = 0 '應答號=0
SndMsgReset.f = 0 '錯誤號=0
SndMsgReset.b = 1 '命令碼=1
SndMsgReset.e = 0 '擴展號=0
SndMsgReset.data(0) = 1 '=1
End Function
'NETLINK鏈接
Private Function NetLINK_Connect()
Dim sRet As Integer
sRet = DevOpenDriver(0) '打開驅動
If sRet = DRV_NO_ERROR Then
sRet = DevInitBoard(0, 0) '初始化板卡
If sRet = DRV_NO_ERROR Then
bNetLink_Connected = True '設置NETLINK鏈接標記
Else
MsgBox "找不到NETLINK!", vbCritical + vbOKOnly, "錯誤"
DevExitBoard 0 '退出板卡
DevCloseDriver 0 '關閉驅動
End If
Else
MsgBox "找不到NETLINK驅動!", vbCritical + vbOKOnly, "錯誤"
DevExitBoard 0
DevCloseDriver 0
End If
End Function
'讀MW0數據
Private Function ReadValue()
Dim sRet As Integer, RcvData(0 To 1) As Byte, Val_INT16 As Integer
sRet = DevPutMessage(0, SndMsgRead, 500) '發送讀取數據的消息
If sRet = DRV_NO_ERROR Then '如果發送消息無錯誤
sRet = DevGetMessage(0, usSize, RcvMsg, 500) '接收返回消息
'如果接收無錯誤且消息無錯誤且功能號為讀取消息則接收消息中的MW0數據
If sRet = DRV_NO_ERROR And RcvMsg.f = 0 And RcvMsg.data(7) = TASK_TFC_READ Then
RcvData(0) = RcvMsg.data(9) '注意高低字節的顛到
RcvData(1) = RcvMsg.data(8)
CopyMemory Val_INT16, RcvData(0), 2
Text_Value.Text = Val_INT16
End If
End If
End Function
'寫MW0數據
Private Function WriteValue()
Dim sRet As Integer, SndData(0 To 1) As Byte, Val_INT16 As Integer
Val_INT16 = Int(Text_Setting.Text)
CopyMemory SndData(0), Val_INT16, 2
SndMsgWrite.data(8) = SndData(1) '注意高低字節的顛到
SndMsgWrite.data(9) = SndData(0)
sRet = DevPutMessage(0, SndMsgWrite, 500) '發送寫數據的消息
If sRet = DRV_NO_ERROR Then '如果發送消息無錯誤
sRet = DevGetMessage(0, usSize, RcvMsg, 500) '接收返回消息
End If
bWrite = False '復位寫值標志
End Function
4、 在Form1添加定時器Timer1,設定周期為100ms;在Timer1的執行事件中添加以下代碼:
'定時器1的執行代碼
Private Sub Timer1_Timer()
If bNetLink_Connected = False Then '如果NetLink沒有鏈接則退出定時器執行
Exit Sub
End If
If bWrite = True Then '如果有寫值請求
WriteValue '寫MW0值
ElseIf bStartRead = True Then '否則檢查是否啟動了讀循環
ReadValue '讀MW0值
End If
End Sub
5、 添加[循環讀取]、[停止]、[寫入新值]、[復位NETLINK]按鈕的動作
'循環讀取按鈕
Private Sub Command_read_Click()
If bNetLink_Connected = False Then '如果NETLINK未鏈接
NetLINK_Connect '鏈接NETLINK
End If
If bNetLink_Connected = True Then '如果已鏈接
bStartRead = True '啟動循環讀
End If
End Sub
'停止按鈕
Private Sub Command_stop_Click()
bStartRead = False
End Sub
'寫入新值按鈕
Private Sub Command_set_Click()
If IsNumeric(Text_Setting.Text) Then
bWrite = True
Else
MsgBox "設定值錯誤,范圍:-32768至32767", vbExclamation + vbOKOnly, "格式錯誤"
End If
End Sub
'復位NETLINK按鈕
Private Sub Command_reset_Click()
Dim sRet As Integer
If bStartRead = True Then
MsgBox "復位NETLINK前請先停止循環讀取。", vbInformation + vbOKOnly, "提示"
Else
sRet = DevPutMessage(0, SndMsgReset, 500) '發送復位NETLINK的消息
End If
End Sub
6、 在Form1的Load事件中添加初始化代碼:
'Form1裝載
Private Sub Form_Load()
bStartRead = False
bWrite = False
bNetLink_Connected = False
Text_Value.Text = 0
Text_Setting.Text = 0
Initial_SndMsgRead '初始化讀取數據消息
Initial_SndMsgWrite '初始化寫值消息
Initial_SndMsgReset '初始化復位消息
NetLINK_Connect '鏈接NETLINK
End Sub
六、注意事項
1、 注意發送消息中的數據起始地址的高低字節顛到和接收消息中數據區的高低字節顛到;
2、 定時器事件在操作系統繁忙時容易被中斷執行,可以適當提高進程和線程的優先級來保證數據的更新速率,在Form_Load()中添加以下代碼:
Dim hThread As Long, hProcess As Long
hThread = GetCurrentThread
hProcess = GetCurrentProcess
SetThreadPriority hThread, THREAD_PRIORITY_HIGHEST
SetPriorityClass hProcess, HIGH_PRIORITY_CLASS
在Module1中添加以下聲明:
Public Const THREAD_BASE_PRIORITY_IDLE = -15
Public Const THREAD_BASE_PRIORITY_LOWRT = 15
Public Const THREAD_BASE_PRIORITY_MIN = -2
Public Const THREAD_BASE_PRIORITY_MAX = 2
Public Const THREAD_PRIORITY_LOWEST = THREAD_BASE_PRIORITY_MIN
Public Const THREAD_PRIORITY_HIGHEST = THREAD_BASE_PRIORITY_MAX
Public Const THREAD_PRIORITY_BELOW_NORMAL = (THREAD_PRIORITY_LOWEST + 1)
Public Const THREAD_PRIORITY_ABOVE_NORMAL = (THREAD_PRIORITY_HIGHEST - 1)
Public Const THREAD_PRIORITY_IDLE = THREAD_BASE_PRIORITY_IDLE
Public Const THREAD_PRIORITY_NORMAL = 0
Public Const THREAD_PRIORITY_TIME_CRITICAL = THREAD_BASE_PRIORITY_LOWRT
Public Const HIGH_PRIORITY_CLASS = &H80
Public Const IDLE_PRIORITY_CLASS = &H40
Public Const NORMAL_PRIORITY_CLASS = &H20
Public Const REALTIME_PRIORITY_CLASS = &H100
Public Declare Function SetThreadPriority Lib "kernel32" (ByVal hThread As Long, ByVal nPriority As Long) As Long
Public Declare Function SetPriorityClass Lib "kernel32" (ByVal hProcess As Long, ByVal dwPriorityClass As Long) As Long
3、 無論是讀取數據還是寫數據,發送和接收消息函數必須成對出現;
4、 在實際的通訊中如果網絡中斷(譬如交換機斷電,插拔網絡插頭)將會導致發送和接收消息函數出錯,其返回值sRet大于等于10000(網絡錯誤),此時需要主動發出NETLINK復位消息;發出復位消息后一般需要等待5秒鐘后再次進行鏈接;
5、 在每次嘗試NETLINK鏈接前為了避免找不到NETLINK導致的驅動函數超時返回,可以先采用NetIdent協議(參考Ni_pie.pdf文件,使用Winsock控件)廣播網絡上的NETLINK,找到NETLINK后再嘗試鏈接,這樣可以提高通訊效率;
6、 一次讀取地址連續的數據包(不要超過240個字節)比多次讀取單個數據的效率要高的多;
7、 發送和返回的響應消息的消息號Nr是對應的,可以用Nr來判斷多個讀寫任務的響應消息;
8、 如果一臺計算機需要同時訪問多個NETLINK通訊,建議采用VC++6.0開發,采用多線程技術;
七、聯系我們
無錫市北辰自動化技術有限公司
江蘇省滴翠路100號無錫市國家工業設計園創意園A幢903
電話:0510-85166823,85162669,聯系人:王海波,張鵬
傳真:0510-85166813
Email:beichen@beichen-automation.com,網址:www.beichen-automation.com