VB5中串口查询法

VB5中串口查询法的实现方法---- 串口查询法是一种主要工作在查询方式下的串口通信实现方法。当通信程序工作在“查询”方式时,可以不考虑Win95的进程和线程的问题。仅在串口有数据时,去读串口缓冲区就可以了。这种方法下确定串口读取的时机、握手协议及软件纠错的实现是程序员应考虑的主要问题。

---- 由于这种方法主要工作在查询方式。程序员必须完成相当一部分通信状态的检测工作,许多细节(甚至包括通信过程中的字符属性的转换)也必须通过程序代码完成。因而相比较通信控件(即利用MSCOMM.OCX控件)方法而言,这种查询方法对通信双方拟订的通信协议的依赖性较大。双方通信协议的约定对程序实现的难易程度影响很大。

---- 由于Win95的串行驱动程序和VB5本身都是“事件驱动的”,在串口查询法中可以利用这种事件驱动的特性提高程序代码的效率。具体过程如下:首先设置通信事件掩码SetCommMask以决定对哪些通信事件进行监视;侦测到一个事件后,就有必要用API函数GetCommMask判断到底是哪个事件发生了,并将那个事件清除,以便这个事件下一次能正常发生;更进一步的作法是直接用WaitCommEvent函数专门等待特定通信事件的发生并对其进行处理。这实际上就对特定的通信事件做了一个消息挂钩,充分体现了事件驱动的优点。

---- 值得注意的一点是,此方法下协议的约定必须满足以下条件:即甲方发送时,乙方必须在甲方发送动作之前进入循环接收状态,直到接收到字符后通过对串口读取函数ReadFile返回值的判断跳出循环状态。

---- VB5是一种极为灵活的高级语言,因而在这种方法下可以方便地引入汇编语言的思维,利用其GoTo转向语句方便地控制程序的流程。非常灵活方便。

四、串口查询法的程序实例

---- 以下是一段程序实例,主要完成以下功能:对串口进行初始化,并完成数据的接收和发送,程序包含一定的纠错机制。通信格式设置为2400波特率,8位数据位,1位停止位,无奇偶校验。

---- 以下是程序的部分源代码,由于篇幅限制,省去了对API函数和一些结构、类型的声明。

  Private  timeouts  As  COMMTIMEOUTS
  Private  handle  As  Long       '串口的句柄
  Private  devname$              
  Public  DCB  As  dwDCB  
    'dwDCB是一个自定义的类
  Private  PendingOutput$
  Private  CurrentEventMask& 
    '当前的通信事件掩码值
  Private  CurrentInputBuffer&
  Private  CurrentOutputBuffer&
  Private  overlaps( 2 )  As  OVERLAPPED      
 ' 0 = read,1 = write,2 = waitevent
  Private  inprogress(2)  As  Boolean       
     ' 指示当前read,write,waitevent事件的状态
  Private  DataWritten&
  Private  DataRead&
  Private  EventResults&
  '以下是打开串口的子函数
Public Function OpenComm(CommDeviceName
 As String,Notify As Object,Optional cbInQueue,Optional cbOutQueue) As Long
If  handle  < > 0  Then  CloseComm 
       '如串口已打开,则先关闭它
    devname = CommDeviceName
handle = CreateFile(devname,GENERIC_READ 
Or GENERIC_WRITE,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0)
If handle = INVALID_HANDLE_VALUE
 Then Err.Raise vbObjectError + ERR
_NOCOMMACCESS,CLASS_NAME,"Unable to open communications device"
    '设置串口的输入和输出缓冲区
If  Not (IsMissing(cbInQueue) 
Or IsMissing(cbOutQueue))  Then
Call  SetupComm( handle,cbInQueue,cbOutQueue )
    Else
        Call  SetupComm(handle,8192,1024)
    End  If
    GetCommTimeouts           '设置超时时间
    timeouts.ReadIntervalTimeout = 1
    timeouts.ReadTotalTimeoutMultiplier = 0
    timeouts.ReadTotalTimeoutConstant = 10
    timeouts.WriteTotalTimeoutMultiplier = 1
    timeouts.WriteTotalTimeoutConstant = 1
    SetCommTimeouts
    ' Initialize the DCB to the current device parameters
Call  DCB.GetCommState(Me)       
    '设置串口的通信格式
Call  SetCommMask(handle,CurrentEventMask) 
    '设置串口的通信事件掩码
    StartInput
End  Function

Private  Sub  StartInput( )          
              '读取串口的子过程
    Dim  res&
If  inprogress( 0 )  Then  Exit Sub   
   ' 如正在读取串口则先退出子过程
If  handle = 0  Then  DeviceNotOpenedError    
  ' 如串口为打开,则指示错误
res = ReadFile(handle,CurrentInputBuffer,ClassBufferSizes,DataRead,overlaps(0))
    If  res < > 0  Then
        ProcessReadComplete            
          '已完成读取串口的操作
    Else
        If  GetLastError( ) = ERROR
_IO_PENDING  Then
            inprogress(0) = True    
     '置读取过程标志为真
        Else
            Err.Raise  vbObjectError
 + ERR_READFAIL,"Failure on Comm device read operation"
        End  If
    End  If
End  Sub

  Private  Sub  TermText_KeyPress
( KeyAscii As Integer
 )      '发送对文本框内的字符的子过程
    If  Not (Comm Is Nothing)  Then
        Comm.CommOutput (Chr$(KeyAscii))
    End  If
    KeyAscii = 0
  End  Sub

  Private  Sub  Timer1_Timer( )       
  '在定时器事件内定时对串口状态进行检查
    If  Not ( Comm  Is  Nothing )  Then  Comm.Poll
  End  Sub

  Public  Sub  Poll( )        
 ' 测试发送、接受和事件侦测是否正在进行
    PollWrite
    PollRead
    PollEvent
  End  Sub

  Public  Function  CommOutput
( outputdata  As  String )  As  Long
    Dim  bytestosend&
    Dim  res&
    If  handle = 0  Then  DeviceNotOpenedError
    PendingOutput = PendingOutput & outputdata
    If  inprogress(1)  Then    '正在向串口发送数据
        CommOutput = True
        Exit Function
    End  If
    ' 重新开始新的数据发送操作
    bytestosend = Len( PendingOutput )
If  bytestosend = 0  Then      
   '无发送的数据则退出
        CommOutput = True
        Exit  Function
    End  If
    '防止缓冲区溢出
If  bytestosend  > ClassBufferSizes  
Then  bytestosend = ClassBufferSizes
If  bytestosend  >
 0  Then  Call  lstrcpyToBuffer
(CurrentOutputBuffer,PendingOutput,bytestosend + 1)
    If  bytestosend = Len(PendingOutput)  Then
        PendingOutput = ""
    Else
        PendingOutput = Mid(PendingOutput,bytestosend + 1)
    End  If
res = WriteFile( handle,CurrentOutputBuffer,bytestosend,DataWritten,overlaps(1) )
    If  res < > 0  Then
        ProcessWriteComplete
        CommOutput = True
    Else
If  GetLastError( ) = ERROR_IO_PENDING  Then
            inprogress(1) = True
            CommOutput = True
        End If
    End If
  End  Function

  Public  Sub  PollWrite( )
    Dim  res&
    If  Not  inprogress(1)  Then  Exit Sub
    ' 检查该事件
    res = WaitForSingleObject( overlaps(1).hEvent,0 )
      If  res = WAIT_TIMEOUT  Then  Exit Sub
      ProcessWriteComplete
  End  Sub

  Public  Sub  ProcessWriteComplete( )     
      '设置发送结束标志的子过程
inprogress(1) = False

    Call  CommOutput(" ")
  End  Sub

  Public  Sub  PollRead( )
    Dim  res&
    If  Not  inprogress(0)  Then
        StartInput
        Exit  Sub
    End  If
    '检查该事件
    res = WaitForSingleObject( overlaps(0).hEvent,0 )
    If  res = WAIT_TIMEOUT  Then  Exit  Sub
    ProcessReadComplete
  End  Sub

  Public  Sub  ProcessReadComplete( )       
       '设置接收结束标志的子过程
    Dim  resstring$
    Dim  copied&
If  inprogress(0)  Then
    DataRead = overlaps(0).InternalHigh
        inprogress(0) = False
    End  If
    If  DataRead < > 0  Then
        resstring$ = String$(DataRead + 1,0)
        copied = lstrcpyFromBuffer(resstring,DataRead + 1)
    End  If
  End  Sub
  Private  Sub  StartEventWatch( )
    Dim  res&
If  inprogress(2)  Then  Exit  Sub  
        '已经启动一个事件监测过程,则退出
If  handle = 0  Then  DeviceNotOpenedError
    EventResults = 0
res = WaitCommEvent
( handle,EventResults,overlaps(2) )
    If  res < > 0  Then
        ProcessEventComplete
    Else
If  GetLastError( ) = ERROR_IO_PENDING  Then
            inprogress(2) = True
        Else
            Err.Raise vbObjectError + 
ERR_EVENTFAIL,"Failure on Comm device event test operation"
        End  If
    End  If
  End  Sub

Private Sub ProcessEventComplete( )   
       '设置侦测事件结束标志的子过程
    Dim  errors&
If  inprogress(2)  Then
   inprogress(2) = False
    End  If
    
    If  EventResults < > 0  Then
       Msgbox  "There is something 
wrong with the comm event !"
    End  If
End  Sub

Private  Sub  PollEvent( )     
  '侦测通信事件的子过程
    Dim  res&
    If  Not  inprogress(2)  Then
        StartEventWatch
        Exit  Sub
    End  If
    res = WaitForSingleObject(overlaps(2).hEvent,0)
    If  res = WAIT_TIMEOUT  Then  Exit  Sub
     ProcessEventComplete
  End   Sub

Public Function CloseComm( ) As Long   
      ' 关闭串口的子函数
    If  handle = 0  Then  Exit  Function
    Call  CloseHandle(handle)
    handle = 0
End  Function

---- 另外,由于32位API函数参数的数据类型的变化,所有整形参数都被换为长整型(Long)以支持32位的处理,这一点在设置返回值时尤其如此。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Format[$] ( expr [ , fmt ] ) format 返回变体型 format$ 强制返回为文本 -------------------------------- 数字类型的格式化 --------------------------------     固定格式参数:     General Number 普通数字,如可以用来去掉千位分隔号     format$("100,1
VB6或者ASP 格式化时间为 MM/dd/yyyy 格式,竟然没有好的办法, Format 或者FormatDateTime 竟然结果和系统设置的区域语言的日期和时间格式相关。意思是尽管你用诸如 Format(Now, "MM/dd/yyyy"),如果系统的设置格式区域语言的日期和时间格式分隔符是"-",那他还会显示为 MM-dd-yyyy     只有拼凑: <%response.write
在项目中添加如下代码:新建窗口来显示异常信息。 Namespace My ‘全局错误处理,新的解决方案直接添加本ApplicationEvents.vb 到工程即可 ‘添加后还需要一个From用来显示错误。如果到这步还不会则需要先打好基础啦 ‘======================================================== ‘以下事件
转了这一篇文章,原来一直想用C#做k3的插件开发,vb没有C#用的爽呀,这篇文章写与2011年,看来我以前没有认真去找这个方法呀。 https://blog.csdn.net/chzjxgd/article/details/6176325 金蝶K3 BOS的插件官方是用VB6编写的,如果  能用.Net下的语言工具开发BOS插件是一件很愉快的事情,其中缘由不言而喻,而本文则是个人首创,实现在了用V
Sub 分列() ‘以空格为分隔符,连续空格只算1个。对所选中的单元格进行处理 Dim m As Range, tmpStr As String, s As String Dim x As Integer, y As Integer, subStr As String If MsgBox("确定要分列处理吗?请确定分列的数据会覆盖它后面的单元格!", _
  窗体代码 1 Private Sub Text1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) 2 Dim path As String, hash As String 3 For Each fil
  Imports MySql.Data.MySqlClient Public Class Form1 ‘ GLOBAL DECLARATIONS Dim conString As String = "Server=localhost;Database=net2;Uid=root;Pwd=123456;" Dim con As New MySqlConnection
‘導入命名空間 Imports ADODB Imports Microsoft.Office.Interop   Private Sub A1() Dim Sql As String Dim Cnn As New ADODB.Connection Dim Rs As New ADODB.Recordset Dim S As String   S = "Provider=OraOLEDB.Oracl
Imports System.IO Imports System.Threading Imports System.Diagnostics Public Class Form1 Dim A(254) As String    Function ping(ByVal IP As Integer) As String Dim IPAddress As String IPAddress = "10.0.
VB运行EXE程序,并等待其运行结束 参考:https://blog.csdn.net/useway/article/details/5494084 Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long Pr
今天碰到一个问题,登陆的时候,如果不需要验证手机号为空,则不去验证手机号 因为登陆的时候所有的验证信息都存放在一个数组里 Dim CheckUserInfo() As String ={UserBirthday, SecEmail, UserMob, UserSex, RealNameFirst, RealName, CheckCardID, CheckCardType, Contactemail
在VB6.0中,数据访问接口有三种: 1、ActiveX数据对象(ADO) 2、远程数据对象(RDO) 3、数据访问对象(DAO) 1.使用ADO(ActiveX Data Objec,ActiveX数据对象)连接SQL Server 1)使用ADO控件连接 使用ADO控件的ConnectionString属性就可以连接SQL Server,该属性包含一个由分号分隔的argument=value语
注:大家如果没有VB6.0的安装文件,可自行百度一下下载,一般文件大小在200M左右的均为完整版的软件,可以使用。   特别提示:安装此软件的时候最好退出360杀毒软件(包括360安全卫士,电脑管家等,如果电脑上有这些软件的话),因为现如今的360杀毒软件直接会对VB6.0软件误报,这样的话就可能会在安装过程中被误报阻止而导致安装失败,或者是安装后缺乏很多必须的组件(其它的杀毒软件或安全卫士之类的
Private Sub Form_Load() Call conndb End Sub Private Function conndb() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Dim strCn, sql As String Dim db_host As String Dim db_user As String
  PPSM06S70:  Add  moddate  EDITSPRINTJOB:  MAX(TO_CHAR(ETRN.MODDATE, ‘yyyy/mm/dd/HH24:MI AM‘)) ACTUAL_SHIPDATE   4.Test Scenario (1) :Query SQL Test DN:8016578337 SELECT CTRN.TKCTID TRUCK_ID,        
  沒有出現CrystalReportViewer時,須安裝CRforVS_13_0. 新增1個數據集,新增1個數據表,添加二列,列名要和資料庫名一樣. 修改目標Framework 修改app.config, <startup >改成<startup useLegacyV2RuntimeActivationPolicy ="true">  CrystalReport1.rpt增加數據庫專家 在表單
Imports System.Threading Imports System Public Class Form1 Dim th1, th2 As Thread Public Sub Method1() Dim i As Integer For i = 1 To 100 If Me.Label1.BackColor =
Friend Const PROCESS_ALL_ACCESS = &H1F0FFF = 2035711 Friend Const PROCESS_VM_READ = &H10 Friend Const PROCESS_VM_WRITE = &H20 Friend Const PAGE_READONLY = &H2 Friend Const PAGE_READWRITE = &H4 Friend
以下代码随手写的 并没有大量测试 效率也有待提升 如果需要C#的请自行转换 Function SplitBytes(Data As Byte(), Delimiter As Byte()) As List(Of Byte()) Dim i = 0 Dim List As New List(Of Byte()) Dim bytes As New
Imports System.Data.SqlClient Public Class Form1 REM Public conn1 As SqlConnection = New SqlConnection("server=.; Integrated Security=False;Initial Catalog= mydatabase1; User ID= sa;password")