本篇目录
本文代码仅适用于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';三、使用对应函数片段
varnkeynew,StrPtr: PAnsiChar;StrPtr: PAnsiChar;beginnkeynew:='FFFFFFFFFFFF';st:=rf_load_key_hex(icdev,loadmode,sector, nkeynew); //装载密钥到读卡器中//st:=0;if st<>0 thenlistbox1.items.add('load key error')elselistbox1.items.add('load key Ok');// ----这里省略一些验密等过程wdatanew:='b1b2b3b4ffffffffffffffffffffffff'; //0-9,A-F 的hex格式长度固定32AssignStringToAnsiChar(wdatanew,StrPtr);//转化函数st:=rf_write_hex(icdev,block,StrPtr);if st<>0 thenlistbox1.items.add('write hex error')elselistbox1.items.add('write hex Ok');
用到的转化函数
procedure AssignStringToAnsiChar(text: string; var AnsiCharVar: PAnsiChar);varAnsiText: 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;interfaceusesWindows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,StdCtrls,StrUtils;typeTForm1 = 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;varForm1: 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 CARDfunction 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 CARDfunction 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;varTempPchar: Pchar;i: integer;Str: string;beginTempPchar := Pchar(Msg); //将字符串 Char数组化i := 0;Str := '';while i < length(TempPchar) do beginStr := TempPchar[i] + TempPchar[i+1]+ Str ;i := i + 2;end;result := Str;end;procedure AssignEditTextToAnsiChar(Edit: TEdit; var AnsiCharVar: PAnsiChar);varEditText: 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);varAnsiText: AnsiString;begin// 将 Delphi 字符串转换为 ANSI 字符串AnsiText := AnsiString(text);// 分配内存来存储 ANSI 字符串(包括结尾的空字符)GetMem(AnsiCharVar, Length(AnsiText) + 1);// 将 ANSI 字符串复制到分配的内存中StrPCopy(AnsiCharVar, AnsiText);end;function AnsiCharToHex(AnsiChar: PAnsiChar): string;vari: Integer;Byte1: Byte;HexStr: string;beginResult := '';if AnsiChar <> nil thenbegin// 遍历 ANSI 字符串中的每个字节i := 0;while AnsiChar[i] <> #0 do // #0 是 ANSI 字符串的结束符beginByte1 := Byte(AnsiChar[i]); // 获取当前字节的值HexStr := IntToHex(Byte1, 2); // 将字节转换为两位十六进制字符串Result := Result + HexStr; // 添加到结果字符串中Inc(i); // 继续下一个字节end;end;end;function AnsiStringToHex(const Input: AnsiString): string;vari: Integer;Byte1: Byte;HexStr: string;beginResult := '';for i := 1 to Length(Input) dobeginByte1 := Byte(Input[i]); // 获取当前字符的 ANSI 编码字节HexStr := IntToHex(Byte1, 2); // 将字节转换为两位十六进制字符串Result := Result + HexStr; // 添加到结果字符串中end;end;function ByteArrayToHex(const data: array of Byte): string;varhexString: string;i: Integer;beginResult := '';SetLength(hexString, 2 * Length(data)); // 预先分配足够的空间for i := Low(data) to High(data) dobegin// 使用位操作获取高位和低位十六进制数字,并转换为字符串//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 波特率115200icdev:=hc_init(1000,115200); //:取值为 0~19 时,表示串口 1~20;为 100 或大于 100,表示 USB 口通讯,此时波特率参数无效。if icdev<=0 thenlistbox1.Items.Add('Init error');st:=rf_get_status(icdev,@status);if st<>0 thenlistbox1.Items.Add('Init ERR')elselistbox1.Items.Add('Init OK');listbox1.Items.Add('Hard Ver: '+ status);end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);beginif icdev>0 thenst:=hc_exit(icdev);end;procedure TForm1.Button1Click(Sender: TObject);varvalue:longint;DelphiString: string;AnsiStringPtr: PAnsiChar;nkeynew,StrPtr: PAnsiChar;HexValue: string;dataread: array[0..31] of Byte; // 读取的数据,16个字节//nkey: TArray<Byte>;beginsnr:=0;sector:=1;block:=sector*4; // 0=a 4=bloadmode:=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 thenlistbox1.items.add('load key error')elselistbox1.items.add('load key Ok');st:=rf_card(icdev,1,@snr);if st<>0 thenlistbox1.items.add('card snr error')elselistbox1.items.add('card snr Ok:'+Trans(format('%x',[snr])));st:=rf_authentication(icdev,loadmode,sector);if st<>0 thenlistbox1.items.add('authentication error')elselistbox1.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 thenlistbox1.items.add('write hex error')elselistbox1.items.add('write hex Ok');st:=rf_read_hex(icdev,block,@dataread);if st<>0 thenlistbox1.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 thenlistbox1.items.add('write 字符串 error')elselistbox1.items.add('write 字符串 Ok');st:=rf_read(icdev,block,@databuff);if st<>0 thenlistbox1.items.add('read 字符串 error')elselistbox1.items.add('read 字符串 Ok:'+databuff);st:=rf_halt(icdev);if st<>0 thenlistbox1.items.add('halt error')elselistbox1.items.add('halt Ok');st:=rf_reset(icdev,10);if st<>0 thenlistbox1.items.add('reset error')elselistbox1.items.add('reset OK');end;end;procedure TForm1.Button3Click(Sender: TObject);varvalue:longint;nkeynew:PAnsiChar;StrPtr: PAnsiChar;beginloadmode:=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 thenlistbox1.items.add('load keyhex error')elselistbox1.items.add('load keyhex Ok');st:=rf_card(icdev,1,@snr);if st<>0 thenlistbox1.items.add('card snr error')elselistbox1.items.add('card snr Ok:'+inttostr(snr));st:=rf_authentication_2(icdev,loadmode,sector,block);if st<>0 thenlistbox1.items.add('authentication_2 error')elselistbox1.items.add('authentication_2 Ok');wdatanew:='b1b2b3b4ffffffffffffffffffffffff'; //Only write 4 byte per timeAssignStringToAnsiChar(wdatanew,StrPtr);st:=rf_write_hex(icdev,block,StrPtr);if st<>0 thenlistbox1.items.add('write hex error')elselistbox1.items.add('write hex Ok');wdatanew:='b5b6b7b8ffffffffffffffffffffffff'; //Only write 4 byte per timeAssignStringToAnsiChar(wdatanew,StrPtr);st:=rf_write_hex(icdev,block+1,StrPtr);if st<>0 thenlistbox1.items.add('write hex error')elselistbox1.items.add('write hex Ok');st:=rf_read_hex(icdev,block,@databuff); //Only read 8 byte per timeif st<>0 thenlistbox1.items.add('read hex error')elselistbox1.items.add('read hex Ok:'+databuff);//Value Operationst:=rf_initval_ml(icdev,100); //initvlaue 100 文档无此函数if st<>0 thenlistbox1.items.add('initval_ml error.')elselistbox1.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 减少1st:=rf_decrement(icdev,sector*4+1,1);if st<>0 thenlistbox1.items.add('decrement_transfer error.')elselistbox1.items.add('decrement_transer Ok');st:=rf_readval_ml(icdev,@value); //文档无此函数if st<>0 thenlistbox1.items.add('readval_ml error.')elselistbox1.items.add('readval_ml Ok: '+inttostr(value));st:=rf_readval(icdev,sector*4+1,@value); //读取块值if st<>0 thenlistbox1.items.add('readval error.')elselistbox1.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
发表评论