谁能帮帮我这个怎么实现IC卡的读写,已经有接口了。100块大洋相送,不够再加啊!(100分)

  • 主题发起人 主题发起人 kylejiang
  • 开始时间 开始时间
K

kylejiang

Unregistered / Unconfirmed
GUEST, unregistred user!
我正在学习用delphi进行IC卡应用编程,已经有一些接口提供了,可是都不是delphi的。不知道怎么样实现IC卡的读写操作,希望大家帮帮我吧。附上接口函数:
MCS_Request 函数搜索天线范围内是否有Mifare卡存在。

WORD MCS_Request(
BYTE _bMode,
WORD *_wTagType
);
*****************************
MCS_Anticoll 函数通过防碰撞机制,获得天线范围内的一张卡的卡号。

WORD MCS_Anticoll(
BYTE _bBcnt,
DWORD *_dwSnr
);
************************************
MCS_Select 函数选定天线范围内指定卡号的卡片。

WORD MCS_Select(
DWORD _dwSnr,
BYTE *_bSize
);
**********************************
MCS_Authentication 函数进行读写器控制模块与Mifare卡的认证。
在选定一张卡片后,进行读写操作之前应首先调用此函数进行认证。
WORD MCS_Authentication(
BYTE _bMode,
BYTE _bSecNr
);
要对卡片进行认证的扇区号,对于Mifare S50卡,其范围为(0 - 15),
MCS_Read 函数从卡片内的指定块地址读取一字符串。此函数受MCS_SetStringMode影响
************************************
WORD MCS_Read(
BYTE _bAdr,
BYTE *_bData
);

参数
_bAdr
要读取的块地址。对于Mifare S50卡,其范围为(0 - 63),对于Mifare L10卡,其范围为(0 - 11)。

_bData
字符型指针,指向从卡片存储区内读到的字符串并返回给应用程序。在HEXADECIMAL模式下,应用程序应确保在调用此函数前,已分配给_bData指针至少16个字节的空间;在ASCIISTRING模式下,应确保已分配给_bData指针至少32个字节的空间。
*******************************************
MCS_Write 函数向卡片内的指定块地址写入一字符串。 此函数受MCS_SetStringMode影响。

WORD MCS_Write(
BYTE _bAdr,
BYTE *_bData
);

参数
_bAdr
要写入的块地址。对于Mifare S50卡,其范围为(0 - 63),对于Mifare L10卡,其范围为(0 - 11)。

_bData
字符型指针,其内容为要写入到卡片内的字符串。在HEXADECIMAL模式下,应用程序应确保在调用此函数前,已分配给_bData指针至少16个字节的空间;在ASCIISTRING模式下,应确保已分配给_bData指针至少32个字节的空间。
************************************

MCS_Init_Value 函数将卡片内的指定块地址初始化为数值0。

WORD MCS_Init_Value(
BYTE _bAdr
);

参数
_bAdr
要初始化的块地址。对于Mifare S50卡,其范围为(0 - 63),对于Mifare L10卡,其范围为(4 - 5)。
**************************************
MCS_Read_Value 函数从卡片内的指定块地址读取一数值。

WORD MCS_Read_Value(
BYTE _bAdr,
long *_lValue
);

参数
_bAdr
要读取的块地址。对于Mifare S50卡,其范围为(0 - 63),对于Mifare L10卡,其范围为(4 - 5)。

_lValue
长整数型指针,其内容为从卡片内读取到的数值。

*************************************************
1)请问一张新卡是怎么生成的啊,要先经过那些步骤呢?
2)如果仅仅是往卡里写入userID 和 用户名 ,怎么写入啊?


 
问题一,象上面的MCS_Write和MCS_Read函数,他们所说的‘字符串’到底是多少字节呢?是遇到#0为止吗?
问题二,从提供的函数看,我们的程序就只能不断检测是否有卡过来?这样cpu占用率一定很高的?

好,先不管这个,看看变量在内存中的情况,现在假设我们已经把卡中16个字节读到我们的内存中了(buffer)

定义 内存情况
buffer :array[1..16] of byte [][][][][][][][][][][][][][][][](一共16字节)
id:longint; [][][][](一共4个字节)
name:string[12]; [][][][][][][][][][][][][](共13字节第1个表示字符串长度)
我们要做的就是把buffer的前4字节复制到id的4个字节,buffer的后12个字节复制到name的后12个字节,
且要确认name第1个字节为12,那么怎么用高级语言表示呢?
id:=(Pinteger(@buffer[1]))^;
for i:=1 to 12 do
name:=char(buffer[4+i]);
name[0]:=12;
这样就从连续的内存分解出来了,也可以直接定义一个紧凑型的类型,包含上述两个域,更方便.
还有,能这样取的前提是,您以前也用相同的方法保存id和name的:
(Pinteger(@buffer[1]))^:=id
for i:=1 to 12 do
buffer[4+i]:=byte(name);

我只是说一个大概的意思,有错误的地方请包含.应该还有更简便的写法,请大家指教.

 
哪位朋友搞过的,请指教,我愿意加分,多少都可以!因为现在有些信息可以读出来了,很激动!
 
首先制作 Dll 的接口文件。

unit XXXDllUnit;

interface

uses windows;

Const
XXXDllName='xxx.dll';

function MCS_Reuset(_BMode:Byte;_wTagType:PWord):DWORD;stdcall; external XXXDllName;

function MCS_Anticoll(_bBcnt:Byte;_dwSnr:PWord):DWORD;stdcall; external XXXDllName;

function MCS_Select(_dwSnr:PWord;_bSize:Byte):DWORD;stdcall; external XXXDllName;

function MCS_Authentication(_bMode:Byte;_bSecNr:Byte):DWORD;stdcall; external XXXDllName;

function MCS_Read(_bAdr:Byte;_bData:PByte):DWORD;stdcall; external XXXDllName;

function MCS_Write(_bAdr:Byte;_bData:PByte):DWORD;stdcall; external XXXDllName;

function MCS_Read_Value(_bAdr:Byte;_lValue:PLongint):DWORD;stdcall; external XXXDllName;

function Init_Value(_bAdr:Byte):DWORD;stdcall; external XXXDllName;

implementation

end.
 
您没有提供返回值的意义,所以暂时只能当它们都可以正确执行。
 
1)请问一张新卡是怎么生成的啊,要先经过那些步骤呢?

用一个 Timer 检测。时间设置合适的话 CPU 不会很忙。

先用 MCS_Reuset() 函数检测卡,MCS_Anticoll()找到卡。MCS_Select()选定卡。

用 MCS_Init_Value() 清空卡。

一个空卡就出来了。
 
它们的字符串其实是字节(Byte),所以不能用 PChar,所以不能以 #0 结束。
但你可以把 PChar的数据Copy 到 PByte 区。

既然你可以读出数据,还有什么问题,数据能读出来,就能写进去,我认为剩下的就是流程了。


 
谢谢麻子和wang_80919兄,你们的意见我都收藏了。
现在已经可以监测了,但是对于刚刚进来的新卡我还是没有办法读到数据。我看了一下文档,大概读的过程是这样的(不一定对):
MCS_InitComm(1,115200) //连接到读写机 1 为com2 115200为波特率 成功
MCS_Request(1,@Tagtype) //检测是否有卡 1表示所有的卡, @tagtype表示卡型 成功
MCS_Anticoll(0,@_dwSnr) //获得一张卡的卡号 。0是默认值,_dwSnr存储卡号 成功
MCS_Select(_dwSnr,@cSize) //选择指定卡号的卡, cSize表示容量 成功
MCS_Load_Key(0,0,255,255,255,255,255,255) //加载B模式密钥 , 成功
MCS_Authentication(0,0) //对0区进行验证,成功 (只有成功以后才能进行下面的读写)
MCS_Read(0,@cBuffer) //对0块进行读取数据,保存在@cBuffer里面 。失败?
但是我在edit3.text:=cBuffer的时候里面是空。这是不正常的,因为Mifare s50 IC卡出厂时候就应该写入了生产商的代码(在0块地址上)。
(cBuffer我是这样定义的, cBuffer:string[16] ;)
大家看看那里错了啊??着急啊!!
 
向卡上写数据之前需校验卡密码
 
怎么效验呢?您读卡的整个过程能讲讲吗?
 
wang_80919,說的對啊...得先要做個dll
 
你有没有接口的头文件,就是后缀名为H的文件,用它来转换DELPHI的声明文件,然后调用就可以了。
 
dll已经有了,里面函数也能调用,现在就是怎么用不知道。[:(]是一些很具体的问题。
这里还有分:http://www.delphibbs.com/delphibbs/dispq.asp?lid=2488535 请笑纳
 
如果是Mifare one(M1) 的非触IC卡,它的特性是这样的
Mifare l卡特性简介
M1卡为8K位的非接触式IC卡。
电气特性
容量为8K位EEPrOM
分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位
每个扇区有独立的一组密码及访问控制
每张卡有唯一序列号,为32位
具有防冲突机制,支持多卡操作
无电源,自带天线,内含加密控制逻辑和通讯逻辑电路
工作温度:-20℃~50℃
工作频率:13.56MHZ
通信速率:106KBPS
读写距离:10mm以内(与读写器有关)
数据保存期为10年,可改写10万次,读不限次
存储结构
M1卡分为16个扇区,每个扇区4块(块0~3),共64块,按块号编址为0~63。第0扇区的块0(即绝对地址0块)用于存放厂商代码,已经固化,不可更改。其他各扇区的块0、块1、块2为数据块,用于存贮数据;块3为控制块,存放密码A、存取控制、密码B
对M1卡的读写操作均需要校验密码,只有密码校验成功后才能进行读写操作。 可通过设置存取控制来设置密码A或密码B只能进行读或者只能写行写,不过一般出厂时,都默认设置为密码A能进行读写操作。
一般操作顺序
(1)程序开始,初始化串口。
(2)寻卡,
相当于连续进行
寻卡请求
防止卡冲突,返回卡的序列号
从多个卡中选取一个给定序列号的卡

(3)对单个扇区操作,顺次执行A~D;
对多个扇区操作,循环执行A~D;
A、选定要操作的扇区;
B、装载密码;
C、验证密码;
D、进行操作,包括读写及值操作。
(4)中止操作。
(5)关闭串口。
 
1)请问一张新卡是怎么生成的啊,要先经过那些步骤呢?
答:对卡片操作是这样的步骤:按这顺序调用上面给出的函数
1。寻卡:
MCS_Request 函数搜索天线范围内是否有Mifare卡存在。

WORD MCS_Request(
BYTE _bMode,
WORD *_wTagType
);
2。防冲突:
MCS_Anticoll 函数通过防碰撞机制,获得天线范围内的一张卡的卡号。

WORD MCS_Anticoll(
BYTE _bBcnt,
DWORD *_dwSnr
);
3。选卡:
MCS_Select 函数选定天线范围内指定卡号的卡片。

WORD MCS_Select(
DWORD _dwSnr,
BYTE *_bSize
);
4。密码验证:
MCS_Authentication 函数进行读写器控制模块与Mifare卡的认证。
在选定一张卡片后,进行读写操作之前应首先调用此函数进行认证。
WORD MCS_Authentication(
BYTE _bMode,
BYTE _bSecNr
);
这样就可以对卡进行读写操作了。

你的步骤都对了,认真检查一下哪出了问题吧!可以试试其他扇区啊!不要试0那么特殊嘛!
 
[8D]我们读‘ 第0扇区的块0 ’是想看看厂商代码多少 [:D]
现在看来,没那么简单,不行! [:(] (这个主意是我出的,抱歉[^])
 
lbylby说的读卡过程我完全同意!!
厂商的卡信息肯定是不能读出来的!还有,每一个块要进行读写操作都要进行校验,注意到16个区有16个校验区,这说明可以控制每一个区的读写权限。能读写第0区的不一定能读写第1区!这个可以在程序里控制!
不过在调用MCS_Authentication 前该先调用MCS_Load_Key 函数将密钥下载至读写器控制模块内,然后才能认证。
 
谢谢大家的支持,在生产商的指点下已经可以争取读去了。其实我们采用这种IC卡是将来作为一种身份认证用的。希望大家继续讨论下去啊。
非常赞成app2001兄的意见,是应该按照这样的步骤的。
分数我会分给大家,不过我还是想知道大家能够谈谈这方面的开发经验。谢谢!!
 
谢谢大家的支持,特别是麻子兄从始至终的帮助和摇旗呐喊。
 
不客气,嘻嘻
 
后退
顶部