3.1 软件的实现
系统实现了基于SECS标准的串口通讯。整个通讯软件分为4个相对独立的模块:等待、发送、接收和竞争,具体描述如下:
1.等待模块。在此状态下,程序处于后台运行,直到接收到以下两种请求之一:①如果
主机收到来自设备的一个ENQ信号(信号的意义见图3,以下同),则回送一个EOT信号给设备,同时自己转入接收状态;②如果设备收到发送命令,作如下处理:
图3 握手建立的时序图
a.向
主机发送一个ENQ信号,然后不断侦听是否有来自主机的EOT信号。在此期间,如果超过T2时间仍然未收到EOT,则重发ENQ,最多重发RTY次。如果重发RTY次后仍然没收到EOT,则发送失败,转入等待状态。
b.如果同时收到一个ENQ信号,则发生竞争,根据是
主机还是设备进行不同处理。
c.如果收到一个EOT信号,则表示通讯握手已经成功,转入发送状"VH如果不是以上两种信号,继续处于等待状态。在这其中最主要的是握手的建立,图3说明了软件中主机和设备之间的握手规则。
2.发送模块。在发送中,要完成以下任务:
①发送长度字节N,N个数据和两个校验和(整个数据称为1个块的数据);②发送完成后转入侦听状态。在此期间,如果在T2时间内如果收到了应答信号,判断该信号是不是ACK,如果不是则发送失败,重发ENQ建立握手,重发数据(最多RTY次、如果在T2时间内收到了ACK信号则发送成功,转入等待状态。
①不断侦听端口,直到收到长度字节N,如果在T2时间仍然没收到长度字节N,则给对方发送NAK信号,表示这一次发送失败;
②如果在T2时间内收到长度字节N后,则:判断其值是否在IO-254之间。如果其值不在10-254之间,继续侦听,直到对方发完所有的数据,最后发送NAK信号给对方,表示这一次发送失败;如果其值在10-254之间,继续侦听端口,开始接收数据,同时启动定时器T1。如果两个字符间的接收间隔时间超过了T1,则发送NAK信号给对方,表示发送失败。如果以上两步均正确,则在所有的数据都收到后,开始计算纵
校验和。
a.加果计算值和收到的校验和相等,说明接收正确。发送ACK信号给对方,一次接收完成。
b.如果计算值和收到的校验和不等,则继续侦听端口,直到对方发送完所有的字节后,发送NAK信号给对方,发送失败。
4.竞争模块。当主机和设备恰巧在同一个时刻发送消息,则需要进行竞争处理。处理的过程如图4所示。
图4 竞争处理的时序图
3.2 串口的编程
使用API函数开发
串口通信应用程序的总体思路是:首先,使用CreateFileQ函数打开特定串口。其次,完成
串行端口的设置,包括
波特率,校验方式,停止位和
数据位等。然后,调用
SetupComm()设置串口接收发送数据的缓冲区大小,串口的设置就基本完成,之后就可以启动读写线程了。
3.2.1 串口设置的方式
串行通讯设计中的重要方面就是对端口进行设置。DCB(device control block)结构中定义了串口通信设备的控制设置。串口端口设置就是对DCB结构成员进行设置。使用API函数GetCommState(),该函数返回DCB结构的当前设置。其使用方法如下:
DCB dcb={0};
If(!::GetcommState(hComm,&dcb)) return FALSE;//
函数调用发生错误
else //已经取回DCB结构当前设置
3.2.2 串口的读写操作
串口的读写操作使用API函数ReadFile()和WriteFile()。当使用异步方式调用这2个函数时,若函数的返回值为TRUE,表示I/O操作立即完成可以进行数据的处理;如果函数的返回值为FALSE,表示I/O操作没有立即完成。举例如下:
BOOL bReadStatus;
bReadStatus=ReadFile(m_hIDComDev,buffer,dwBytesRead,&dwBytesRead,&m_OverlappedRead);
if(! bReadStatus)
{
If(GetLastErrorQ==ERROR_IO_PENDING)
{
WaitForSingleObject(m_OverlappedRead.hEvent,1000);
Return((int)dwBytesRead);
}
Return(0);
}
Return((int)dwHytesRead);