1 引 言
在开发汽车仪表检测设备的过程中,非常重要的工作就是实现工控机与汽车仪表的串行通讯。通过串行通讯可以实现对仪表软、硬件版本的检测、仪表里程清零及仪表调校等一系列仪表出厂前重要的检测项目及参数设定。对应于"新捷达"型汽车组合仪表(西门子VDO公司产品),为实现技术安全性,故其串行口采用非标准串行通讯协议,是用一般的串口通讯控件所难以实现的,必须由熟悉仪表软件结构的人员从底层编写通讯程序。
本文采用C++Builder开发平台,在Windows 98操作系统下,成功实现了与"新捷达"型汽车组合仪表的通讯,并具有美观简洁的用户操作界面。 2 New Jetta型仪表串行通讯要求简述
2.1 硬件连接
文中工控机与仪表的硬件连接是从仪表的K-line经过电平转换器连接工控机的RS-232串行口,采用半双工串行异步通讯方式。如图1所示。 (图片) 2.2 软件规范
软件规范关于串口数据通讯协议中包括了通信握手、多重校验、出错重发、超时处理等。
2.2.1 通讯初始化
当仪表点火信号端起动约2s后可以建立通讯响应。首先以5b通讯速率发送信息,该信息包含1个起始位,7个数据位,1个奇偶校验位和1个停止位(向仪表发送* * H)。
仪表收到该信息后大约要等待一个约5 ms的循环时间,然后通讯模块起动。从此时起所有的通讯字节将以10 400b/s的波特率来收发(此波特率为非标准波特率)。
经过100ms仪表送出同步字节(1个起始位,8个数据位,1个停止位,为* * H),再经过loms仪表送出密码的低字节,10ms后仪表送出密码的高字节(1个起始位,7个数据位,1个奇偶校验位,1个停止位,密码值为* * * *H)。
此后,仪表等待工控机送回倒序的密码高字节。这种回送方式是本串行通讯的防错处理机制。如果此字节仪表没有接收到,那么仪表将再次发送同步字节和密码字节。
当仪表接收到回送字节后,标准模块通讯以10 400b/s的波特率起动(每字节包含1个起始位,8个数据位,1个停止位)。此时,仪表开始发送仪表ID模块,为4个模块,分别包括16,16,15,9个字节。在这4个模块的发送过程中,仪表与工控机之间又有很多的信息应答要求,如有差错则通讯中止。
2.2.2 正常通讯过程
经过通讯初始化后,正常通讯以10 400b/s的波特率开始建立,此时工控机可以发送命令字节流给仪表,来实现对仪表的控制及参数设置。每隔特定的时间间隔,仪表与工控机间仍须互送握手信号,否则通讯中止。
3 软件程序设计
本通讯方式属于零Modem串行异步通讯。在异步通讯中,字符格式和波特率是2个重要指标。本文中通讯过程既有波特率的变化,也有帧格式的变化,对通讯的响应时间也有严格要求。
在C++Builder可视化编程格式下不再支持直接对寄存器操作的函数,故首先用嵌入汇编的办法实现Inporb和Outporb函数。本通讯的数据流是以字节为发送单位的,故编写字节收发函数,为查询方式,如清单1所示:
清单1:
byte TForml∷bytReceiveByte(void)
{
byte bytTemp; //Dim bytTemp As Byte
int intTemp; //Dim intTemp As Integer
byte bytResult;
bytTemp=InportB(intLSR);//intLSR=0x3fd
intTemp=0;
blnBeyond WaitTime=False;
while((bytTemp&0x1)!=0x1)
{
bytTemp=InportB(intLSR);
intTemp=intTemp+1;
S1eep(1);
//检查接收的数据是否准备好,为1表示接收移位寄存器已收到一个完整的数据,并送到接收缓冲器中
if(intTemp>intWaitTime)
{Error();}
}
if(!blnBeyondWaitTime)
bytResult=InportB(intDRR);//intDRR=0x3f8
return bytResult;
}
VOld TForml∷subSendByte(byte bytSend)
{
byte bytTemp;
bytTemp=InportB(intLSR);
//检查发送缓冲器是否为空,1为空
while((bytTemp&0x20)!=0x20)
bytTemp=InportB(intLSR);
OutportB(0x3F8,bytSend); //发送缓冲器为空
bytTemp=InportB(intLSR);
//检查发送移位寄存器是否为空,即发送缓冲器的数据是否送完
while((bytTemp&0x40)!=0x40)
bytTemp=InportB(intLSR);
bytTemp=InportB(intLSR);
//检查接收的数据是否准备好,为1表示接收移位寄存器已收到一个完整的数据,并送到接收缓冲器中
while((bytTemp & 0x1)!=0x1)
bytTemp=InportB(intLSR);
bytTemp=InportB(intDRR);
//清空接收缓冲区中的发送数据
}
在此基础上建立本通讯初始化的主函数,如清单2所示:
清单2:
void TForml∷InitRS232(void)
{
String strTemp;//Dim strTemp As String
byte bytTemp; //Dim bytTemp As Byte
int intTemp; //Dim intTemp As Integer
int i; //Dim I As Integer
//Stepl:
OutportB (intLCR,0x80);
//输出控制字,下面输出波特串
OutportB(intLSB,0x0); //低位
OutportB(intMSB,0x5A); //高位
OutportB(intLCR,0xA);
//5 bit,l起始位,1奇偶位和1停止位
OutportB(intIER,0); //抑制中断
strTemp="";
subSendByte (0x * *) //发送建立通讯密码
//Step2:
OutportB(intLCR,0x80);
//输出控制字,下面输出波特率
OutportB(intLSB,0xB);
OutportB(intMSB,0x0);
OutportB(intLCR,0x3);//10400,8,N
strTemp=strTemp+""+IntToHex(bytReceiveByte(),2);
//Step3:
Receive the Low byte Of Key Word
strTemp=strTemp+""+IntToHex(bytReceiveByte(),2);
//Step4:
Receive the High byte Of Key Word
bytTemp=bytReceiveByte();
strTemp=strTemp+""+IntToHex(bytTemp,2);
//Step5:
下面PC送高位字节的取反
if(! blnBeyondWaitTime)
subSendByte(byte(~bytTemp)); //byte
else
{Error();}
//Step 6 Receive the block data
if (! blnReceiveIDBlock(16)) //接收第1个ID块,为16B
{Error();}
if (! blnReceiveIDBlock(16)) //接收第2个ID块,为16B
{Error();}
if (! blnReceiveIDBlock(15)) //接收第3个ID块,为15B
{Error();}
if (! blnReceiveIDBlock(9)) //接收第4个ID块,为9B
{Error();}
//Cluster)> >PC
subReceiveTheFifthBlock();
String ResOfFT=strTestDataStream(strEnableFT);
//仪表Epprom可读写命令
if(ResOfFT==EmptyStr)
{Error();}
blnInitRS232=True;
4 结 语
本文采用C++Builder软件平台成功开发了仪表特殊串行口通讯程序,该系统在西门子VDO(芜湖)公司生产线投入使用一年多,与采用快速通讯方式相比通讯传输性能稳定,并具有了方便美观的用户界面,为实现仪表检测设备奠定了基础,具有重要的应用价值。
1/22/2006
|