四、 应用实例 由于该项目的软件源代码较长,我们只拿出和串口通讯有关的程序片段来供大家参考。在我们的工作中实践了三种通讯方式,即查询方式、事件驱动方式、事件驱动转查询方式,这三种方式各有利敝,查询方式有方便可靠的特点,可利用协议或设定时钟进入和退出查询状态,但不是资源的有效利用方式,事件触发方式对于定长通讯非常有效,但定长通讯在有些场合不实用,事件驱动转查询方式既有事件驱动的特点又有转查询方式特点,可以说是集二者之长,有效利用资源。下面着重介绍事件驱动转查询方式。 首先在公共模块中定义和ONCOMM有关的参数: . . . Global Const MSCOMM_EV_RECEIVE = 2\'收到 Rthreshold 个字符。该事件将持续产生直到用 Input 属性从接收缓冲区中删除数据。 Global Const MSCOMM_ER_RXOVER = 1008\'接受缓冲区溢出。接收缓冲区没有空间。 Global Const MSCOMM_ER_TXFULL = 1010 \'传输缓冲区已满。传输字符时传输缓冲区已满
在启动过程中对串口和输入输出缓冲区初始化: Sub Form_Load () . . . comm1.Settings = \"1200,n,8,1\" \'设定波特率1200bps,无校验,8位数据位,1位停止位 comm1.CommPort = 1 \'串口1 comm1.InputLen = 1 \'一次从输入缓冲区中读取一个字符 comm1.InBufferSize = 512 \'定义输入缓冲区为512字节(bytes) comm1.InBufferCount = 0 \'清空输入缓冲区 comm1.OutBufferCount = 0 \'清空输出缓冲区 comm1.PortOpen = True \'启动串口 End Sub 下面是发送数传命令的子过程,启动该过程由一个定时器控制: Sub sample_data () . . . comm1.RTSEnable = True \'将Modem的PTT置高,同时打开对讲机 Call time_delay \'适当延时 comm1.Output = \"*TRNS\" + Chr$(13) \'发送命令 Do \'该循环用来检测命令是否全部发送完毕 Loop Until comm1.OutBufferCount = 0 Call time_delay \'适当延时 comm1.RTSEnable = False \'将Modem的PTT置低,将对讲机改为接受状态 comm1.InBufferCount = 0 \'清空接收缓冲区 comm1.RThreshold = 1 \'设定RThreshold = 1,等待出发OnComm事件 . . . End Sub 在OnComm编写接收和处理代码: Sub Comm1_OnComm () Select Case comm1.CommEvent . . . Case MSCOMM_ER_RXOVER \'接收缓冲区溢出。可插入相应的代码 Case MSCOMM_ER_TXFULL \'传输缓冲区已满。可插入处理代码 Case MSCOMM_ER_RECEIVE \'收到1个字符,可进入以下处理过程 comm1.RThreshold = 0 \'不再响应OnComm事件,转入查寻方式接收 ii = 0 iii = 0: sinn = Chr$(42): sinn1 = Chr$(42) \'初始化变量 Do duration = Timer + .2 \'设定超时退出的时间值 iii = iii + 1 sinn1 = sinn Do \'该循环判断输入缓冲区是否有数据或是否超时 \'dummy% = DoEvents() Loop Until comm1.InBufferCount >= 1 Or Timer >= duration If Timer >= duration Then iii = iii - 1 overtime = True \'确定超时退出,并非正常退出 Exit Do End If sinn = comm1.Input \'正常退出,取值付给sinn If header_er = 0 Then GoTo test_header End If If Asc(sinn) > 175 Or Asc(sinn) < 160 Then \'判断包头是否正确 iii = 0 GoTo station_number_er \'包头不正确,丢掉该数据 End If test_header: header_er = 0 \'包头正确,接受到包头,header_er=0 ssin(iii) = sinn\'----put date into string dimantion station_number = Asc(ssin(1)) package_number = Asc(ssin(2)) sentence_number = Asc(ssin(3)) last_character = Asc(ssin(iii)) station_number_er: Loop Until sinn1 = Chr$(10) and sinn = Chr$(13) \'当收到正确的包尾0A,0D后退出 If overtime = True Then \'如果超时非正常退出 overtime = False comm1.RThreshold = 1 \'重新启动OnComm事件,等待接收下一包 timer6_wait.Enabled = True GoTo endsub End If 以下是接收数据正确以后的数据处理程序,包括解码和计算这里从略。 . . . If package_number = 1 Then \'如果接收数据正确,而且是最后一包 timer2_sample.Enabled = True \'启动控制数传命令定时器 comm1.RTSEnable = True \'置PTT为高 comm1.OutBufferCount = 0 \'清空输出缓冲区 Call time_delay \'适当延时 comm1.Output = \"*MACK\" + Chr$(13) \'发送清内存命令 Do \'检测是否发送完毕 Loop Until comm1.OutBufferCount = 0 Call time_delay \'适当延时 comm1.RTSEnable = False \'置PTT为低 End If If package_number > 1 Then \'如果不是最后一包 comm1.RThreshold = 1 \'启动OnComm准备接收下一包 timer6_wait.Enabled = True End If endsub: header_er = 1: comm1.InBufferCount = 0 \'--empty inbuffer protect from bed data on the inbuffer End Select End Sub