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/
赞赏
微信赞赏
支付宝赞赏
发表评论