delphi2010调用HC RF 非接触式 IC 卡读写器代码
本文代码仅适用于GH-230Z -YKT型号读卡器,用来读写感应式M1卡。一般都可以从硬件购买店铺获得对应的sdk开发包,我这个算是接收别人的项目,已经把读卡器的相关逻辑做了二次封装,现在有些操作逻辑需要更原始的数据操作实现不了,后面就直接想办法联系到了这款读卡器的厂家要到了相关SDK开发包,但是里面的delphi demo是基于delphi7的,我现在测试用的delphi是2010版本,有的dll函数可以调用有的又不行,就花了几天时间改动了下(其实dll调用都是比较标准的方法,主要还是delphi不同版本 函数参数类型的问题导致的)。
一、密钥加载函数rf_load_key_hex改动如下
far;external 'hcrf32.dll' name 'rf_load_key';
//function rf_load_key_hex(icdev:longint;mode,secnr:smallint;nkey:pchar):smallint;stdcall; // 原来的
function rf_load_key_hex(icdev:Integer;mode,secnr:Short;nkey:PAnsiChar):Short;stdcall;
二、写卡rf_write_hex函数改动如下(hex方式)
// function rf_write_hex(icdev:longint;adr:smallint;data:PChar):smallint;stdcall; // 原来的
function rf_write_hex(icdev:Integer;adr:Short;data:PAnsiChar):Short;stdcall;
far;external 'hcrf32.dll' name 'rf_read_hex';
三、使用对应函数片段
var nkeynew,StrPtr: PAnsiChar; StrPtr: PAnsiChar; begin nkeynew:='FFFFFFFFFFFF'; st:=rf_load_key_hex(icdev,loadmode,sector, nkeynew); //装载密钥到读卡器中 //st:=0; if st<>0 then listbox1.items.add('load key error') else listbox1.items.add('load key Ok'); // ----这里省略一些验密等过程 wdatanew:='b1b2b3b4ffffffffffffffffffffffff'; //0-9,A-F 的hex格式长度固定32 AssignStringToAnsiChar(wdatanew,StrPtr);//转化函数 st:=rf_write_hex(icdev,block,StrPtr); if st<>0 then listbox1.items.add('write hex error') else listbox1.items.add('write hex Ok');
用到的转化函数
procedure AssignStringToAnsiChar(text: string; var AnsiCharVar: PAnsiChar); var AnsiText: AnsiString; begin // 将 Delphi 字符串转换为 ANSI 字符串 AnsiText := AnsiString(text); // 分配内存来存储 ANSI 字符串(包括结尾的空字符) GetMem(AnsiCharVar, Length(AnsiText) + 1); // 将 ANSI 字符串复制到分配的内存中 StrPCopy(AnsiCharVar, AnsiText); end;
四、整个”HC RF开发包 V1.4ExampleDelphi7“中rfexamp.pas改编后的完整代码
unit rfexamp; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,StrUtils; type TForm1 = class(TForm) ListBox1: TListBox; Button1: TButton; Label1: TLabel; Button2: TButton; Edit1: TEdit; procedure FormShow(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure Button1Click(Sender: TObject); procedure Button3Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; icdev: longint; snr:longint; nkey,wdata,sendblock:pchar; st,sector,block,loadmode:smallint; status:Array[0..18]of Char; databuff:Array[0..15]of Char; ack:Array[0..255]of Char; datahex:Array[0..31]of Byte; wdatanew:string; MyWideChar: PWideChar; MyString: UnicodeString ; {a example for your to try using .dll. add_s return i+1} function add_s(i: smallint): smallint; stdcall; far;external 'hcrf32.dll' name 'add_s'; {comm function.} //function hc_init(port: smallint;baud:longint): longint; stdcall; // 原来的 function hc_init(port: Short;baud:Integer): Integer; stdcall; far;external 'hcrf32.dll' name 'hc_init'; function hc_exit(icdev: longint):smallint;stdcall; far;external 'hcrf32.dll'name 'hc_exit'; function rf_encrypt(key:pchar;ptrsource:pchar;msglen:smallint;ptrdest:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_encrypt'; function rf_decrypt(key:pchar;ptrsource:pchar;msglen:smallint;ptrdest:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_decrypt'; // //function rf_card(icdev:longint;mode:smallint;snr:pChar):smallint;stdcall; // 原来的 function rf_card(icdev:Integer;mode:Short;snr:PAnsiChar):Short;stdcall; far;external 'hcrf32.dll'name 'rf_card'; function rf_load_key(icdev:longint;mode,secnr:smallint;nkey:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_load_key'; //function rf_load_key_hex(icdev:longint;mode,secnr:smallint;nkey:pchar):smallint;stdcall; // 原来的 function rf_load_key_hex(icdev:Integer;mode,secnr:Short;nkey:PAnsiChar):Short;stdcall; far;external 'hcrf32.dll' name 'rf_load_key_hex'; function rf_authentication(icdev:longint;mode,secnr:smallint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_authentication'; // function rf_read(icdev:longint;adr:smallint;data:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_read'; //function rf_read_hex(icdev:longint;adr:smallint;data:pchar):smallint;stdcall; //原来的 function rf_read_hex(icdev:Integer;adr:Short;data:PAnsiChar):Short;stdcall; far;external 'hcrf32.dll' name 'rf_read_hex'; function rf_write(icdev:longint;adr:smallint;data:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_write'; // function rf_write_hex(icdev:longint;adr:smallint;data:PChar):smallint;stdcall; // 原来的 function rf_write_hex(icdev:Integer;adr:Short;data:PAnsiChar):Short;stdcall; far;external 'hcrf32.dll' name 'rf_write_hex'; function rf_halt(icdev:longint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_halt'; function rf_reset(icdev:longint;msec:smallint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_reset'; //M1 CARD function rf_initval(icdev:longint;adr:smallint;value:longint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_initval'; function rf_readval(icdev:longint;adr:smallint;value:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_readval'; function rf_increment(icdev:longint;adr:smallint;value:longint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_increment'; function rf_decrement(icdev:longint;adr:smallint;value:longint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_decrement'; function rf_restore(icdev:longint;adr:smallint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_restore'; function rf_transfer(icdev:longint;adr:smallint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_transfer'; function rf_check_write(icdev,snr:longint;adr,authmode:smallint;data:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_check_write'; function rf_check_writehex(icdev,snr:longint;adr,authmode:smallint;data:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_check_writehex'; function rf_changeb3(Adr:pchar;keyA:pchar;B0:pchar;B1:pchar;B2:pchar;B3:pchar;Bk:pchar;KeyB:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_changeb3'; //DEVICE //function rf_get_status(icdev:longint;status:pchar):smallint;stdcall; // 原来的 function rf_get_status(icdev:Integer;status: PAnsiChar):Short;stdcall; far;external 'hcrf32.dll' name 'rf_get_status'; function rf_beep(icdev:longint;time:smallint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_beep'; function rf_ctl_mode(icdev:longint;ctlmode:smallint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_ctl_mode'; function rf_disp_mode(icdev:longint;mode:smallint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_disp_mode'; function rf_disp8(icdev:longint;len:longint;disp:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_disp8'; function rf_disp(icdev:longint;pt_mode:smallint;disp:longint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_disp'; // function rf_settimehex(icdev:longint;dis_time:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_settimehex'; function rf_gettimehex(icdev:longint;dis_time:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_gettimehex'; function rf_swr_eeprom(icdev:longint;offset,len:smallint;data:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_swr_eeprom'; function rf_srd_eeprom(icdev:longint;offset,len:smallint;data:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_srd_eeprom'; //ML CARD function rf_authentication_2(icdev:longint;mode,keyNum,secnr:smallint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_authentication_2'; function rf_initval_ml(icdev:longint;value:longint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_initval_ml'; function rf_readval_ml(icdev:longint;rvalue:pchar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_readval_ml'; function rf_decrement_transfer(icdev:longint;adr:smallint;value:longint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_decrement_transfer'; function rf_pro_rst(icdev:longint;_Data:pChar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_pro_rst'; function rf_pro_trn(icdev:longint;problock,recv:pChar):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_pro_trn'; function rf_pro_halt(icdev:longint):smallint;stdcall; far;external 'hcrf32.dll' name 'rf_pro_halt'; function hex_a(hex,a:pChar;length:smallint):smallint;stdcall; far;external 'hcrf32.dll' name 'hex_a'; function a_hex(a,hex:pChar;length:smallint):smallint;stdcall; far;external 'hcrf32.dll' name 'a_hex'; implementation {$R *.DFM} Function Trans(Msg: string): string; var TempPchar: Pchar; i: integer; Str: string; begin TempPchar := Pchar(Msg); //将字符串 Char数组化 i := 0; Str := ''; while i < length(TempPchar) do begin Str := TempPchar[i] + TempPchar[i+1]+ Str ; i := i + 2; end; result := Str; end; procedure AssignEditTextToAnsiChar(Edit: TEdit; var AnsiCharVar: PAnsiChar); var EditText: string; AnsiText: AnsiString; begin // 获取 TEdit 控件中的文本 EditText := Edit.Text; // 将 Delphi 字符串转换为 ANSI 字符串 AnsiText := AnsiString(EditText); // 分配内存来存储 ANSI 字符串(包括结尾的空字符) GetMem(AnsiCharVar, Length(AnsiText) + 1); // 将 ANSI 字符串复制到分配的内存中 StrPCopy(AnsiCharVar, AnsiText); end; procedure AssignStringToAnsiChar(text: string; var AnsiCharVar: PAnsiChar); var AnsiText: AnsiString; begin // 将 Delphi 字符串转换为 ANSI 字符串 AnsiText := AnsiString(text); // 分配内存来存储 ANSI 字符串(包括结尾的空字符) GetMem(AnsiCharVar, Length(AnsiText) + 1); // 将 ANSI 字符串复制到分配的内存中 StrPCopy(AnsiCharVar, AnsiText); end; function AnsiCharToHex(AnsiChar: PAnsiChar): string; var i: Integer; Byte1: Byte; HexStr: string; begin Result := ''; if AnsiChar <> nil then begin // 遍历 ANSI 字符串中的每个字节 i := 0; while AnsiChar[i] <> #0 do // #0 是 ANSI 字符串的结束符 begin Byte1 := Byte(AnsiChar[i]); // 获取当前字节的值 HexStr := IntToHex(Byte1, 2); // 将字节转换为两位十六进制字符串 Result := Result + HexStr; // 添加到结果字符串中 Inc(i); // 继续下一个字节 end; end; end; function AnsiStringToHex(const Input: AnsiString): string; var i: Integer; Byte1: Byte; HexStr: string; begin Result := ''; for i := 1 to Length(Input) do begin Byte1 := Byte(Input[i]); // 获取当前字符的 ANSI 编码字节 HexStr := IntToHex(Byte1, 2); // 将字节转换为两位十六进制字符串 Result := Result + HexStr; // 添加到结果字符串中 end; end; function ByteArrayToHex(const data: array of Byte): string; var hexString: string; i: Integer; begin Result := ''; SetLength(hexString, 2 * Length(data)); // 预先分配足够的空间 for i := Low(data) to High(data) do begin // 使用位操作获取高位和低位十六进制数字,并转换为字符串 //hexString[2 * i + 1] := IntToHex(data[i] ,2); // 低位字符 // hexString[2 * i] := IntToHex(data[i] shr 4)[1]; // 高位字符 // hexString := IntToHex(data[i], 2); // 将字节转换为两位十六进制字符串 // Result := Result + hexString; // 添加到结果字符串中 // Result := Result +'['+IntToStr(i)+']'+IntToHex(Integer(data[i]),1)+'----intstr'+char(data[i]); Result := Result +char(data[i]); // Writeln(data[i]); end; //i :=i+1; // Result := hexString; end; procedure TForm1.FormShow(Sender: TObject); begin //icdev:=hc_init(0,115200); //串口1 波特率115200 icdev:=hc_init(1000,115200); //:取值为 0~19 时,表示串口 1~20;为 100 或大于 100,表示 USB 口通讯,此时波特率参数无效。 if icdev<=0 then listbox1.Items.Add('Init error'); st:=rf_get_status(icdev,@status); if st<>0 then listbox1.Items.Add('Init ERR') else listbox1.Items.Add('Init OK'); listbox1.Items.Add('Hard Ver: '+ status); end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin if icdev>0 then st:=hc_exit(icdev); end; procedure TForm1.Button1Click(Sender: TObject); var value:longint; DelphiString: string; AnsiStringPtr: PAnsiChar; nkeynew,StrPtr: PAnsiChar; HexValue: string; dataread: array[0..31] of Byte; // 读取的数据,16个字节 //nkey: TArray<Byte>; begin snr:=0; sector:=1; block:=sector*4; // 0=a 4=b loadmode:=0; // nkey:= Chr(160) + Chr(161) + Chr(162) + Chr(163) + Chr(164) + Chr(165); // st:=rf_load_key(icdev,loadmode,sector, nkey); // nkey:= Chr(255)+Chr(255)+Chr(255)+Chr(255)+Chr(255)+Chr(255); //st:=rf_load_key(icdev,0,1,nkey); // nkey:='ffffffffffff'; nkey:='FFFFFFFFFFFF'; nkeynew:='FFFFFFFFFFFF'; st:=rf_load_key_hex(icdev,loadmode,sector, nkeynew); //装载密钥到读卡器中 //st:=0; if st<>0 then listbox1.items.add('load key error') else listbox1.items.add('load key Ok'); st:=rf_card(icdev,1,@snr); if st<>0 then listbox1.items.add('card snr error') else listbox1.items.add('card snr Ok:'+Trans(format('%x',[snr]))); st:=rf_authentication(icdev,loadmode,sector); if st<>0 then listbox1.items.add('authentication error') else listbox1.items.add('authentication Ok'); begin // hex写入形式 // 读取输入内容并转换格式 AssignEditTextToAnsiChar(Edit1, StrPtr); try // 在这里你可以使用 AnsiText 变量,它现在指向包含 Edit1 文本内容的 ANSI 字符串 st:=rf_write_hex(icdev,block,StrPtr ) ; // ... finally // 释放之前分配的内存 FreeMem(StrPtr); end; if st<>0 then listbox1.items.add('write hex error') else listbox1.items.add('write hex Ok'); st:=rf_read_hex(icdev,block,@dataread); if st<>0 then listbox1.items.add('read hex error') else // listbox1.items.add('read Ok:'); listbox1.items.add('read hex Ok:'+ ByteArrayToHex(dataread)); wdata:=('这里是染卷ranjuana1a2a3a4a5a6a7a8a1a2a3a4a5a6a7a8'); // 字符串写入 ,最长8个字符 ,截取前面8个字符 st:=rf_write(icdev,block,wdata); if st<>0 then listbox1.items.add('write 字符串 error') else listbox1.items.add('write 字符串 Ok'); st:=rf_read(icdev,block,@databuff); if st<>0 then listbox1.items.add('read 字符串 error') else listbox1.items.add('read 字符串 Ok:'+databuff); st:=rf_halt(icdev); if st<>0 then listbox1.items.add('halt error') else listbox1.items.add('halt Ok'); st:=rf_reset(icdev,10); if st<>0 then listbox1.items.add('reset error') else listbox1.items.add('reset OK'); end; end; procedure TForm1.Button3Click(Sender: TObject); var value:longint; nkeynew:PAnsiChar; StrPtr: PAnsiChar; begin loadmode:=0; sector:=1; //选择0-15扇区的1扇区 block:=sector*4; //选择块号,0-15扇区 包含了 0-63块; nkey:='ffffffffffff'; nkeynew:='ffffffffffff'; st:=rf_load_key_hex(icdev,loadmode,sector, nkeynew); if st<>0 then listbox1.items.add('load keyhex error') else listbox1.items.add('load keyhex Ok'); st:=rf_card(icdev,1,@snr); if st<>0 then listbox1.items.add('card snr error') else listbox1.items.add('card snr Ok:'+inttostr(snr)); st:=rf_authentication_2(icdev,loadmode,sector,block); if st<>0 then listbox1.items.add('authentication_2 error') else listbox1.items.add('authentication_2 Ok'); wdatanew:='b1b2b3b4ffffffffffffffffffffffff'; //Only write 4 byte per time AssignStringToAnsiChar(wdatanew,StrPtr); st:=rf_write_hex(icdev,block,StrPtr); if st<>0 then listbox1.items.add('write hex error') else listbox1.items.add('write hex Ok'); wdatanew:='b5b6b7b8ffffffffffffffffffffffff'; //Only write 4 byte per time AssignStringToAnsiChar(wdatanew,StrPtr); st:=rf_write_hex(icdev,block+1,StrPtr); if st<>0 then listbox1.items.add('write hex error') else listbox1.items.add('write hex Ok'); st:=rf_read_hex(icdev,block,@databuff); //Only read 8 byte per time if st<>0 then listbox1.items.add('read hex error') else listbox1.items.add('read hex Ok:'+databuff); //Value Operation st:=rf_initval_ml(icdev,100); //initvlaue 100 文档无此函数 if st<>0 then listbox1.items.add('initval_ml error.') else listbox1.items.add('initval_ml Ok'); st:=rf_load_key_hex(icdev,loadmode,sector, nkeynew); // st:=rf_transfer(icdev,block+1); st:=rf_initval(icdev,sector*4+1,100); st:=rf_increment(icdev,sector*4+1,100); //st:=rf_decrement_transfer(icdev,sector*4+1,1); //decrement 10 减少1 st:=rf_decrement(icdev,sector*4+1,1); if st<>0 then listbox1.items.add('decrement_transfer error.') else listbox1.items.add('decrement_transer Ok'); st:=rf_readval_ml(icdev,@value); //文档无此函数 if st<>0 then listbox1.items.add('readval_ml error.') else listbox1.items.add('readval_ml Ok: '+inttostr(value)); st:=rf_readval(icdev,sector*4+1,@value); //读取块值 if st<>0 then listbox1.items.add('readval error.') else listbox1.items.add('readval Ok: '+inttostr(value)); st:=rf_halt(icdev); end; end.
PS:这款GH-230Z-YKT是不支持安卓的,如果想要安卓开发可以让客服或供货商推荐别的型号;另外x宝上也有一些性价比更好的读卡器。
下载完整代码包:
https://gitee.com/rorgent/delphi/tree/master/GH-230Z-YKT%E8%AF%BB%E5%8D%A1%E5%99%A8
基于互联网精神,在注明出处的前提下本站文章可自由转载!
本文链接:https://ranjuan.cn/delphi2010-hc-rf-m1card/
赞赏
微信赞赏支付宝赞赏
发表评论