|
Private Function OpenThePort ( cPort as String , cBaud as
String , cParity
as String , cData as String , tStops asString ) As Boolean
' 打开串口的子过程
Dim lResult as Long
Dim lHandle as Long
Dim DCB_COMM as DCB
Dim cDCBConfig as String
lHandle = CreateFile ( cPort , GENERIC_READ
Or GENERIC_WRITE ,
0& , 0& , OPEN_EXISTING , 0& , 0&
)
If lHandle = -1 Then '打开串口失败
OpenThePort = False
MsgBox “串口可能正被其他应用程序占用!”
lResult = CloseHandle
( lHandle ) '先关闭串口后再打开
If lResult = 0 Then
OpenThePort
Exit
Function
End If
End If
cDCBConfig.band = 2400 '设置
DCB
cDCBConfig.parity = None
cDCBConfig.data = 8
cDCBConfig.stop = 1
lResult = BuildCommDCB ( cDCBConfig , DCB_COMM
) '按用户设定配置一个 DCB 结构
If lResult = 0 Then
OpenThePort =
False
MsgBox “无法建立 DCB
设备控制块”
Exit Function
End If
lResult = SetCommState ( lHandle , DCB_Comm
) '实际设置一个串口的 DCB
If lResult = 0 Then
OpenThePort =
False
MsgBox “无法建立 DCB
设备控制块”
Exit Function
End If
OpenThePort = True
End Function
Private Sub SendHand ( ) '发送握手信号的子过程
Dim Nchars As Long
Static Readbuff As String * 1
Static Writebuff As String * 1
Dim lpDCB As DCB
Dim lRet As Long
Dim lHandle As Long
Dim lpOverlapped As OVERLAPPED
Dim RNum As Integer
MsgBox “请把读卡器插在串口 2 上!”,
48 ,“提示窗口”
lHandle = OpenThePort ( COMM1,2400,None,8,1
)
lRet = PurgeComm( lHandle , 1 ) '清输出缓冲区
lRet = PurgeComm( lHandle , 0 ) '清输入缓冲区
lRet = GetCommState ( lHandle , lpDCB ) '获得通讯口的状态
Shand :
Writebuff $ = Chr $ (&H8F)
lRet = WriteFile (lHandle,Writebuff $ ,1,Nchars,lpOverlapped
)
'送握手信号入串口缓冲区
If lRet <= 0 Then
MsgBox “发送操作出错,卡握手信号未发送成功”,
16
GoTo Shand
'不成功则重发
Else
GoTo Qtest
End If
GoTo Shand
Qtest :
Readbuff$ = “ ” '清除缓冲区为空
Do While lHandle '循环查询串口
RNum = 0 '设置读串口次数的指针为 0
ReadAgain :
lRet = ReadFile( lHandle , Readbuff
$, 1 , Nchars , lpOverlapped )
If lRet < 0 Then
MsgBox “读取应答信号时出错”, 16
End If
If lRet = 0 Then
If RNum
> 1000 Then '只读 1000 次串口,以免陷入死循环
MsgBox
" 卡没有插接好或卡没有接在串口上 !"
GoTo CloseP
End If
RNum = RNum +
1
GoTo ReadAgain
End If
If Hex $ (Asc(Readbuff)) <> Hex $ (&HFF)
Then GoTo Shand
'回送码不正确则返回继续发送握手信号
Else
Label1.Caption = “握手信号是:”
+ Hex $ (Asc(Readbuff
$ ))
Msgbox “握手信号正确,已正确联机”
GoTo CloseP
End If
Loop
CloseP : lRet = CloseHandle( lHandle )
If lRet = 0 Then
MsgBox “串行通讯口关闭成功”,
48 ,“提示窗口”
End If
End Sub
这里要注意的是:当 PC 机与单片机系统通信时,单片机数据存储区 ( RAM ) 内的数据是十六进制,在信号线上传输的是十六进制数的
ASCII 码的二进制形式;而 Windows 系统下使用的是 ANSI 码, ANSI 码仅在前 126 个与 ASCII
码相同。即在 Win95 下接收到的是十六进制数的 ASCII 码的字符串,可先转换为 ANSI 码后再在 Win95
下还原为十六进制数。
具体为: Code$=Hex $ (Asc ( Readbuff$ ) )
另外,由于 32 位 API 函数参数的数据类型的变化,所有整形参数都被换为长整型( Long
)以支持 32 位的处理,这一点在设置返回值时尤其如此。
6 结束语
以上的软硬件在我们的实践中达到了较为理想的效果。通过软件节省了硬件的开销,并通过在 PIC16F84
单片机系统和 PC 机双方的通信软件内增加握手信号,达到了软件数据校验的目的,获得了较高的通信可靠性。
参 考 文 献
1 MICROCHIP CO. PIC16/17 MICROCO-NTROLLER DATA BOOK. 1995/1996
2 李东星等 . PIC16CXX 系列单片机应用设计 . 高奇电子科技公司, 1996.10
3 美 Darwin Boyle 等 . Visual Basic 4 Developer ' s Guide. 北京:机械工
业出版社, 1997.
这是 PIC 单片机对 PC 机的单向串行通信程序。
;---------------------------------------------------
;sent to pc use delay program.2400dps
;---------------------------------------------------
DELAY_H MOVLW
8CH
MOVWF DELA
H_LOOP DECFSZ DELA
GOTO H_LOOP
RETLW 0
;--------------------------------------------------------------
;mcu to pc sent program. 2400dps
;--------------------------------------------------------------
SENT MOVLW
BITNUM ;sent to pc program
MOVWF COUNT
BCF RA,3
CALL DELAY_H
NEXT RRF
SENTD
BTFSC STATUS,C
BSF RA,3
BTFSS STATUS,C
BCF RA,3
CALL DELAY_H
DECFSZ COUNT
GOTO NEXT
STOP BSF
RA,3
CALL DELAY
RETLW 0
|