1 系统总体方案
我们采用美国ATMEL公司的子公司TEMIC公司生产的TK5550射频识别IC卡、IDIC(Identification Integrated Circuit)、读写基站集成电路U2270B和ATMEL公司的8位单片机研制开发学校食堂就餐管理系统,系统具有预付收费、目标识别、身份验证、数据采集、数据加密和数据库管理的功能。系统由TK5550卡、就餐机、数据库管理系统、就餐机和数据库管理微机的通讯系统四部分组成。主机与就餐机之间的通信采用RS-485通信标准,工作方式为半双工,每次通信都是主机首先呼叫从机。
2 串行通信接口设计
最常见的串行通行接口标准是RS-232-C串行总线,传输的是单端信号,即信号线中一条是公共地线,另一条是信号线。它只适用于数据传送速率要求不高,距离不长的场合(小于15米),适合于长距离传送的总线标准有:RS-422、RS-423、RS-485、RS-499以及20MA电流环串行接口。
本系统中单片机与上位主机的通讯选用了RS-485总线标准,并采用了MAX465芯片来实现,它具有RS-485通讯接口中要的全部功能,数据通讯的方向由RE,DE 脚来控制,设计中二者连在一起,由单片机的P1.5来控制,当它为高电平时,数据由单片机经MAX485到外部串行总线,即处于发送状态;为低电平时,数据由外部串行总线到单片机。
一般微机的串行口采用RS-232接口,故在主机一端需要一个RS-232/RS-485转换器。本设计中采用了台湾ATEN公司生产的IC-485SN转换器,它是一种双向RS-232/RS-485或RS-422转换器,可提供点对点、点对多点的全双工和半双工以及多点的单工串行通信。具体工作方式可通过两个拨码开关和外部界限灵活配置。由于本系统中涉及到多点半双工通讯,下面就以此方式介绍其使用方法。
在此工作方式下系统的连线如左图。可见转换器对外部的RS-485总线只需两根信号线:DATA+和DATA-,即发送和接收数据公用一对差分传输线,而转换器和微机的RS-232接口则需通过3根线进行连接:RX, DX和RTS/CTS,其中RX为接收数据信号线,TX为发送数据信号线,RTS和CTS端接在一起,控制数据发送是否允许。由于转换器工作时RTS必须为高电平来为转换器供电,即转换器接收数据时也一直处于数据发送允许的状态,为避免发生冲突,应在设计主机串行通讯程序时,控制发送和接收数据分时进行,即系统始终工作在半双工的工作方式。
3 串行通信程序设计
本系统上位主机数据库管理系统采用VF5.0编写,这里介绍的串行通信程序主要是在VF中实现与单片机的通信程序设计。
3.1就餐系统通信程序的设计
WINDOWS 应用程序串行通信方式有调用WINDOWS API函数和标准的通信控件COMMUNICATIONS两种方式。本系统采用标准的通信控件communications进行通信程序的设计,实现挂失数据的发送、用户卡号的发送、发卡和就餐数据的接收。在这里主要以接收用户就餐数据为例讨论应用通信控件Communications通信程序的设计。
就餐机向主机传送的数据为学生卡号和消费金额,主机把接受后的数据临时存贮在表jc中,然后通过相关运算后修改表stu中的存款数据。主机与多台就餐机的通讯方式为,先与一号机通讯,待到一号机数据传输完毕后,再与二号机通信直到最大编号就餐机。使用主机的串口com2与就餐机相连。
3.2 主机与就餐机双方通信的约定
微机向就餐机发送字符串时,该块字符串前附加A,末尾附加B,串口两端的校验和一致,则向微机发送C,如果不一致,则向微机发送D;微机收集来自就餐机的数据时,先由微机向特定的就餐机发送E,该就餐机收到E以后,向微机发送数据块以及校验和,并且在数据块的末尾附加F,如果串口两端的校验和一致,则微机发送G,如果不一致,则微机发送H。(注:A,B,C,D,E,F,G,H都以ASCII码格式发送,而且在OleControl1中收到的都是字符,而不是数字)。
3.3 通信程序实现
每次通信时,首先在主机的init事件中初始化通信控件olecontrol1,初始化设置为:
thisform.olecontrol1.CommPort=1 //选择串行口com1
thisform.olecontrol1.PortOpen=1 //打开串行口com1
thisform.olecontrol1.InputMode=0 //接收的数据按文本方式
thisform.olecontrol1.RTSEnable=1 //允许使用rts线,用于rs-232/485转换器的发送控制和供电
thisform.olecontrol1.InputLen=1 //每次读取接收缓冲区的一个字符
thisform.olecontrol1.OutbufferCount=0 //清除发送缓冲区
thisform.olecontrol1.InbufferCount=0 //清除接收缓冲区
定时控件timer1作为超时定时器, 在Timer1的OnTimer事件中,(假定共有两台就餐机)如果微机向就餐机#1发送的数据正确,那么,延时后,向下一个就餐机发送数据,直到最后一个就餐机,然后提示发送完毕;如果微机向就餐机发送的数据错误,那么,延时后,再发一次。如果连续三次发送都发生了错误,那么,给出错误的就餐机号,并且向下一个就餐机发送数据。定时器的初始化为:
timer1.Interval=50 *定时时间间隔为50ms
timer1.ensbled=.f.先关超时定时器1
在Command1的Click 事件中通过调用外部过程program2向就餐机发送地址(即机号),和要求就餐机向主机传送就餐数据的命令。Program2的程序为:
procedure programe2
*发送机号
表单js.olecontrol1.RThreshold=0
表单js.olecontrol1.Settings="2400,m,8,1"
jh2=chr(jh2)
表单js.olecontrol1.OutPut=jh2
*发送命令
表单js.olecontrol1.Settings="2400,s,8,1"
表单js.olecontrol1.OutPut="E"
表单js.olecontrol1.InbufferCount=0
表单js.olecontrol1.OutbufferCount=0
表单js.olecontrol1.RThreshold=1
表单js.timer1.enabled=.t.
return
具体为:首先在发送数据之前设置OLECONTROLL的Rthreshold为0,禁止对发送事件产生ONCOMM事件,防止主机接收自己的数据。在发送一个字节的机号时,设settings表单js.olecontrol1.Settings="2400,m,8,1"
即校验位为mark:‘1 i,代表地址字节,以校验位作为识别地址的标志。在发送完机号后,设置settings为:
表单js.olecontrol1.Settings="2400,s,8,1"
即校验位为space:‘0 i,表示发送的一个字节E是要求就餐机开始向主机传送就餐数据的命令。主机向就餐机发送数据的方法是应用通信控件的OUTPUT函数,即为表单js.olecontrol1.OutPut="E"。在发送完命令后,要清控主机的发送和接收缓冲区,即令:
表单js.olecontrol1.InbufferCount=0
表单js.olecontrol1.OutbufferCount=0
同时,使控件的Rthreshold有效,等待接收就餐机发来的数据,另外要打开超时定时器即令表单js.timer1.enabled=.t.,以判断就餐机是否正常。在OleControl1的OnComm事件中,首先判断控件的属性CommEvent=2,表示收到 Rthreshold 个字符。该事件将持续产生直到用 Input 属性从接收缓冲区中删除数据。然后接收从串口来的就餐数据和校验和,就餐机发送完数据后紧接着发送一个F,表示数据发送完毕。如果主机接收正确向就餐机发送一个G。延时后与下一台就餐机通信。接收后的数据临时存贮在表JCJ中,等待处理。如果主机接收不正确向就餐机发送一个H。
主机与就餐机的通信成功与否,在超时定时器的ONTIMER事件进行判断,其工作方法在前面已说明。
4 结束语
前面比较详细的介绍了主机接收就餐机数据的程序设计过程和方法,至于主机向就餐机发送挂失卡号和发卡初始化新卡的通信程序的设计原理是相同的。只是发卡时,因为一次通信要传输的数据量很小,卡号金额均为10个字符,对通信结果成功与否的判断,没有使用求校验和的方法,采取了连续传输3次, 在3中取2的措施,这样更可靠。