初学串口编程,用厂商提供的例子能读写RF感应卡,但我想用SpComm来开发驱动程序,
可是SpComm该如何读写RF感应卡?卡里面的数据我该怎么读(我是用厂家的程序往卡里写的数据).看了一些例子,只能发送(没有报错),但就是接收不到数据.那位高手搞过串口编程,能指点一下吗? 

解决方案 »

  1.   

    厂方提供的示例如下:
    打开串口:
    procedure TForm1.butOpenClick(Sender: TObject);
    var
      portno: integer;
    begin
        Commhandle:=opencomm('com1:9600,n,8,1');
        if Commhandle>0 then
        begin
            lstexesta.caption:='Open com'+inttohex(portno+1,1)+ ' OK';
            butwr.Enabled:=true;
            butrd.enabled:=true;
            butbeep.Enabled:=true; 
        end
        else
            lstexesta.caption:='Open COMx error';
    end;写卡:
    procedure TForm1.butWrClick(Sender: TObject);
    var mykey:keystruc;
        retval:longint;
        stmp:string;
    begin
        mykey.cardtype :=strtoint(trim(edit0.text));
        stmp:=trim(edit1.Text);
        hextobin(pchar(stmp),pchar(@mykey.hotelid),3);
        mykey.AreaID :=strtoint(trim(edit2.text));
        mykey.FloorID:=strtoint(trim(edit3.text));
        mykey.roomid:=strtoint(trim(edit4.text));
        mykey.CardID:=strtoint(trim(edit5.Text));
        mykey.OffOn:=0;
        stmp:=trim(edit7.Text);
        hextobin(pchar(stmp),pchar(@mykey.sdate),5);
        stmp:=trim(edit8.text);
        hextobin(pchar(stmp),pchar(@mykey.edate),5);
        stmp:=trim(edit9.Text);
        hextobin(pchar(stmp),pchar(@mykey.STime),2);
        stmp:=trim(edit10.Text);
        hextobin(pchar(stmp),pchar(@mykey.eTime),2);
        mykey.FloorCot:=strtoint(trim(edit11.text));
        retval:=WRkey_t5557(commhandle,mykey);
        if retval<>0 then
        begin
            lstexesta.caption:=' Wr Card error ';
            dv_beep(commhandle,10);
            dv_beep(commhandle,10);
        end
        else
        begin
            dv_beep(commhandle,10);
            lstexesta.caption:=' Wr Card OK';
        end;
    end;读卡:
    procedure TForm1.butRDClick(Sender: TObject);
    var
        mykey:KeyStruc;
        retval:longint;
        ptmp:array[0..64] of char;
    begin
        retval:=rdkey_t5557(commhandle,mykey);
        if (retval=0) then
        begin
            lstexesta.caption:='Rd card ok';
            dv_beep(commhandle,10);
        end
        else
        begin
            lstexesta.caption:=format(' rd card error %.2x%',[retval]);
            dv_beep(commhandle,10);
            dv_beep(commhandle,10);
            exit
        end;
        edit0.Text:=inttostr(mykey.cardtype);
        fillchar(ptmp,63,0);
        bintohex(pchar(@mykey.hotelid),ptmp,3);
        edit1.Text:=ptmp;
        edit2.text:=inttostr(mykey.AreaID);
        edit3.text:=inttostr(mykey.FloorID);
        edit4.Text:=inttostr(mykey.roomid);
        edit5.Text:=inttostr(mykey.cardID);
        edit6.Text:='0';
        fillchar(ptmp,63,0);
        bintohex(pchar(@mykey.sdate),ptmp,6);
        edit7.Text:=ptmp;
        bintohex(pchar(@mykey.edate),ptmp,6);
        edit8.Text:=ptmp;
        fillchar(ptmp,63,0);
        bintohex(pchar(@mykey.stime),ptmp,2);
        edit9.Text:=ptmp;
        bintohex(pchar(@mykey.etime),ptmp,2);
        edit10.Text:=ptmp;
        edit11.Text:=inttostr(mykey.FloorCot);
    end;引用的单元
    unit hotel1;
    interfaceType KeyStruc=RECORD
        cardtype:byte;
        HotelID: array[0..2] of byte;// 
        AreaID: byte;
        FloorID:byte;
        roomid:Byte;
        CardID:Byte;
        OffOn:Byte;
        SDate:array[0..4] of byte; 
        EDate:array[0..4] of byte; 
        STime:array[0..1] of Byte;
        ETime:array[0..1] of byte;
        FloorCot:byte;
    End;Const
        conGuest =1;
        conWaiter=2;
        conClear =3;
        conMange =4;
        conWarn  =5;function rdkey_4150(Commhandle:longint;var keyinfo:KeyStruc):longint;stdcall;
    external 'hotel1.dll';
    function wrkey_4150(Commhandle:longint;var keyinfo:KeyStruc):longint;stdcall;
    external 'hotel1.dll';
    function rdkey_ib91(Commhandle:longint;var keyinfo:KeyStruc):longint;stdcall;
    external 'hotel1.dll';
    function wrkey_ib91(Commhandle:longint;var keyinfo:KeyStruc):longint;stdcall;
    external 'hotel1.dll';
    function rdkey_t5557(Commhandle:longint;var keyinfo:KeyStruc):longint;stdcall;
    external 'hotel1.dll';
    function wrkey_t5557(Commhandle:longint;var keyinfo:KeyStruc):longint;stdcall;
    external 'hotel1.dll';Function rdkey_4442(commhandle:longint;var keys:keystruc):longint;stdcall;
    external 'hotel1.dll';
    Function wrkey_4442(commhandle:longint;var keys:keystruc):longint;stdcall;
    external 'hotel1.dll';implementationend.
    如果用API来写驱动,需要哪些资料?
      

  2.   

    以我们以前做过的一个读cpu卡的读卡器为例我们在开发这个读卡器的时候会设计一套协议来实现与通过串口与pc机的交互.比如我在pc机上通过串口发送$1b $xx两个字节,读卡器就会执行相应的操作,比如写卡,初始化,读等等.你所谓的驱动,只是把这套协议封装起来方便调用.实际的通信过程就是一个"一问一答"的过程,你发什么命令,读卡器就执行什么操作.从你给的代码来看,'hotel1.dll'这实际上就是一个驱动封装了.你的delphi程序仅仅只是调用而已,甚至除了打开串口以外都没有对串口的操作(操作全部封装在hotel1.dll里了)如果你想做一个驱动,那光有这个例子是不够的,你需要知道hotel1.dll里所封装的通讯协议的具体内容,知道控制命令集以及数据格式,这些都需要厂家提供.
    用api,你只需要操作串口的打开,关闭,收,发 就足够了.open,write,read几个函数就可以了.
    如果你要做真正的驱动,就是把读卡器做成一个windows设备,象word可以调用打印机那样,那据我所知delphi恐怕是不够的,你需要使用winddk或者DriverWizard之类的开发工具
      

  3.   

    看了给的例子,与读卡器通讯协议已经封装到API里面了。而你只要的做的就是保证COM的打开和关闭,发送和接收使用定义好的API函数即可。至于你为什么接收不到数据的问题,不清楚读卡器对于数据的接收是如何处理的。
    有一个简单的办法分析封装的协议,
    就是你用串口调试助手,再找个两个母头的线,连接计算机上的两个Com口。
    然后分别执行各个函数,这样你就能得到计算机发送出去的命令了。然后在用串口调试助手发送刚才收到的命令(按照接收时候的格式发送,此时就不用两个母头的线了,直接用线连接读卡器),
    就可以得到读卡器返回来的数据了。这样便于你分析发送和接收的协议,如果能分析出来,也就不用受dll文件的受制了。
    注意,协议有可能加密了,否则应该不会给你提供dll文件。
      

  4.   

    to skylkj:确实像你所说的那样,对读卡器的操作,全部都是封装在'hotel1.dll'中了.我看到相关的Delphi用API来开发驱动.所以就试试.看来问题的关键上决有找到读卡器的通信协议.
    谢谢大家的支持.
      

  5.   

    你把這一段
    写卡: 
    procedure TForm1.butWrClick(Sender: TObject); 
    var mykey:keystruc; 
        retval:longint; 
        stmp:string; 
    begin 
        mykey.cardtype :=strtoint(trim(edit0.text)); 
        stmp:=trim(edit1.Text); 
        hextobin(pchar(stmp),pchar(@mykey.hotelid),3); 
        mykey.AreaID :=strtoint(trim(edit2.text)); 
        mykey.FloorID:=strtoint(trim(edit3.text)); 
        mykey.roomid:=strtoint(trim(edit4.text)); 
        mykey.CardID:=strtoint(trim(edit5.Text)); 
        mykey.OffOn:=0; 
        stmp:=trim(edit7.Text); 
        hextobin(pchar(stmp),pchar(@mykey.sdate),5); 
        stmp:=trim(edit8.text); 
        hextobin(pchar(stmp),pchar(@mykey.edate),5); 
        stmp:=trim(edit9.Text); 
        hextobin(pchar(stmp),pchar(@mykey.STime),2); 
        stmp:=trim(edit10.Text); 
        hextobin(pchar(stmp),pchar(@mykey.eTime),2); 
        mykey.FloorCot:=strtoint(trim(edit11.text)); 
        retval:=WRkey_t5557(commhandle,mykey); 
        if retval <>0 then 
        begin 
            lstexesta.caption:=' Wr Card error '; 
            dv_beep(commhandle,10); 
            dv_beep(commhandle,10); 
        end 
        else 
        begin 
            dv_beep(commhandle,10); 
            lstexesta.caption:=' Wr Card OK'; 
        end; 
    end; 
    引用到你的程序中,把用的dll和所引用的單元一并引用到你所開發的單元中,按著卡的數據結構寫數據,應該是可以的。我以前也是這么干的,就是數據結構那邊要搞清楚它的類型和長度。
      

  6.   

    to lindaozhi:你说的方式那只是应用,我是想写他那样的DLL,也就是不要厂商的DLL,而自己开发. 
      

  7.   

    1.2 通讯参数:
    波特率: 9600
    数据位: 8
    停止位: 1
    校验位: None(无)2、通信协议
    2.1 协议格式:
    STX ADDR LEN CMD/STU DATA BCC
    STX:通讯起始符,1字节,其值为 0x02。
    ADDR:设备地址号,1字节,0对所有地址有效。
    LEN:数据长度,1字节,CMD/STU+DATA的字节数。
    CMD/STU:命令字节(Host->Reader)或状态字节(Reader->Host),1字节。
    DATA:数据字段,字节个数不定,该段有可能不存在。
    BCC:为区段核对字符,1字节,为数据包除STX,BCC以外所有字节的异或值。2.2 命令集:
       
    功能          发送命令   返回状态      数据及说明蜂鸣器控制       0x22     0x00      蜂鸣控制字(1字节)蜂鸣控制字→ =0: 响一声,=2: 响二声
    T5557卡读序列号 0x41     0x00   卡序列号(8字节)
    T5557卡读卡数据 0x42     0x00   卡数据(24字节)
    T5557卡写卡数据 0x43     0x00      卡数据(24字节)

     返回状态代码
    代码 代表意义
    0x00 正常执行
    其它值 错误 → 无卡以上就是我现在有的资料,那位给一个简单的示例.
      

  8.   

    比如蜂鸣器响一声
    var
       buf:array of byte;
       i:integer;
       bcc:byte;
    begin
    setlength(buf,1+1+1+1+1+1);buf[0]:=$02; //STX 
    buf[1]:=$00; //ADDR 
    buf[2]:=1;   //LEN 
    buf[3]:=$22; //CMD/STU  蜂鸣器
    buf[4]:=0;   //DATA  响一声
    bcc:=0;
    for i:=1 to length(buf)-1 do
       bcc:=bcc xor buf[i];buf[5]:=bcc; //BCCcomm1.WriteCommData(pchar(@buf[0]),length(buf));
    end;当然,这之前比要保证comm1的各个状态已经设置好,并且已用stratcom打开
    comm1的onReceiveData事件处理接收数据,如果收到$00,表示执行成功
      

  9.   

    上面for i:=1 to length(buf)-1 do
    改成for i:=1 to length(buf)-1-1 do
      

  10.   

    to skylkj:
    你上边的例子,我是试了.可是接收数据该怎么写.如果我想发送"谢谢您"这个字符串,怎么改代码.因为我发现不能发字符串.