首先两点要明确一下:
1、硬件得支持看门狗,这一点许多工控机都是支持的;
2、本示例是以某一款工控机为例,不同工控机具体的指令协议可能不同,做参考即可。
这里使用了InpOut硬件接口操作库:
可搜索下载 :
代码:
1 Public Class InpOut 2 3 <DllImport("InpOut32.dll", CharSet:=CharSet.Auto, EntryPoint:="Inp32")> 4 Private Shared Function Inp32(ByVal PortAddress As Short) As Short 5 End Function 6 7 <DllImport("InpOut32.dll", CharSet:=CharSet.Auto, EntryPoint:="Out32")> 8 Private Shared Sub Out32(ByVal PortAddress As Short, ByVal Data As Short) 9 End Sub 10 11 <DllImport("InpOut32.dll", CharSet:=CharSet.Auto, EntryPoint:="IsInpOutDriverOpen")> 12 Private Shared Function IsInpOutDriverOpen() As UInt32 13 End Function 14 15 <DllImport("InpOutx64.dll", CharSet:=CharSet.Auto, EntryPoint:="Inp32")> 16 Private Shared Function Inp32_x64(ByVal PortAddress As Short) As Short 17 End Function 18 19 <DllImport("InpOutx64.dll", CharSet:=CharSet.Auto, EntryPoint:="Out32")> 20 Private Shared Sub Out32_x64(ByVal PortAddress As Short, ByVal Data As Short) 21 End Sub 22 23 <DllImport("InpOutx64.dll", CharSet:=CharSet.Auto, EntryPoint:="IsInpOutDriverOpen")> 24 Private Shared Function IsInpOutDriverOpen_x64() As UInt32 25 End Function 26 27 Dim m_bX64 As Boolean = False 28 29 Sub New() 30 Dim nResult As UInt32 31 Try 32 nResult = IsInpOutDriverOpen() 33 Catch ex As Exception 34 nResult = IsInpOutDriverOpen_x64() 35 If (nResult <> 0) Then 36 m_bX64 = True 37 End If 38 End Try 39 If (nResult = 0) Then 40 Windows.Forms.MessageBox.Show("Unable to open InpOut driver") 41 End If 42 End Sub 43 44 Public Sub read(iPort As Short) 45 Try 46 If (m_bX64) Then 47 Debug.WriteLine(Inp32_x64(iPort).ToString()) 48 Else 49 Debug.WriteLine(Inp32(iPort).ToString()) 50 End If 51 Catch ex As Exception 52 Windows.Forms.MessageBox.Show("An error occured:\n" + ex.Message) 53 End Try 54 End Sub 55 56 Public Sub write(iPort As Short, iData As Short) 57 Try 58 If (m_bX64) Then 59 Out32_x64(iPort, iData) 60 Else 61 Out32(iPort, iData) 62 End If 63 64 Catch ex As Exception 65 Windows.Forms.MessageBox.Show("An error occured:\n" + ex.Message) 66 End Try 67 End Sub 68 69 Sub open() 70 write(&H2E, &H87) 71 write(&H2E, &H1) 72 write(&H2E, &H55) 73 write(&H2E, &H55) '进入MB PNP模式 74 75 write(&H2E, &H7) 76 write(&H2F, &H7) '设定07为逻辑设备 77 write(&H2E, &H71) 78 write(&H2F, &H0) '打开看门狗 79 80 write(&H2E, &H2) 81 write(&H2F, &H2) 82 End Sub 83 84 Sub feed() 85 write(&H2E, &H87) 86 write(&H2E, &H1) 87 write(&H2E, &H55) 88 write(&H2E, &H55) '进入MB PNP模式 89 write(&H2E, &H7) 90 write(&H2F, &H7) '设定07为逻辑设备 91 92 write(&H2E, &H72) 93 write(&H2F, &H0) ' 偏移值72h,里面写00h表示看门狗计时单位为秒;为80h,表示看门狗计时器单位为分,开始喂看门狗, 94 '73 74 为timeout value,如 16秒 95 write(&H2E, &H73) 96 write(&H2F, &H10) '写入需要设置的看门狗的值 97 write(&H2E, &H74) 98 write(&H2F, &H0) 99 100 write(&H2E, &H2) 101 write(&H2F, &H2) 102 End Sub 103 104 Sub close() 105 write(&H2E, &H87) 106 write(&H2E, &H1) 107 write(&H2E, &H55) 108 write(&H2E, &H55) '进入MB PNP模式 109 write(&H2E, &H7) 110 write(&H2F, &H7) '设定07为逻辑设备 111 112 write(&H2E, &H72) 113 write(&H2F, &H0) ' 偏移值72h,里面写00h表示看门狗计时单位为秒;为80h,表示看门狗计时器单位为分,开始喂看门狗, 114 '73 74 为timeout value,如 16秒 115 write(&H2E, &H73) 116 write(&H2F, &H10) '写入需要设置的看门狗的值 117 write(&H2E, &H74) 118 write(&H2F, &H0) 119 120 write(&H2E, &H2) 121 write(&H2F, &H2) 122 End Sub 123 End Class
封装的 WatchDog 类:
1 Imports System.Runtime.InteropServices 2 3 Public Class WatchDog 4 Dim inpout As New InpOut 5 6 Private Sub SetValue(value As Integer) 7 Dim keyPtr = &H2E 8 inpout.write(keyPtr, value) 9 End Sub 10 11 Private Sub SetValue(key As Integer, value As Integer) 12 Dim keyPtr = &H2E 13 Dim valuePtr = &H2F 14 inpout.write(keyPtr, key) 15 inpout.write(valuePtr, value) 16 End Sub 17 18 ''' <summary> 19 ''' (喂狗准备)进入特定值进入配置模式 20 ''' </summary> 21 ''' <returns></returns> 22 Function Ready() As WatchDog 23 SetValue(&H87) 24 SetValue(&H1) 25 SetValue(&H55) 26 SetValue(&H55) 27 Return Me 28 End Function 29 30 ''' <summary> 31 ''' (唤狗)选择和打开dog 32 ''' </summary> 33 ''' <returns></returns> 34 Function [Call]() As WatchDog 35 SetValue(&H7, &H7) '设定07为逻辑设备 36 SetValue(&H71, &H0) '打开看门狗 37 Return Me 38 End Function 39 40 Enum TimeMode 41 Second = &H0 42 Minute = &H1 43 End Enum 44 45 ''' <summary> 46 ''' (喂狗)设置超时时间 47 ''' </summary> 48 ''' <param name="mode"></param> 49 ''' <param name="value"></param> 50 ''' <returns></returns> 51 Function Feed(value As Integer, mode As TimeMode) As WatchDog 52 SetValue(&H72, mode) '设置时间格式 &H0为秒 &H80为分钟 53 Dim bs = BitConverter.GetBytes(value) '时间值最长两个字节 54 SetValue(&H73, bs(0)) 55 SetValue(&H74, If(bs.Count > 1, bs(1), 0)) 56 Return Me 57 End Function 58 59 ''' <summary> 60 ''' 完成 61 ''' </summary> 62 ''' <returns></returns> 63 Function Finish() As WatchDog 64 '退出配置模式 65 SetValue(&H2, &H2) 66 Return Me 67 End Function 68 69 End Class
打开看门狗和喂狗示例:
'看门狗 Dim dog As New UX.Devices.Computer.WatchDog Dim inpout As New UX.Devices.Computer.InpOut Private Sub Button_Click(sender As Object, e As RoutedEventArgs) Select Case CType(sender, FrameworkElement).Tag.ToString Case "ready" inpout.open() 'dog.Ready().Call.Finish() Debug.WriteLine($"callDog@{Now.ToLongTimeString}") Case "feed" inpout.feed() 'dog.Feed(5, WatchDog.TimeMode.Second).Call.Finish() Debug.WriteLine($"feedDog@{Now.ToLongTimeString}") End Select End Sub
界面代码:
<StackPanel HorizontalAlignment="Center" > <Button Content="ready" HorizontalAlignment="Left" VerticalAlignment="Top" Width="46" Height="48" Click="Button_Click" Tag="ready"/> <Button Content="feed" HorizontalAlignment="Left" VerticalAlignment="Top" Width="46" Height="48" Click="Button_Click" Tag="feed"/> </StackPanel>
基本原理就是定期给硬件发指令,是为喂狗,如果超时不喂,机器就会自动重启,一般软件会设置随机器重新启动,所以不管是任何原因导致软件不能正常工作,喂狗中断,就会强制重新启动,这样可保证软件在跑死之后还能自己活过来。