支持看门狗的工控机实现软件挂掉机器重启

发布时间 2023-08-18 15:43:49作者: 子禾学长

首先两点要明确一下:

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
View Code

封装的 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>

 基本原理就是定期给硬件发指令,是为喂狗,如果超时不喂,机器就会自动重启,一般软件会设置随机器重新启动,所以不管是任何原因导致软件不能正常工作,喂狗中断,就会强制重新启动,这样可保证软件在跑死之后还能自己活过来。