int OneCommand(int cmd, int dlength,BYTE * pBuff,int nTypeAB, int nOutOfTime)
cmd 2字节命令字,参照具体协议
dlength 要发送的pBuff中的数据字节数
pBuff 要发送的数据, 同时也是接收数据缓冲区
nTypeAB 预留,这里请附0, //0 TypeA 1 TypeB
nOutOfTime 接收数据等待超时时间,没有接收到数据,要等待到超时,如果接收到数据,则立即返回
Return
>=0 Success, 实际接收到pBuff中的数据长度
-1 没有接收到数据
-2 发送错误
-3: 数据长度越界,最大允许2048
-10 接收到数据,但数据不正确,一般情况是接收数据校验错误读二代证:
cmd=0x3001
dlength=0 发送数据长度为0
pBuff 缓冲区指针,缓冲区最少1300字节
nTypeAB=1 1表示读取二代证
nOutOfTime=1500 超时时间,建议1500ms
返回数据:pBuff[0]~pBuff[2]标志状态, pBuff[2]==0x90时,说明找读卡成功 此时Return=1288
pBuff[3],pBuff[4]应该为 0x01,0x00 表示文字信息长度为0x0100 即256字节
pBuff[5],pBuff[6]应该为 0x04,0x00 表示图片信息长度为0x0400 即1024字节
从pBuff[7]开始的256字节为文字信息
从pBuff[7+256]字节开始的1024字节为加密压缩的照片 256字节的文字处理,(文字编码格式为GB13000.1 即Unicode)
从头向为按字节截取
项目: 姓名 性别 民族 出生 住址 号码 签发 有效期起 有效期止
字节数:30 2 4 16 70 36 30 16 16
1024字节的照片处理,需要存储为后缀为.wlt的文件,然后调用相应函数进行解码,得到同名的bmp照片如何写成一个Delphi的函数.
还有能把这个函数随便写几个内容吗?来描述下以上变量怎么用.
cmd 2字节命令字,参照具体协议
dlength 要发送的pBuff中的数据字节数
pBuff 要发送的数据, 同时也是接收数据缓冲区
nTypeAB 预留,这里请附0, //0 TypeA 1 TypeB
nOutOfTime 接收数据等待超时时间,没有接收到数据,要等待到超时,如果接收到数据,则立即返回
Return
>=0 Success, 实际接收到pBuff中的数据长度
-1 没有接收到数据
-2 发送错误
-3: 数据长度越界,最大允许2048
-10 接收到数据,但数据不正确,一般情况是接收数据校验错误读二代证:
cmd=0x3001
dlength=0 发送数据长度为0
pBuff 缓冲区指针,缓冲区最少1300字节
nTypeAB=1 1表示读取二代证
nOutOfTime=1500 超时时间,建议1500ms
返回数据:pBuff[0]~pBuff[2]标志状态, pBuff[2]==0x90时,说明找读卡成功 此时Return=1288
pBuff[3],pBuff[4]应该为 0x01,0x00 表示文字信息长度为0x0100 即256字节
pBuff[5],pBuff[6]应该为 0x04,0x00 表示图片信息长度为0x0400 即1024字节
从pBuff[7]开始的256字节为文字信息
从pBuff[7+256]字节开始的1024字节为加密压缩的照片 256字节的文字处理,(文字编码格式为GB13000.1 即Unicode)
从头向为按字节截取
项目: 姓名 性别 民族 出生 住址 号码 签发 有效期起 有效期止
字节数:30 2 4 16 70 36 30 16 16
1024字节的照片处理,需要存储为后缀为.wlt的文件,然后调用相应函数进行解码,得到同名的bmp照片如何写成一个Delphi的函数.
还有能把这个函数随便写几个内容吗?来描述下以上变量怎么用.
读取二代证厂家一般返回一个固定格式的文本和一个bmp头像。
你直接到相应目录去读就是了。
在VB里将接口再次封装,弄出一个新的动态库,供delphi调用。
int OneCommand(int cmd, int dlength,BYTE * pBuff,int nTypeAB, int nOutOfTime)
是一个DLL的函数.这个好象是VB的写法吧?
弄成Delphi怎么写呢?
我这样搞的:
function OneCommand(cmd,dlength:smallInt; pBuff:PChar; nTypeAB,nOutOfTime:smallInt): smallInt;
应该没错吧?
函数的说明是cmd 传入固定值:0x3001 ,dlength 是发送数据长度为0,pBuff缓冲区指针,缓冲区最少32字节 nTypeAB为0,nOutOfTime为1000.
那Delphi 写成:
OneCommand(0x3001,0, pBuff, 1, 1500);0x3001就编译不过去,呵呵.我基础不好, 这样的数字0x3001 在Delphi如何表示呢?
这是C/C++中的写法,不是VB的
转成Delphi这样的试试function OneCommand(cmd: Integer; dLength: Integer; pBuff: PByte; nTypeAB: Integer; nOutOfTime: Integer): Integer; Stdcall;另:
不要忘了Stdcall;
C/C++的int对应Delphi 中的Integer,实际上只要是类型的长度相同就OK了.本来PBuff可以写成PChar的,但是如果在D2009上工作,肯定不行,因为Char<>byte,类似的情况在VC中也是,主要取决于Char的类型定义
var OneCommand:function (cmd: Integer; dLength: Integer; pBuff: PChar;
nTypeAB: Integer; nOutOfTime: Integer): Integer; Stdcall;
pBuff:PChar;
iReturn:Integer;
begin
OneCommand := GetProcAddress(DllHandle,'OneCommand');
iReturn := OneCommand($3001,0, pBuff, 1, 1500);
if iReturn<0 then
begin
showmessage('error');
Exit;
end;
end;
但每次都是返回-1,而使用VC的代码却能正确取得数据.
procedure TfrmSc2Main.btnOneCommandClick(Sender: TObject); pBuff:PChar;
iReturn:Integer;
begin
getMem(pBuff,1300);
OneCommand := GetProcAddress(DllHandle,'OneCommand');
iReturn := OneCommand($3001,0, pBuff, 1, 1500);
if iReturn<0 then
begin
showmessage('error');
Exit;
end;
end;
执行的iReturn >0 调用Dll好像成功了.
但是我Showmessage(pBuff);没有得到相应的值.
并且过程执行完毕会出错.
我这样写的:(你那种写法是编译不过去的)procedure TfrmSc2Main.btn1Click(Sender: TObject);
var pBuff:PChar; iReturn:Integer;
OneCommand:function (cmd:Word;dlenth:word;pbuff:Pchar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
begin
// getMem(pBuff,2048);
pBuff:=StrAlloc(2048);
OneCommand := GetProcAddress(DllHandle,'OneCommand');
iReturn := OneCommand($3001,0, pBuff, 1, 1500);
if iReturn<0 then
begin
showmessage('error');
Exit;
end else begin
ShowMessage(pBuff);
end;
end;
procedure TfrmSc2Main.btn1Click(Sender: TObject);
var pBuff:PChar; iReturn:Integer;
OneCommand:function (cmd:Word;dlenth:word;pbuff:Pchar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
begin
getMem(pBuff,2048);
//pBuff:=StrAlloc(2048);
try
OneCommand := GetProcAddress(DllHandle,'OneCommand');
iReturn := OneCommand($3001,0, pBuff, 1, 1500);
if iReturn<0 then
begin
showmessage('error');
end else begin
ShowMessage(pBuff[0]);
end;
finally
FreeMem(pBuff);
end;
end;
这个写法,返回的pBuff也没有值.郁闷...
var pBuff:PChar; iReturn:Integer;
OneCommand:function (cmd:Word;dlenth:word;pbuff:Pchar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
begin
getMem(pBuff,2048);
//pBuff:=StrAlloc(2048);
try
OneCommand := GetProcAddress(DllHandle,'OneCommand');
iReturn := OneCommand($3001,0, pBuff, 1, 1500);
if iReturn<0 then
begin
showmessage('error');
end else begin
ShowMessage(strPas(pbuff)); //这样试下。
end;
finally
FreeMem(pBuff);
end;
请你多多指教了.呵呵.下面这个是我改了的.但是就是取不到结果返回来的值.就是pBuff为空.不知道怎么搞的..
不知是不是Pchar和PBtye的问题呢?我实在是个菜鸟,PByte不会用.呵呵.
procedure TfrmSc2Main.btn1Click(Sender: TObject);
var pBuff:PChar; iReturn:Integer;
OneCommand:function (cmd:Word;dlenth:word;pbuff:Pchar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
begin
getMem(pBuff,2048);
//pBuff:=StrAlloc(2048);
try
OneCommand := GetProcAddress(DllHandle,'OneCommand');
iReturn := OneCommand($3001,0, pBuff, 1, 1500);
if iReturn<0 then
begin
showmessage('error');
end else begin
ShowMessage(pBuff[0]);
end;
finally
FreeMem(pBuff);
end;
end;
Prjshensiselfcard2
---------------------------
飓C
---------------------------
OK
---------------------------并且执行完毕不知道编译器为什么传出一大把错误...
{
//读身份证卡
int nRet,i;
CString ss,ss1;
BYTE buf[2048];
if(pOneCommand==NULL)
{
m_strEdit.Insert(0,"没有初始化通讯库\r\n");
UpdateData(FALSE);
return;
} nRet=pOneCommand(PICC_RDRead,0,buf,TYPE_ID2,1500); //注意超时时间这里为1.5秒
if(nRet>0)
{..............................省略代码
procedure TfrmSc2Main.btn1Click(Sender: TObject);
var
pBuff:PansiChar; iReturn:Integer;
OneCommand:function (cmd:Word;dlenth:word;pbuff:PAnsichar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
begin
getMem(pBuff,2048);
fillChar(pbuff,2048,#0);
try
OneCommand := GetProcAddress(DllHandle,'OneCommand');
iReturn := OneCommand($3001,0, pBuff, 1, 1500);
if iReturn<0 then
begin
showmessage('error');
end else begin
ShowMessage(strPas(pbuff)); //这样试下。
end;
finally
FreeMem(pBuff);
end; 如果是DELPHI2009,用上面的试试。
var
pBuff:Array[0..2048-1] of AnsiChar;
iReturn:Integer;
OneCommand:function (cmd:Word;dlenth:word;var pbuff:array of AnsiChar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
begin try
OneCommand := GetProcAddress(DllHandle,'OneCommand');
iReturn := OneCommand($3001,0, pBuff, 1, 1500);
if iReturn<0 then
begin
showmessage('error');
end else begin
ShowMessage((pbuff)); //这样试下。
end;
finally
FreeMem(pBuff);
end;
我用Delphi2009的代码测试跟踪返回的是空值.
用最后面的那个Delphi2007的测试返回也是为空.
并且执行iReturn := OneCommand($3001,0, pBuff, 1, 1500);很快.一般不会哪么快的.毕竟要返回很多信息还有身份证的头像照片.
因为用C的调试执行这个代码是需要点时间的.大概一秒左右。你用QQ吗、要不我把C的整个源代码给你看看?另:我在上海,如果方便很想结识你这个朋友,搞定这个可酬谢.
procedure TfrmSc2Main.btn1Click(Sender: TObject);
var
pBuff:Array[0..2048-1] of AnsiChar;
iReturn:Integer;
OneCommand:function (cmd:Word;dlenth:word;var pbuff:array of AnsiChar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
begin try
OneCommand := GetProcAddress(DllHandle,'OneCommand');
iReturn := OneCommand($3001,0, pBuff, 1, 1500);
if iReturn<0 then
begin
showmessage('error');
end else begin
ShowMessage((pbuff)); //这样试下。
end;
finally
FreeMem(pBuff);
end;
这样基本上跟C的就一样了。 Ansichar,Byte 都占用的是一个字节
//二代证命令
#define PICC_RDFind 0x2001
#define PICC_RDAuth 0x2002
#define PICC_RDRead 0x3001#define TYPE_BANK 0
#define TYPE_ID2 1
OneCommand:function (cmd:Word;dlenth:word;var pbuff:array of AnsiChar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
函数与 Dll 函数
#include "WINDEF.h"
extern HINSTANCE hModule;
typedef int (*pFun_OpenComm)(int ,int);
typedef int (*pFun_bCommConnect)(void);
typedef int (*pFun_CloseComm)(void);
typedef int (*pFun_SendData)(int cmd, int dlength,BYTE * pBuff, int nTypeAB);
typedef int (*pFun_RecvData)(BYTE* pBuff,int nOutOfTime);
typedef int (*pFun_OneCommand)(int cmd, int dlength,BYTE * pBuff,int nTypeAB, int nOutOfTime);extern pFun_OpenComm pOpenComm;
extern pFun_bCommConnect pbCommConnect;
extern pFun_CloseComm pCloseComm;
extern pFun_SendData pSendData;
extern pFun_RecvData pRecvData;
extern pFun_OneCommand pOneCommand;extern BOOL LoadComDll();
extern void FreeComDll();
会冲突.所以导致iReturn := OneCommand($3001,0, pBuff, 1, 1500);根本没执行.
#include "StdAfx.h"
#include "ComDll.h"HINSTANCE hModule;pFun_OpenComm pOpenComm;
pFun_bCommConnect pbCommConnect;
pFun_CloseComm pCloseComm;
pFun_SendData pSendData;
pFun_RecvData pRecvData;
pFun_OneCommand pOneCommand;BOOL LoadComDll();
void FreeComDll();BOOL LoadComDll()
{
hModule=LoadLibrary(_T("DllCom.dll"));
if(hModule ==NULL )
{
//AfxMessageBox(_T("加载动态库失败"));
return FALSE;
}
pOpenComm =(pFun_OpenComm)GetProcAddress(hModule,_T("OpenComm"));
pbCommConnect =(pFun_bCommConnect)GetProcAddress(hModule,_T("bCommConnect"));
pCloseComm =(pFun_CloseComm)GetProcAddress(hModule,_T("CloseComm"));
pSendData =(pFun_SendData)GetProcAddress(hModule,_T("SendData"));
pRecvData =(pFun_RecvData)GetProcAddress(hModule,_T("RecvData"));
pOneCommand =(pFun_OneCommand)GetProcAddress(hModule,_T("OneCommand")); if(pOpenComm == NULL || pbCommConnect == NULL || pCloseComm == NULL
|| pSendData == NULL || pRecvData == NULL
|| pOneCommand == NULL )
{
return FALSE;
}
else
{
return TRUE;
}
}void FreeComDll()
{
if(hModule !=NULL )
{
if(pbCommConnect()>0)
{
pCloseComm();
Sleep(500);
}
FreeLibrary(hModule);
hModule=NULL; pOpenComm=NULL;
pbCommConnect = NULL;
pCloseComm = NULL;
pSendData = NULL;
pRecvData = NULL;
pOneCommand = NULL;
} }
先打开串口,连接上设备 ->SendData 这样的吧,可能是某些步骤没有走,就直接发命令了。
这同我上次做IF卡差不多。
extern pFun_OpenComm pOpenComm;
extern pFun_bCommConnect pbCommConnect;
extern pFun_CloseComm pCloseComm;
extern pFun_SendData pSendData;
extern pFun_RecvData pRecvData;
extern pFun_OneCommand pOneCommand;
{
//读身份证卡
int nRet,i;
CString ss,ss1;
BYTE buf[2048];
if(pOneCommand==NULL)
{
m_strEdit.Insert(0,"没有初始化通讯库\r\n");
UpdateData(FALSE);
return;
} nRet=pOneCommand(PICC_RDRead,0,buf,TYPE_ID2,1500); //注意超时时间这里为1.5秒
if(nRet>0)
{
ss="";
for(i=0;i<nRet;i++)
{
ss1.Format("%02X ",buf[i]);
ss+=ss1;
}
ss+="\r\n";
m_strEdit.Insert(0,ss);
if(buf[0]==0x00 && buf[1]==0x00 && buf[2]==0x90) //一般只判断成功即可
{
//身份证读取成功,显示信息
//前256字节为文本,后1024位加密压缩照片
//文本
char byName[32],bySex[4],byFolk[6],byBirth[18],byAddr[72],byIDNum[38],byDep[32],byBegin[18],byEnd[18];
memset(byName ,0,32);
memset(bySex ,0,4);
memset(byFolk ,0,6);
memset(byBirth ,0,18);
memset(byAddr ,0,72);
memset(byIDNum ,0,38);
memset(byDep ,0,32);
memset(byBegin ,0,18);
memset(byEnd ,0,18);
int n;
n=7;
memcpy(byName, &buf[ n],30);n+=30;
memcpy(bySex , &buf[ n], 2);n+=2;
memcpy(byFolk , &buf[ n], 4);n+=4;
memcpy(byBirth, &buf[ n],16);n+=16;
memcpy(byAddr, &buf[ n],70);n+=70;
memcpy(byIDNum, &buf[ n],36);n+=36;
memcpy(byDep, &buf[ n],30);n+=30;
memcpy(byBegin, &buf[ n],16);n+=16;
memcpy(byEnd, &buf[ n],16);n+=16; ss=::SysAllocString((LPCWSTR)&byEnd);
ss.TrimRight();
m_strEdit.Insert(0,ss+"\r\n");
ss=::SysAllocString((LPCWSTR)&byBegin);
ss.TrimRight();
m_strEdit.Insert(0,ss+"\r\n");
ss=::SysAllocString((LPCWSTR)&byDep);
ss.TrimRight();
m_strEdit.Insert(0,ss+"\r\n");
ss=::SysAllocString((LPCWSTR)&byIDNum);
ss.TrimRight();
m_strEdit.Insert(0,ss+"\r\n");
ss=::SysAllocString((LPCWSTR)&byAddr);
ss.TrimRight();
m_strEdit.Insert(0,ss+"\r\n");
ss=::SysAllocString((LPCWSTR)&byBirth);
ss.TrimRight();
m_strEdit.Insert(0,ss+"\r\n");
ss=::SysAllocString((LPCWSTR)&byFolk);
ss.TrimRight();
ss=FOLK[atoi(ss.GetBuffer(ss.GetLength()))];
m_strEdit.Insert(0,ss+"\r\n");
ss=::SysAllocString((LPCWSTR)&bySex); //(CW2A((LPCWSTR)&bySex));
ss.TrimRight();
if(ss=="1")
{
ss="男";
}
else
{
ss="女";
}
m_strEdit.Insert(0,ss+"\r\n");
ss=::SysAllocString((LPCWSTR)&byName);
ss.TrimRight();
m_strEdit.Insert(0,ss+"\r\n");
UpdateData(FALSE);
//照片,保存为文件
if(m_hBitmap!=NULL)
{
DeleteObject(m_hBitmap);
}
int nRet=0;
FILE *fp;
char filename[128]; //ss:=ExtractFilePath(Application.ExeName)+'b.bmp';
TCHAR exePath[128];
GetModuleFileName(NULL,exePath,128);
CString sPath;
sPath.Format("%s",exePath);
for(int i=sPath.GetLength();i>0;i--)
{
if(exePath[i]==0x5c)
{
exePath[i+1]=0x00;
break;
}
}
sprintf(filename,"%szp.wlt",exePath);
//保存文件
fp=fopen(filename, "w+b");
if( fp!=NULL )
{
fwrite(&buf[7+256],1024, 1, fp);
fclose(fp);
}
else
{
return;
}
//解码
nRet=Ftest(filename);
if(nRet==1)
{
//读取文件显示
sprintf(filename,"%szp.bmp",exePath);
m_hBitmap=(HBITMAP)LoadImage(NULL,filename,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);
if(m_hBitmap!=NULL )
{
m_ctBmp.SetBitmap(m_hBitmap);
m_ctBmp.ShowWindow(SW_SHOW);
}
else
{
m_ctBmp.ShowWindow(SW_HIDE);
}
}
else
{
m_ctBmp.ShowWindow(SW_HIDE);
m_strEdit.Insert(0,"照片解码错误\r\n");
} m_strEdit.Insert(0,"读身份证卡成功\r\n");
}
else
{
m_strEdit.Insert(0,"读身份证卡失败\r\n");
}
}
else
{
m_strEdit.Insert(0,"读身份证卡失败,未收到数据\r\n");
}
UpdateData(FALSE);
}
根本就读取不到OneCommand:function (cmd:Word;dlenth:word;var pbuff:array of AnsiChar;nTypeAb:word;nOutOfTime:word):Word;stdcall;我觉得很大程度上是 var pbuff:array of AnsiChar 定义的问题.
因为执行这个过程后都能让读卡器Beep,这个是函数自动的.只要检测读取成功 就会Beep声响.关键是Beep后赋值给返回pbuff时就出现错误了.
这种写法:var pbuff:array of AnsiChar Delphi执行过程中不会报错,但是返回值为空.跟踪时发现 pbuff值根本没被改变.
这种写法:
OneCommand:function (cmd:Word;dlenth:word;pbuff:PAnsichar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
听到读卡器Beep后Delphi会出现错误.
nTypeAB: Integer; nOutOfTime: Integer): Integer; Stdcall;
buf:array [0..2047] of BYTE ;
iReturn:Integer;
begin
OneCommand := GetProcAddress(DllHandle,'OneCommand');
try
iReturn := OneCommand($3001,0, @buf[0], 1, 1500);
if iReturn<0 then
begin
showmessage('OneCommand ERROR');
Exit;
end;
finally end;
end;
array[0..2047] of byte 是相同的。不明白,是不是你那个地方有地方错误。OK就行了。