sunrain_hjb的BLOG
Develop Helpful and Effective apps to make Jobs easier and Better!

      最近朋友的一个项目有这样的需求,让我帮忙探个路。经过两天的努力,总算是有点收获。

      VB.NET是一种面向对象的计算机编程语言,可以看做是Visual Basic的升级版。它也是Visual Studio.NET的核心语言之一。开发人员可以利用它快速而高效的创建出基于.NET Framework的应用程序。.NET Framework家族也包括了面向移动设备领域的两个成员,它们分别是.NET Compact Framework和.NET Micro Framework。其中.NET CF可以认为是WinCE平台上.NET Framework的精简版,而.NET MF则面向更小型的设备。

     要让WinCE支持VB.NET,需要在定制系统时添加.NET Compact Framework组件。这很简单,在PB5.0或6.0中将相应的组件选入到Catalog中,重新编译系统即可。主要问题是如何编写一个应用程序,并且能访问底层硬件的数据。

     翻箱倒柜,找出很久以前买的一本VB.NET的书,快速地翻看了几个重要的章节,对VB.NET有了大概的了解,并基本确定了实现方式——使用动态链接库(DLL)。

     实现过程中,最大的麻烦就是语言不熟悉。传说中的“拖拉拽”快速编程方式在我这变成了拖拉机。好在之前先用C实现了功能,参照着改到VB下来,要容易不少。下面就VB的代码部分做一个简单的总结,以备后用。

     首先是自定义常量,效果等同于宏定义。

    Const WRITE_BASE_ADDRESS = &H0           ' 用于写入数据的基地址
    Const READ_BASE_ADDRESS = &H1000         ' 用于读取数据的基地址

     VB.NET中的结构体定义格式如下。

Private Structure CMDINFO
      Dim pCMDBuf As UInteger         ' 指令缓冲区,应用申请空间,指针类型
       Dim dwWriteAddr As UInteger     ' 指令写入的地址
       Dim dwCMDLen As UInteger        ' 指令的长度
       Dim dwRetryCount As UInteger    ' 重试的次数
       Dim dwDelayTime As UInteger     ' 重试的周期,以ms为单位
End Structure
Private Structure READINFO
      Dim pReadBuf As UInteger         ' 读取数据的缓冲区,库申请空间,指针类型
      Dim dwDataAddr As UInteger       ' 读取RAM的地址
      Dim dwReadLen As UInteger        ' 读取数据的长度
      Dim dwRetryCount As UInteger     ' 重试的次数
      Dim dwDelayTime As UInteger      ' 重试的周期
  End Structure

    DLL中实现的库函数的声明。

    Private Declare Function SendCommand Lib "DPRAMLib" (ByVal CMDInfo As CMDINFO) As Integer
    Private Declare Function ReadDPRAM Lib "DPRAMLib" (ByRef ReadInfo As READINFO) As Integer
    Private Declare Sub WritePort Lib "DPRAMLib" (ByVal Port As UShort, ByVal Value As Byte)
    Private Declare Function ReadPort Lib "DPRAMLib" (ByVal Port As UShort) As Byte

     需要注意的是,如果函数有返回值须使用Function,如果没有返回值,则使用Sub,否则,程序在运行过程中会出现异常。如果函数的参数为指针或者引用类型,则用ByRef,如果是值传递,则用ByVal。

Private Sub ButtonRead_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonRead.Click
        Dim i As Integer
        Dim szTmp As String
        Dim szShowBuf As String
        Dim ReadBuf As Byte()
        ' 获取地址
        RamAddr = Val("&H" + TextBoxAddr.Text.Substring(2))
        ' 获取长度
        Length = Val("&H" + TextBoxLength.Text.Substring(2))
        ' 调用库函数读取RAM
        stReadInfo.dwDelayTime = 2
        stReadInfo.dwRetryCount = 5
        stReadInfo.dwDataAddr = RamAddr     
        stReadInfo.dwReadLen = Length       
        stReadInfo.pReadBuf = vbNullString  
        ReadDPRAM(stReadInfo)
 
        Length = stReadInfo.dwReadLen - 1 ' 将长度转换为索引的最大值
        ' 获取读取出来的数据长度,并分配相应的内存
        ReDim ReadBuf(Length)
        ' 将库中读取的数据拷贝至托管代码的数组中,以便处理
        Marshal.Copy(stReadInfo.pReadBuf, ReadBuf, 0, stReadInfo.dwReadLen)
        ' 显示读取到的内容
        szShowBuf = "0000:"
        For i = 0 To Length Step 1
            szTmp = Hex(ReadBuf(i))
            If szTmp.Length = 1 Then
                szTmp = "0" & szTmp
            End If
            szShowBuf = szShowBuf & szTmp & " "
            If (i + 1) Mod (8) = 0 Then
                szShowBuf = szShowBuf & vbCrLf ' 加入换行符
                If i < Length Then
                    szTmp = Hex(i + 1)
                    Dim szTmp2 As New String("0", 4 - Len(szTmp))
                    szTmp = szTmp2 & szTmp & ":"
                    szShowBuf = szShowBuf & szTmp
                End If
            End If
        Next
        TextBoxValue.Text = szShowBuf
    End Sub

     以上代码调用库函数读取数据,并在EDIT控件中以十六进制的方式显示出来。其中,用Val和Hex做字符串和十六进制数据之间的转换。Marshal用来处理托管代码和非托管代码之间的数据封送。

Private Sub ButtonWrite_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonWrite.Click
        Dim i As Integer, j As Integer, nLength As Integer
        Dim nValue As Byte
        Dim szTmp As String
        Dim WriteBuf As Byte()
        
        RamAddr = Val("&H" + TextBoxAddr.Text.Substring(2))
 
        ' 获取需要写入的数据
         nLength = TextBoxValue.Text.Length()
        ReDim WriteBuf((nLength + 1) / 3)
        i = 0
        j = 0
        While i < nLength
            szTmp = "&H" + Mid(TextBoxValue.Text, i + 1, 2)
            nValue = Val(szTmp)
            WriteBuf(j) = nValue
            i += 3
            j += 1
        End While
        Dim pt As New IntPtr
        pt = Marshal.AllocHGlobal(j)        ' 从进程的非托管内存中分配内存
         Marshal.Copy(WriteBuf, 0, pt, j)    ' 将数据从托管数组复制到非托管内存指针
        ' 调用库函数写入RAM
        stCmdInfo.pCMDBuf = pt
        stCmdInfo.dwCMDLen = j
        stCmdInfo.dwDelayTime = 2
        stCmdInfo.dwRetryCount = 5
        stCmdInfo.dwWriteAddr = RamAddr
        SendCommand(stCmdInfo)
        Marshal.FreeHGlobal(pt)   ' 释放使用AllocHGlobal 从进程的非托管内存中分配的内存
    End Sub

     以上代码调用库函数,将用户输入的十六进制数据写入到RAM中。

posted on 2010-07-08 23:52  sunrain_hjb  阅读(6957)  评论(4编辑  收藏  举报

Map