编写一个简单的vb.net上位机

  • 编程语言:vb.net
  • 开发环境:visual studio
  • 技术类别:可视化Windows窗体应用
  • 主要内容:串口通信

小弟嵌入式菜鸟一枚,从事嵌入式一年了,第一次写blog,不知道怎么下手,写得不好,求不黑,之前一直都在做底层单片机的程序,关于上位机编程其实刚涉足,我看了下网上这方面的免费案例材料好像并不多,有的只是很老vb6.0以前的资料,所以决定给论坛做点贡献,把我了解到的有价值的一些知识点都记录下来,同时和大家分享,共同进步。

上位机是嵌入式人机交互的重要一个环节,编程者可以使用各种不同的方式达到对底层设备的信号控制和数据采集,vb.net提供的一些简单的控件可以帮助我们快速上手一个上位机项目,实现基本功能。下面首先了解一下基本的控件。相应的控件使用方法可以参照visual studiu MSDN官方给出的说明。比如我们做一个简单的测试小工具如该图所示。

java怎么开发上位机 .net 上位机开发_编程语言


前期准备

VB.NET是一门开发语言,我们需要在visual studio编译环境中运行和开发项目,下图所示为visual studio软件截图及下载链接。(具体安装在这里就不详细描述了,自行按照引导“下一步下一步”就行了)。

java怎么开发上位机 .net 上位机开发_java怎么开发上位机_02


visual studio下载地址安装完整后,打开软件,文件-新建-项目

java怎么开发上位机 .net 上位机开发_vb.net_03

弹出的对话框中,找到,已安装-模板-visual basic-windows窗体应用,给自己的项目取个名字。点击确定完成项目创建。

java怎么开发上位机 .net 上位机开发_visual studio_04

创建一个空白窗体后的界面如图所示,在工具栏中找到你要的控件,点击放置到窗体相应的位置,常用的控件都有。其中和串口通信有关的关键控件是serialport。

java怎么开发上位机 .net 上位机开发_vb.net_05

我们添加完控件,给每个空间设置好相应的属性,效果如图所示。

java怎么开发上位机 .net 上位机开发_嵌入式_06

双击窗体及每个控件,对其进行相应的事件程序编写。(需要有一定的vb.NET编程基础)

java怎么开发上位机 .net 上位机开发_编程语言_07

编写程序

创建一个窗体文件和一个模块文件,窗体文件用来放置控件和编写窗体运行的相关事件过程代码,模块文件用来存放公共变量

附上工程代码

'Create By Fgl
'添加串口相关引用和文件读写相关引用
Imports System.IO.Ports
Imports Microsoft.VisualBasic.FileIO
''' <窗体类代码>
''' 包含整个窗体的运行过程和事件
''' </窗体类代码>
Public Class Form_Main
    ''' <窗体变量的定义>
    ''' 
    ''' </窗体变量的定义>
    Dim Ports As String() '定义端口数组
    Dim PortNum As Integer '定义端口数量
    Dim HsArray() As HScrollBar = New HScrollBar() {HScrollBar_P0, HScrollBar_V0, HScrollBar_P1, HScrollBar_V1,
       HScrollBar_P2, HScrollBar_V2, HScrollBar_P3, HScrollBar_V3, HScrollBar_P4, HScrollBar_V4}
    Dim SentToDeviceFlag As Boolean = False
    Const HsDataNum = 10 '定义横向框的数量

    ''' <无阻塞延时函数>
    ''' 单位1ms
    ''' </无阻塞延时函数>
    ''' <param name="Interval"></param>
    Public Shared Sub Sleep(ByVal Interval)
        Dim __time As DateTime = DateTime.Now
        Dim __Span As Int64 = Interval * 10000   '因为时间是以100纳秒为单位。   
        While (DateTime.Now.Ticks - __time.Ticks < __Span)
            Application.DoEvents()
        End While
    End Sub

    ''' <消息框输出>
    ''' 自动加上时间和回车换行
    ''' </消息框输出>
    ''' <param name="Msg"></param>
    Private Sub GiveMsg(Msg As String)
        Dim s As String = String.Format("{0} {1} {2}", Now, Msg, vbCrLf)
        TextBox_Msg.AppendText(s)
    End Sub

    ''' <错误信息输出>
    ''' 自动加上错误信息及时间和回车换行
    ''' </错误信息输出>
    ''' <param name="Msg"></param>
    Private Sub GiveErrMsg(Msg As String)
        TextBox_Msg.AppendText("Err: ")
        GiveMsg(Msg)
    End Sub

    ''' <刷新设置参数>
    ''' 
    ''' </刷新设置参数>
    ''' <param name="SData"></param>
    Private Sub ReFreshSettingData(ByVal SData() As Byte)
        For j = 0 To HsDataNum - 1
            CType(Panel1.Controls.Item(j), HScrollBar).Value = SData(j)
        Next
    End Sub


    ''' <发送当前参数到设备>
    ''' 
    ''' </发送当前参数到设备>
    Private Sub SentCurrentDataToDevice()
        Try
            SerialPort1.Write(ActionCmd_Current, 0, ActionCmd_Current.Length)
        Catch ex As Exception
            GiveErrMsg(ex.Message)
        End Try

    End Sub

    ''' <设置进度条最大值>
    ''' 
    ''' </设置进度条最大值>
    ''' <param name="parent"></param>
    Public Sub SetProgressBarMaximum(ByVal parent As Control)
        For Each c As Control In parent.Controls
            If TypeOf (c) Is ProgressBar Then
                CType(c, ProgressBar).Maximum = 255
            End If
            'MessageBox.Show(c.ToString())
            If c.HasChildren Then
                '利用递归实现容器子控件的访问
                SetProgressBarMaximum(c)
            End If
        Next
    End Sub

    ''' <设置横向框值域>
    '''
    ''' </设置横向框值域>
    ''' <param name="parent"></param>
    Public Sub SetHScrollBarMaximum(ByVal parent As Control)
        For Each c As Control In parent.Controls
            If TypeOf (c) Is HScrollBar Then
                CType(c, HScrollBar).Maximum = 255
            End If

            'MessageBox.Show(c.ToString())
            If c.HasChildren Then
                '利用递归实现容器子控件的访问
                SetHScrollBarMaximum(c)
            End If
        Next
    End Sub

    ''' <窗体事件>
    ''' 
    ''' </窗体事件>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub Form_Main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        GiveMsg("Start App")
        Dim FirstOpenFlag As Integer
        FileOpen(1, Application.StartupPath & "\FileCmdData.txt", OpenMode.Random)
        Try
            FileGet(1, FirstOpenFlag, 1)
        Catch ex As Exception
            GiveErrMsg(ex.Message)
        End Try

        If Not FirstOpenFlag = 123456 Then '如果是第一次打开
            FilePut(1, 123456, 1)
            For i = 0 To ActionCmd_Table.GetLength(0) - 1
                FilePut(1, ActionCmd_Table(i), i + 2)
            Next
        End If
        For i = 0 To ActionCmd_Table.GetLength(0) - 1
            FileGet(1, ActionCmd_Table(i), i + 2)
        Next
        FileClose({1})

        SetProgressBarMaximum(GroupBox_Return) '初始化进度条参数
        SetHScrollBarMaximum(GroupBox_Setting) '初始化横向框

        Ports = SerialPort.GetPortNames '获取当前存在的端口名
        PortNum = Ports.GetLength(0) '获取当前存在的端口数量
        For Each Portx As String In Ports
            ComboBox_PortNum.Items.Add(Portx) '向复选框里添加可用端口
        Next
        If PortNum > 0 Then
            ComboBox_PortNum.Text = ComboBox_PortNum.Items(1)
        End If
        For Each str As String In Modual_ActionTable.ActionTable
            ComboBox_BasicAction.Items.Add(str) '初始化训练动作组合框内容
        Next
        ComboBox_BasicAction.Text = ComboBox_BasicAction.Items(0)
        For i = 0 To 100
            ComboBox_BasicTrainTimes.Items.Add(i) '初始化训练次数组合框内容
        Next
        ComboBox_BasicTrainTimes.Text = 1
        CheckBox_SA.Checked = True
        'TextBox_Msg.AppendText(ComboBox_BasicAction.SelectedIndex)


        GiveMsg("Init Ok")
    End Sub

    ''' <复位按键的点击事件>
    ''' 
    ''' </复位按键的点击事件>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub Button_Reset_Click(sender As Object, e As EventArgs) Handles Button_Reset.Click
        Try
            For i = 0 To 11
                ActionCmd_Current(i) = ActionCmd_Table(0)(i) '刷新当前电机参数
            Next
            ReFreshSettingData(ActionCmd_Current) '刷新横向框参数
            SentToDeviceFlag = True '发送数据到电机
            GiveMsg("复位")
        Catch ex As Exception
            GiveErrMsg(ex.Message)
        End Try
    End Sub

    ''' <打开串口过程>
    ''' 
    ''' </打开串口过程>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub Button_OpenUart_Click(sender As Object, e As EventArgs) Handles Button_OpenUart.Click
        Try
            If SerialPort1.IsOpen = True Then
                SerialPort1.Close()
                Button_OpenUart.Text = "打开串口"
            Else
                SerialPort1.Open()
                Button_OpenUart.Text = "关闭串口"
            End If
            ComboBox_PortNum.Enabled = Not SerialPort1.IsOpen
        Catch ex As Exception
            GiveErrMsg(ex.Message)
        End Try
    End Sub

    ''' <训练按钮单击事件>
    ''' 
    ''' </训练按钮单击事件>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub Button_Train_Click(sender As Object, e As EventArgs) Handles Button_Train.Click
        'Try
        Dim i As Integer = ComboBox_BasicAction.SelectedIndex
        If i < ActionCmd_Table.GetLength(0) Then
            For j = 0 To ActionCmd_Current.Length - 1
                ActionCmd_Current(j) = ActionCmd_Table(i)(j) '刷新当前电机参数
            Next
            ReFreshSettingData(ActionCmd_Current) '刷新横向框参数
            SentToDeviceFlag = True '发送当前参数到电机
            Dim s As String = String.Format("进行{0}训练", ComboBox_BasicAction.Text)
            GiveMsg(s)
        End If
        'Catch ex As Exception
        '    GiveErrMsg(ex.Message)
        'End Try
    End Sub

    ''' <组合框选择事件>
    ''' 
    ''' </组合框选择事件>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub ComboBox_PortNum_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox_PortNum.SelectedIndexChanged
        Try
            SerialPort1.PortName = ComboBox_PortNum.Text
        Catch ex As Exception
            GiveErrMsg(ex.Message)
        End Try

    End Sub

    ''' <清空按钮单机事件>
    ''' 
    ''' </清空按钮单机事件>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub Button_Clear_Click(sender As Object, e As EventArgs) Handles Button_Clear.Click
        TextBox_Msg.Clear()
    End Sub

    ''' <横向框滚动事件>
    ''' 
    ''' </横向框滚动事件>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub HScrollBar_PX_Scroll(sender As Object, e As ScrollEventArgs) Handles HScrollBar_P0.Scroll,
        HScrollBar_P1.Scroll, HScrollBar_P2.Scroll, HScrollBar_P3.Scroll, HScrollBar_P4.Scroll, HScrollBar_PA.Scroll
        Try
            For i = 0 To HsDataNum - 1
                ActionCmd_Current(i) = CType(Panel1.Controls.Item(i), HScrollBar).Value
            Next
            SentToDeviceFlag = True
        Catch ex As Exception
            GiveErrMsg(ex.Message)
        End Try
    End Sub
    ''' <定时器扫描过程>
    ''' 在定时器中扫描发送标志位并对待发送的内容进行发送
    ''' </定时器扫描过程>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        If SentToDeviceFlag = True Then
            SentToDeviceFlag = False
            SentCurrentDataToDevice()
        End If
    End Sub

    ''' <总体滚动条滚动事件>
    ''' 
    ''' </总体滚动条滚动事件>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub HScrollBar_PA_Scroll(sender As Object, e As ScrollEventArgs) Handles HScrollBar_PA.Scroll
        Try
            For i = 0 To 4
                If CType(Panel2.Controls.Item(i), CheckBox).Checked = True Then
                    CType(Panel1.Controls.Item(i * 2 + 1), HScrollBar).Value = HScrollBar_PA.Value
                End If
            Next
        Catch ex As Exception
            GiveErrMsg(ex.Message)
        End Try
    End Sub

    ''' <全选复选框改变事件>
    ''' 
    ''' </全选复选框改变事件>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub CheckBox_SA_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox_SA.CheckedChanged
        If CheckBox_SA.CheckState = CheckState.Checked Then
            For Each c As CheckBox In Panel2.Controls
                c.Checked = True
            Next

        End If
        If CheckBox_SA.CheckState = CheckState.Unchecked Then
            For Each c As CheckBox In Panel2.Controls
                c.Checked = False
            Next
        End If

    End Sub
    ''' <复选框改变事件>
    ''' 
    ''' </复选框改变事件>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub CheckBox_S0_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox_S0.CheckedChanged _
        , CheckBox_S1.CheckedChanged, CheckBox_S2.CheckedChanged, CheckBox_S3.CheckedChanged, CheckBox_S4.CheckedChanged
        If CheckBox_S0.Checked = True And CheckBox_S1.Checked = True And CheckBox_S2.Checked = True And
            CheckBox_S3.Checked = True And CheckBox_S4.Checked = True Then
            CheckBox_SA.CheckState = CheckState.Checked
        ElseIf CheckBox_S0.Checked = False And CheckBox_S1.Checked = False And CheckBox_S2.Checked = False And
            CheckBox_S3.Checked = False And CheckBox_S4.Checked = False Then
            CheckBox_SA.Checked = CheckState.Unchecked
        Else
            CheckBox_SA.CheckState = CheckState.Indeterminate
        End If
    End Sub

    ''' <标定按钮单击事件>
    ''' 
    ''' </标定按钮单击事件>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub Button_Sign_Click(sender As Object, e As EventArgs) Handles Button_Sign.Click
        For i = 0 To 11
            ActionCmd_Table(ComboBox_BasicAction.SelectedIndex)(i) = ActionCmd_Current(i)
        Next
        FileOpen(1, Application.StartupPath & "\FileCmdData.txt", OpenMode.Random)
        For i = 0 To ActionCmd_Table.GetLength(0) - 1
            FilePut(1, ActionCmd_Table(i), i + 2)
        Next
        FileClose({1})
        Dim s As String = String.Format("{0}手势位置标定成功", ComboBox_BasicAction.Text)
        GiveMsg(s)
    End Sub

    ''' <保存历史按钮单击事件>
    ''' 
    ''' </保存历史按钮单击事件>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub Button_SaveHistory_Click(sender As Object, e As EventArgs) Handles Button_SaveHistory.Click

        SaveFileDialog1.Filter = "txt files (*.txt)|*.txt"
        Dim s As String = String.Format("History")
        SaveFileDialog1.FileName = s
        If SaveFileDialog1.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
            '如果确定保存
            My.Computer.FileSystem.WriteAllText(SaveFileDialog1.FileName, TextBox_Msg.Text, True)
            My.Computer.FileSystem.WriteAllText(SaveFileDialog1.FileName, ActionCmd_Table.ToString, True)
        End If
    End Sub

End Class


Module Modual_ActionTable
    Public ActionTable() As String = {"张开", "握拳", "食指对指", "中指对指", "无名指对指", "小拇指对指",
        "数字1", "数字2", "数字3", "数字4", "数字5", "数字6", "数字7", "数字8", "数字9"}

    Public ActionCmd_Reset() As Byte = {&HFF, &H00, &HFF, &H00, &HFF, &H00, &HFF, &H00, &HFF, &H00, &HFF, &H00, &HFF, &H00}
    Public ActionCmd_Fist() As Byte = {&HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF}
    Public ActionCmd_IndexToThumb() As Byte = {&HFF, &HFF, &HFF, &HFF, &HFF, &H00, &HFF, &H00, &HFF, &H00, &HFF, &H00, &HFF, &H00}
    Public ActionCmd_MiddleToThumb() As Byte = {&HFF, &HFF, &HFF, &H00, &HFF, &HFF, &HFF, &H00, &HFF, &H00, &HFF, &H00, &HFF, &H00}
    Public ActionCmd_RingToThumb() As Byte = {&HFF, &HFF, &HFF, &H00, &HFF, &H00, &HFF, &HFF, &HFF, &H00, &HFF, &H00, &HFF, &H00}
    Public ActionCmd_LittleToThumb() As Byte = {&HFF, &HFF, &HFF, &H00, &HFF, &H00, &HFF, &H00, &HFF, &HFF, &HFF, &H00, &HFF, &H00}

    Public ActionCmd_Current() As Byte = {&HFF, &H00, &HFF, &H00, &HFF, &H00, &HFF, &H00, &HFF, &H00, &HFF, &H00, &HFF, &H00}


    Public ActionCmd_Table()() As Byte = {ActionCmd_Reset, ActionCmd_Fist, ActionCmd_IndexToThumb, ActionCmd_MiddleToThumb,
        ActionCmd_RingToThumb, ActionCmd_LittleToThumb}
End Module

OK,运行一下,完成。

java怎么开发上位机 .net 上位机开发_vb.net_08

哦,对了,如果要移植copy此模板,记得控件的名字要和代码中一致。

看似复杂的上位机工程,其实代码也就短短几百行。关于指令解析部分,下一篇再写吧。

第一次写blog可能难免会有犯些基本错误,若有什么问题好的建议随时和我交流。