VB.NET中使用IO卡
IO卡接端子板,在程序中可以用来提供触发信号,端子板接传感器或者接动作开关之后就可以检测到输入和提供输出了。
IO卡使用的是研华PCI-1762十六位输入输出的IO ,先在windows中安装IO卡的驱动程序和客户端,这样就可以手动控制IO卡了,系统中安装了IO卡提供的集成环境之后,VB.NET中就可以引用IO卡提供的DLL了
这是第一步,
在引用中添加控件DLL
第二步就是引用到程序空间一句话:Imports Automation.BDaq
到了这里就可以在程序中使用IO提供的函数和方法了,采用代码加载的方式,我采用控件的方式,所以还要继续
第三步:加载控件
在控件界面,工具——>新建选项卡——>选择项——>NET Framework组件(一定不要选COM组件,我被坑过)——>浏览,找到刚刚引用的DLL 点击确定,在如图我们新建的IO中就有一堆控件了,里面我们需要用到的是InstantDiCtrl和InStantDoCtrl,添加到窗口
第四步:在两个控件中选择IO卡,如图标红,SelectedDevice中显示的是No device ,这是因为我的笔记本没有安装IO卡,如果安装会有可以选择的项,这边只有简单选择一些就可以了。然后就可以代码编程了
第五步:代码编程,一个定时器控件用来轮询IO卡的输入值,定时器控件默认不开启,需要控制开启。
Imports Automation.BDaq
Public Class Form1
#Region "IO定义"
Public Const NUM_BITIN As Integer = 16
Public b(NUM_BITIN) As Boolean '定义一个数组存放IO读取到的结果
Public mpbof(8) As Boolean '定义控件组大小
Public card_output As Short
Public giOutput As Integer
Public gIOCard As Integer
Public Di_Data As Long '输入信号
Public Do_Data As Long '输出信号
Dim SleepIO As Integer
Public mpbo() As PictureBox
Public mpbi() As PictureBox
Private Const m_startPort As Integer = 0
Private Const m_portCountShow As Integer = 4
#End Region
Private Sub InstantDiCtrl1_ChangeOfState(ByVal sender As Object, ByVal e As Automation.BDaq.DiSnapEventArgs) Handles InstantDiCtrl1.ChangeOfState
MsgBox("触发1")
End Sub
Private Sub InstantDiCtrl1_DiIntChanX(ByVal src As Object, ByVal args As DiSnapEventArgs) Handles InstantDiCtrl1.Interrupt
Try
MsgBox("IOka ")
'If args.SrcNum = 0 Then '判断触发端口和是否处于OK状态
' SetOut2(5, 1)
' Thread.Sleep(500)
' GrabImage(1)
' SetOut2(5, 0)
' If b(10) = True Then
' RunImage(1)
' ElseIf b(11) = True Then
' RunImage2(2)
' End If
'ElseIf args.SrcNum = 8 Then
'End If
Catch ex As System.Exception
End Try
End Sub
Private Sub IOINstall()
If Not InstantDoCtrl1.Initialized Then
MessageBox.Show("Please select a device in control property!", "StaticDO")
Me.Close()
Return
End If
If Not InstantDiCtrl1.Initialized Then
MessageBox.Show("Please select a device in control property!", "StaticDO")
Me.Close()
Return
End If
'复位输出端口
InstantDiCtrl1.DiintChannels(0).Enabled = True
InstantDiCtrl1.DiintChannels(1).Enabled = True
Dim err As ErrorCode = ErrorCode.Success
err = InstantDiCtrl1.SnapStart() '开启中断
If err <> ErrorCode.Success Then
HandleError(err)
Return
End If
End Sub
Private Sub HandleError(ByVal err As ErrorCode)
If err <> ErrorCode.Success Then
MessageBox.Show("Sorry ! Some errors happened, the error code is: " & err.ToString(), "StaticDI")
End If
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
IOINstall()
Label1.Text = "90"
End Sub
Public Sub IoRead()
InstantDiCtrl1.Read(0, Di_Data)
Dim index As Integer
For index = 1 To 8 '获取16个IO口的结果
If CBool(Di_Data And (1 << (index - 1))) Then '如果有信号输入则为true没有者为false
b(index) = True '将对应的b数组置为true
Else
b(index) = False '将对应的b数组置为false
End If
Next
InstantDiCtrl1.Read(1, Di_Data)
For index = 1 To 8 '获取16个IO口的结果
If CBool(Di_Data And (1 << (index - 1))) Then '如果有信号输入则为true没有者为false
b(index + 8) = True '将对应的b数组置为true
Else
b(index + 8) = False '将对应的b数组置为false
End If
Next
End Sub
Public Sub SetOut2(ByRef mbBit As Short, ByRef mbValue As Byte)
card_output = mbBit
SetOut(mbBit, mbValue) '调用取位模块
' InstantDoCtrl1.Write()方法,根据端口和位来输出结果,1762是16位IO卡,端口有0和1两个,每个端口八位,两个字节
'输入的数据转换为十六进制值对应到每一位,获取输入时同样的道理
InstantDoCtrl1.Write(gIOCard, giOutput) '写出结果
End Sub
Private Sub SetOut(ByRef mbBit As Short, ByRef mbValue As Byte)
If mbBit = 0 Or mbBit > 16 Then 'Error’判断值是否在范围内
Exit Sub '退出循环
MessageBox.Show("请检查输出端口是否正确") '报错
End If
Dim x As Boolean '设置一个标志
If mbValue = 1 Then '判断是否为1
x = True '将x值为true
Else '否则
x = False '将X值为false
End If
Dim i As Short
i = mbBit
mpbof(i - 1) = Not mpbof(i - 1)
If mbBit <= 8 Then
gIOCard = 0
Else
gIOCard = 1
mbBit = mbBit - 8
i = mbBit
End If
If x = False Then
mpbof(i) = False
Else
mpbof(i) = True
End If
Dim b As Byte '定义一个byteb当x=false的时候反转
If x = True Then
For i = 1 To 8
If mpbof(i) Then
giOutput = giOutput Or (1 << (mbBit - 1))
End If
Next
Else
b = 0 '将b赋值
b = b Or (1 << (mbBit - 1)) '移位获取b值
b = Not b '将b值反转
giOutput = giOutput And b '将指定端口关闭
End If
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
SetOut2(1, 1)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
SetOut2(1, 0)
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Try
IoRead()
Label1.Text = "90"
IoRead()
If b(2) = False Then
Label1.Text = "0"
Else
Label1.Text = "1"
End If
Catch ex As Exception
MsgBox(ex.Message & "错误")
End Try
End Sub
Private Sub Label1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Label1.Click
End Sub
End Class
原理:很多代码是为了变换数值和数制。输入和输出主要通过两行代码: InstantDiCtrl1.Read(0, Di_Data)读取端口和 InstantDoCtrl1.Write(0, giOutput) '写出结果,先说读取,read(第一个参数,第二个参数),其中第一个参数是IO卡的端口,可以在IO卡提供的客户端中看到,如图
第一个参数对应port,在研华1762中只能取1或者0 第二个参数则对应hex是十六进制值,也就是说,我们给的第二个参数的值,控件自动解析成hex,如果读取到32,那么则是
D5为高电平,如果是33,则是D5和D0都是高电平。我们读取到的是十进制数,要把它解析成十六进制才能找到对应的端口。输出也是一样道理write(第一个参数,第二个参数),第二个参数也是十六进制,如果我们想让0端口的0和6为高电平(低电平为默认)那么第一个参数是0,第二个参数是32(6)加1(0)33,也就是除了这两个位,别的位都为0,这样就会更新端口的状态,达到控制输出的目的。
PS:我都资源中有Demo 感谢雷哥和文哥