各位高手:
小弟初次接触IC卡,只看了一些参考书,晕!想请教一些问题,谢谢!(用敏华接触式读卡器)
1.向生产卡的供应商拿了几张卡,他告诉我已做了初始化,这是什么意思,我在一些参考书上关于IC卡的应用程序上也有初始化程序,这两者有区别吗?我拿了这些供应商提供的卡还需初始化吗?
2.书上说对卡的读写首先需要检验密码,连续几次密码错误,卡会烧掉,则密码供应商是否会提供(据说供应商不愿提供),在我编程的时候密码是否要写在程序中?
3.听说对数据的读写都是十六制的并且要知道地址,如何知道卡的具体地址数(听说是块操作,且每个块都要一次性写满,否则出错).
4.据说每次对卡的操作都要经过上下电的程序,这是什么意思?
总之,对ic卡的知识极度匮乏,各位费心了!这好象和计算机的读写方式不一样吧

解决方案 »

  1.   

    我有一点 mifire 1的资料, 别的卡也大同小异,供参考二、 存储结构
    1、 M1卡分为16个扇区,每个扇区由4块(块0、块1、块2、块3)组成,(我们也将16个扇区的64个块按绝对地址编号为0~63,存贮结构如下图所示:   
    块0       数据块 0
    扇区0   块1 数据块 1
    块2 数据块 2
    块3 密码A   存取控制   密码B 控制块 3
       块0 数据块 4
    扇区1 块1 数据块 5
    块2 数据块 6
    块3 密码A   存取控制   密码B 控制块 7
                ∶      ∶      ∶
         0 数据块 60
    扇区15     1 数据块 61
      2 数据块 62
      3 密码A    存取控制   密码B 控制块 632、 第0扇区的块0(即绝对地址0块),它用于存放厂商代码,已经固化,不可更改。
    3、 每个扇区的块0、块1、块2为数据块,可用于存贮数据。
       数据块可作两种应用:
    ★ 用作一般的数据保存,可以进行读、写操作。
    ★ 用作数据值,可以进行初始化值、加值、减值、读值操作。
    4、 每个扇区的块3为控制块,包括了密码A、存取控制、密码B。具体结构如下:
                    密码A(6字节)  存取控制(4字节) 密码B(6字节)  5、 每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制。存取控制为4个字节,共32位,扇区中的每个块(包括数据块和控制块)的存取条件是由密码和存取控制共同决定的,在存取控制中每个块都有相应的三个控制位,定义如下:
        
              块0:   C10   C20   C30
              块1:   C11   C21   C31
              块2:   C12   C22   C32
              块3:   C13   C23   C33
      三个控制位以正和反两种形式存在于存取控制字节中,决定了该块的访问权限(如  
      进行减值操作必须验证KEY A,进行加值操作必须验证KEY B,等等)。三个控制
      位在存取控制字节中的位置,以块0为例:
     
       对块0的控制:
               bit  7    6     5       4     3      2      1      0
    字节6 C20_b C10_b
    字节7 C10 C30_b
    字节8 C30 C20
    字节9
                    ( 注: C10_b表示C10取反 )      存取控制(4字节,其中字节9为备用字节)结构如下所示:
              bit  7    6      5       4     3      2      1      0
    字节6 C23_b C22_b C21_b C20_b C13_b C12_b C11_b C10_b
    字节7 C13 C12 C11 C10 C33_b C32_b C31_b C30_b
    字节8 C33 C32 C31 C30 C23 C22 C21 C20
    字节9
                         ( 注: _b表示取反 )    6、数据块(块0、块1、块2)的存取控制如下:  控制位(X=0.1.2)            访 问 条 件 (对数据块 0、1、2)
    C1X C2X C3X  Read  Write  Increment Decrement, transfer,Restore
    0 0 0 KeyA|B KeyA|B KeyA|B KeyA|B
    0 1 0 KeyA|B Never Never Never
    1 0 0 KeyA|B KeyB Never Never
    1 1 0 KeyA|B KeyB KeyB KeyA|B
    0 0 1 KeyA|B Never Never KeyA|B
    0 1 1 KeyB KeyB Never Never
    1 0 1 KeyB Never Never Never
    1 1 1 Never Never Never Never
         (KeyA|B 表示密码A或密码B,Never表示任何条件下不能实现)
      例如:当块0的存取控制位C10 C20 C30= 1 0 0时,验证密码A或密码B正确后可读;
            验证密码B正确后可写;不能进行加值、减值操作。    7、控制块块3的存取控制与数据块(块0、1、2)不同,它的存取控制如下: 密码A 存取控制 密码B
    C13 C23 C33 Read Write  Read Write Read Write
    0 0 0 Never KeyA|B KeyA|B Never KeyA|B KeyA|B
    0 1 0 Never Never KeyA|B Never KeyA|B Never
    1 0 0 Never KeyB KeyA|B Never Never KeyB
    1 1 0 Never Never KeyA|B Never Never Never
    0 0 1 Never KeyA|B KeyA|B KeyA|B KeyA|B KeyA|B
    0 1 1 Never KeyB KeyA|B KeyB Never KeyB
    1 0 1 Never Never KeyA|B KeyB Never Never
    1 1 1 Never Never KeyA|B Never Never Never
       例如:当块3的存取控制位C13 C23 C33= 0 0 1时,表示:
               密码A:不可读,验证KEYA或KEYB正确后,可写(更改)。
             存取控制:验证KEYA或KEYB正确后,可读、可写。
               密码B:验证KEYA或KEYB正确后,可读、可写。新卡片中的控制字为:“FF 07 80 69”,其定义中说明密码A可用,密码B不可用,新卡中所有密码A都为6个字节的“FF”;   推荐的控制字
    方案一:7F 07 88 69
       此控制字说明:数据块:用密码A或B都可以读写;
                     控制块:密码A:由密码B来写,不可读;
                             密码B:由密码B来写,不可读;
                             控制字:用密码A或B都可读,由密码B写;
    方案二:08 77 8F 69
       此控制字说明:数据块:用密码A读,由密码B读写;
                     控制块:密码A:由密码B来写,不可读;
                             密码B:由密码B来写,不可读;
                             控制字:用密码A或B都可读,由密码B写;三、 卡片
    卡片的电气部分只由一个天线和ASIC组成。
    天线:卡片的天线是只有几组绕线的线圈,很适于封装到IS0卡片中。
    ASIC:卡片的ASIC由一个高速(106KB波特率)的RF接口,一个控制单元和一个
          8K位EEPROM组成。四、对数据块的操作 
    读 (Read):读一个块;
    写 (Write):写一个块;
    加(Increment):对数值块进行加值;
    减(Decrement):对数值块进行减值;
    存储(Restore):将块中的内容存到数据寄存器中;
    传输(Transfer):将数据寄存器中的内容写入块中;
        中止(Halt):将卡置于暂停工作状态;
      

  2.   

    1.向生产卡的供应商拿了几张卡,他告诉我已做了初始化,这是什么意思,我在一些参考书上关于IC卡的应用程序上也有初始化程序,这两者有区别吗?我拿了这些供应商提供的卡还需初始化吗? 给你卡的供应商,应该不是生产商,可能是一些做卡应用行业的公司,他们拿给你的卡,并且说已初始化,则很可能是加密码了,只能他们自己的设备来使用。
    2.书上说对卡的读写首先需要检验密码,连续几次密码错误,卡会烧掉,则密码供应商是否会提供(据说供应商不愿提供),在我编程的时候密码是否要写在程序中? 
    不会烧掉的。16个扇区,除了0扇区的密码不提供外,其他的都是12个f
    3.听说对数据的读写都是十六制的并且要知道地址,如何知道卡的具体地址数(听说是块操作,且每个块都要一次性写满,否则出错). 
    这个不懂。
    4.据说每次对卡的操作都要经过上下电的程序,这是什么意思? 
    这个也不懂。
    总之,对ic卡的知识极度匮乏,各位费心了!这好象和计算机的读写方式不一样吧附资料,你看一下:http://baike.baidu.com/view/4189.htm
      

  3.   

    这个厂家都会提供各个语言的调用demo,楼主不清楚的地方最好问厂家。
      

  4.   

    1.向生产卡的供应商拿了几张卡,他告诉我已做了初始化,这是什么意思,我在一些参考书上关于IC卡的应用程序上也有初始化程序,这两者有区别吗?我拿了这些供应商提供的卡还需初始化吗? 
      给你卡的供应商,应该不是生产商,可能是一些做卡应用行业的公司,他们拿给你的卡,并且说已初始化,则很可能是加密码了,只能他们自己的设备来使用。 haochin回答的正确,应该是供应商提前将卡内设置密码了,你在读写该卡时都需要用密码提前验证,因此你必须问供应商要到该密码。2.书上说对卡的读写首先需要检验密码,连续几次密码错误,卡会烧掉,则密码供应商是否会提供(据说供应商不愿提供),在我编程的时候密码是否要写在程序中? 
      确切的说如果密码多次错误,会导致卡锁死,倒不至于烧掉,当然卡锁死的话,也就不能再对该卡进行读写了。至于密码,是厂家自己定的出厂密码,肯定会告诉你的,否则你读写卡是无法通过密码验证,而且这个密码一般还允许自行设定,所以你编程的时候肯定要用的密码。
    3.听说对数据的读写都是十六制的并且要知道地址,如何知道卡的具体地址数(听说是块操作,且每个块都要一次性写满,否则出错). 
      数据的读写一般是2进制或16进制,而是否需要知道地址,这个需要根据厂家提供的通讯协议来确定
    4.据说每次对卡的操作都要经过上下电的程序,这是什么意思? 
      上下电是一次读写卡的操作步骤而已,你想象成开始,结束就行。比如一次读写卡的步骤是:上电,判断读卡器有卡,验证卡密码,读写卡数据,下电
      

  5.   

    要回答你的问题,首先要搞清楚你用的是接触式的IC卡还是非接触式的IC卡
    前面的回答均是针对非接触式IC卡来的,但我看你用的应该是接触式的IC卡,应为你提到你用的是明华的接触式读写器。如果你用的是接触式的IC卡,那么答案应该就不一样了。
    1:两种卡是一样的,初始化的意思应该是修改了原始的密码,也即是说已经写了新密码了
    2:非接触式IC卡的密码可以随便校验,密码错了再试多少次也没有问题,但接触式的IC卡应该是试了N次后卡会被锁死的。如果你要对其编程,一般来说两种卡都需要知道密码。
    3:读写卡要通知读写器我要读写哪个区那个块
    4:卡内有芯片,存储了数据,没有电怎么读?只不过两种卡的电的来源不一样。一般明华的读写器都附带有很详细的说明,你可以看看说明。
      

  6.   

    1.向生产卡的供应商拿了几张卡,他告诉我已做了初始化,这是什么意思,我在一些参考书上关于IC卡的应用程序上也有初始化程序,这两者有区别吗?我拿了这些供应商提供的卡还需初始化吗?
    答:初始化就是向IC卡里写入了认证密码(IC卡出厂的时候默认为空密码),对写入认证密码之后的IC卡读写,必须使用相同的密码认证,否则就无法对IC卡读写,应用程序的初始化应该是读卡器芯片的初始化吧。你拿的IC卡,发卡操作时读卡器就对IC卡进行了初始化。
    2.书上说对卡的读写首先需要检验密码,连续几次密码错误,卡会烧掉,则密码供应商是否会提供(据说供应商不愿提供),在我编程的时候密码是否要写在程序中? 
    答:这个密码是读卡器和IC卡之间通讯的认证秘钥,如果供应商不原意提供,就是说读卡器初始化卡的时候写入了一个只有读卡器供应商知道的、固定的密码,你就不需要管这个密码了。如果读卡器厂商提供的应用接口可以改写这个密码,你就要管理起这个密码了。也就是初始化卡时你写入什么密码,你读写这些初始化过的卡时,必须使用相同的密码来认证。
    3.听说对数据的读写都是十六制的并且要知道地址,如何知道卡的具体地址数(听说是块操作,且每个块都要一次性写满,否则出错).
    答:卡存储分块,区。不同的卡容量不同,根据卡片类型对应处理。 
    4.据说每次对卡的操作都要经过上下电的程序,这是什么意思?
    答:上电有点奇怪,如果卡片拿到了读卡器的射频区(读卡器通过固定频率如13.56M发射射频能量,通讯的编码调制在这个固定频率上),IC卡的线圈接收射频能量,可能就几个mS,IC卡的电路充电后就可以正常工作了,也就算是上电吧。IC卡的内容读写之前需要一系列的认证步骤。真正的下电就是把IC卡从读卡器的射频区移开。这里的下电可能是指IC卡的IDLE吧,IC卡休眠之后就不再响应读卡器的通讯请求了(当然如果从射频区移开,IC卡电路冷重启之后就可以相应请求了)。因为读卡器读卡是快速定时扫描的,比如1秒钟50次,如果你不休眠,可能会在你刷卡的一两秒钟之间,发生多次读写(可能就多次扣钱了,呵呵)。
      

  7.   

    仔细看一下,卡的说明书,很简单的 不懂的话,再上Google
      

  8.   

    其实上位机编程是很简单的,楼主可以到供应商网上下载示例程序,一看就明白的。
    timic,mifare卡结构不同,你只要知道卡结构怎么存储,一般读卡器供应商都给你写好了底层代码,你只要调用读写等命令就好了.
      

  9.   

    ding le~
    密码不对会烧掉的
      

  10.   

    我再补充一句:非接触卡通常不会密码锁死,也不需要上电操作,而接触式的逻辑加密卡或cpu卡入连续多次密码错误则可能锁卡,且需要上电操作。
      

  11.   

    各位大佬的回复非常感激,但因是新手故还需讨教.我有一个明华接触式读写器(URD系列),拿了几张卡,用明华随机DEMO测试为ATMEL系列(AT24C01A),用参考尽收眼底中的程序进行试验,可以读和写,但是程序中只有一个字段(用EDIT),但是如果有几个字段呢?另外理解各位大佬的回复似乎是应根据地址读和写,但在程序中没发现
    (可以是我不懂),请指教.大致程序如下:
    procedure TForm1.Button1Click(Sender: TObject);//读
    begin
      if edit1.Text='' then
         begin
           application.MessageBox('数据不能为空','');
           exit; 
         end;
      if Open_Card() then
         if Write_card(pchar(edit1.Text)) then
          if CLose_Card then
            begin
            end;
    end;
    procedure TForm1.Button2Click(Sender: TObject);//写 begin
    If OPen_Card Then
        begin
        edit2.Text := Read_Card;
         If Close_card Then
            begin
             Exit;
            end;
        end;
    end;unit U_Card;
      interface
       {1} //打开设备,进行口令验正
        function Open_Card():Boolean;
        
       {2} // 关闭设备
        function CLose_Card():boolean;
       {3} // 写卡,对卡进行写操作
        function Write_card(COntent:pchar):boolean;
       {4}//对卡进行读操作
        function Read_Card():string;
       {5} //写卡时内容组织
        function Content(aa:string):string;
       {6}//卡片比效函数
        function Card_Compare():boolean;
        {7}//是否有卡片在驱动器里
        function Check_card():Boolean;
     implementation
     uses u_public_define,dialogs,sysutils,StrUtils;   {1} //打开设备,进行口令验正
        function Open_Card():Boolean;
          var
             Status:integer;
             aa:array[0..2]of char;
         begin
           //       g_icdev:=auto_init(0,9600);
             g_st:=setsc_md(g_icdev,1);        aa:=chr(0)+chr(0)+chr(0);
            //  g_icdev:=auto_init(0,9600);
              G_st := cmp_dvsc(G_icdev, 3, aa);          G_st:=setsc_md(G_icdev, 0);          G_st:=get_status(G_icdev, @Status);
            If G_st < 0 Then
              begin
                 showmessage('驱动器有错误!请检查设备后继续使用!');
                 OPen_Card:= False;
                // G_st :=ic_exit(G_icdev);
                  Exit;
             end;
                  OPen_Card := True;
         end;
       {2} // 关闭设备
        function CLose_Card():boolean;
          begin
           G_st := ic_exit(G_icdev);
         If G_st < 0 Then
          begin
          showmessage('关闭设备时有误,请重新启动系统');
           close_card:=false;
           exit;
          end;
          close_card:=true;
          //
          end;
       {3} // 写卡,对卡进行写操作
        function Write_card(COntent:pchar):boolean;
         begin
            G_st := swr_eeprom(G_icdev, 0, 384, Content);
           If G_st <> 0 Then
               begin
                 showmessage('写卡时出错,请检查后使用!');
                 Write_card := False;
                 exit;
               end;        Write_card:= True;
          //
          end;
       {4}//对卡进行读操作
        function Read_Card():string;
          var
          Cent:array[0..383] of char;
          tent:array[0..383] of char;
          I,j:integer;
          DD:string;
         begin
         G_st:= srd_eeprom(G_icdev, 0, 383, Cent);
              If G_st < 0 Then
                 begin
                   showmessage('读卡时出错,请检查后使用!');
                    Exit;
                end;
        For i := 0 To 383 do
         begin
            If i > 13 Then
              begin
                 for j:=0 to 12 do
                   begin
                       dd:=dd+cent[j];
                   end;
                    Read_Card:= dd;
                    Exit;
              end;
          end;
         end;
     
          //   {5} //写卡时内容组织
    function Content(aa:string):string;
         begin
          //
          end;
       {6}//卡片比效函数
         function Card_Compare():boolean;
          begin
          //
          end;
       {7}//
         function check_card():boolean;
           var
             Status:integer;
             aa:array[0..2]of char;
         begin
              status:=0;
              G_st:=get_status(G_icdev, @Status);          If  Status  =0 Then
                 begin
                   //showmessage('请插入卡后使用!');
                   check_Card:=False;
                  // G_st := ic_exit(G_icdev);
                    Exit;
                  End;              check_Card := True;
           end;end.
      

  12.   

    代码部分:
    unit WriteIC4428_RemovingEndNum;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Buttons;type
      TPCH_Write_IC_Card4428 = class(TForm)
        rb_IsWriteMainCard: TRadioButton;
        lst_ReadWriteInfo: TListBox;
        rb_IsWriteAttachCard: TRadioButton;
        grp__1: TGroupBox;
        grp__2: TGroupBox;
        lbl_1: TLabel;
        lbl_2: TLabel;
        lbl_3: TLabel;
        grp__3: TGroupBox;
        lbl_4: TLabel;
        edt_CardPWD: TEdit;
        lbl_5: TLabel;
        edt_WritePosition_Byte: TEdit;
        lbl_7: TLabel;
        btn_OpenInterface: TBitBtn;
        btn_VerifyCardPwd: TBitBtn;
        btn_ReadCard: TBitBtn;
        btn_ClearListBoxRec: TBitBtn;
        btn_Exit: TBitBtn;
        btn_WriteCard: TBitBtn;
        edt_CardMainNo: TEdit;
        edt_CardFirstNo: TEdit;
        edt_AttachCardEndNo: TEdit;
        grp__4: TGroupBox;
        edt_WriteCardNum: TEdit;
        lbl_6: TLabel;
        btn_ChangeCardPWD: TBitBtn;
        btn_ClosePort: TBitBtn;
        procedure btn_OpenInterfaceClick(Sender: TObject);
        procedure btn_VerifyCardPwdClick(Sender: TObject);
        procedure btn_WriteCardClick(Sender: TObject);
        procedure btn_ExitClick(Sender: TObject);
        procedure btn_ReadCardClick(Sender: TObject);
        procedure btn_ChangeCardPWDClick(Sender: TObject);
        procedure btn_ClearListBoxRecClick(Sender: TObject);
        procedure btn_ClosePortClick(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure edt_CardMainNoChange(Sender: TObject);
        procedure edt_AttachCardEndNoChange(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    var
      PCH_Write_IC_Card4428: TPCH_Write_IC_Card4428;  ClickNum:Integer;
      MainCardNum:string[10];
      RW_MainCardNum:string[20];
      RW2_MainCardNum:string[44];
      RW2_AttachCardNum:string[48];
    // ----------------------------------------------
      icdev:longint;
      st:smallint;
      outbuff:pchar; //输出缓冲区_主卡
      inbuff:string; //输入缓冲区implementation{$R *.dfm}uses drv_unit_D6;// 打开串口
    procedure TPCH_Write_IC_Card4428.btn_OpenInterfaceClick(Sender: TObject);
    begin
    //  ClickNum:=0;
      icdev := IC_InitComm(100);
    If icdev < 0 Then
       begin
       lst_ReadWriteInfo.Items.Add('打开端口出错!请检查端口是否被占用或设备是否已连接!');
         exit;
      end
      else
    begin
          lst_ReadWriteInfo.Items.Add('打开端口成功!');
      PCH_Write_IC_Card4428.btn_VerifyCardPwd.Enabled:=True;
    PCH_Write_IC_Card4428.btn_WriteCard.Enabled:=True;
    PCH_Write_IC_Card4428.btn_ReadCard.Enabled:=True;
    PCH_Write_IC_Card4428.btn_ChangeCardPWD.Enabled:=True;
          PCH_Write_IC_Card4428.btn_ClosePort.Enabled:=True;
        end; st := IC_Status(icdev);
    If st <0 Then begin
    lst_ReadWriteInfo.Items.Add('读写器存在错误!');
    exit;
    end;
    lst_ReadWriteInfo.Items.Add('读写器状态正常!'); If st >0 Then
        If st = 1 then
          begin
            Windows.Beep(300,600);
      lst_ReadWriteInfo.Items.Add('>>>>>>>>>>>没有检测到卡,请重新插卡!');
            st := IC_ExitComm(icdev);     //关闭串口
        icdev:=0;
          end
    else
    lst_ReadWriteInfo.Items.Add('检测到卡!'); st := IC_InitType(icdev, 4);       //给卡型号
    If st = 0 Then
       begin
    lst_ReadWriteInfo.Items.Add('卡型检测成功!');
    Exit;
    End
      else
       lst_ReadWriteInfo.Items.Add('卡型检测失败!');
    end;//校验密码
    procedure TPCH_Write_IC_Card4428.btn_VerifyCardPwdClick(Sender: TObject);
    begin
    st := IC_ReadCount_SLE4428(icdev);
    If st < 0 Then begin
    lst_ReadWriteInfo.Items.Add('读芯片SLE4428、4442出错!');
    Exit;
    End; lst_ReadWriteInfo.Items.Add('读芯片SLE4428、4442成功!');
      lst_ReadWriteInfo.Items.Add('错误记数器为'+inttostr(st));  inbuff:=string(edt_CardPWD.Text);                //核对密码
      st := IC_CheckPass_4428hex(icdev,pchar(inbuff));
      If st <> 0 Then begin
    lst_ReadWriteInfo.Items.Add('密码校验失败!');
    Exit;
      End;
      lst_ReadWriteInfo.Items.Add('密码校验成功!');
    end;
      

  13.   


    // 写卡
    procedure TPCH_Write_IC_Card4428.btn_WriteCardClick(Sender: TObject);
    var CardMain_temp:string[6];
        CardMainNo:string[6];
        CardFirstNo:string[4];
        CardEndNo:string[2];
        M_WriteCardNum:string[22];
        A_WriteCardNum:string[24];
    begin
      CardMain_temp:=IntToStr(StrToInt(edt_CardMainNo.Text)+ClickNum);
      if Length(CardMain_temp)=1 then
        CardMainNo:='00000'+string(CardMain_temp)
      else
       begin
          if Length(CardMain_temp)=2 then
           CardMainNo:='0000'+string(CardMain_temp)
          else
           begin
             if Length(CardMain_temp)=3 then
               CardMainNo:='000'+string(CardMain_temp)
              else
              begin
                  if Length(CardMain_temp)=4 then
          CardMainNo:='00'+string(CardMain_temp)
                  else
                    begin
                      if Length(CardMain_temp)=5 then
        CardMainNo:='0'+string(CardMain_temp)
                    else
                      CardMainNo:=string(CardMain_temp);
                     end;
                end;
            end;
        end;   CardFirstNo:=Copy(string(edt_CardFirstNo.Text),1,2)+copy(edt_CardFirstNo.Text,3,2);
        CardEndNo:=Copy(string(edt_AttachCardEndNo.Text),1,1)+copy(edt_AttachCardEndNo.Text,2,1);  MainCardNum:=string(CardFirstNo)+string(CardMainNo);
      M_WriteCardNum:=Copy(MainCardNum,1,2)+'YN'+copy(MainCardNum,5,10)+'  '+
                        Copy(MainCardNum,1,2)+'YN'+copy(MainCardNum,5,10);
      A_WriteCardNum:=string(M_WriteCardNum)+string(CardEndNo);  inbuff:=string(edt_CardPWD.Text);                //核对密码
      st := IC_CheckPass_4428hex(icdev,pchar(inbuff));
      If st <> 0 Then begin
    lst_ReadWriteInfo.Items.Add('密码校验失败!');
    Exit;
      End;
      lst_ReadWriteInfo.Items.Add('密码校验成功!');  if rb_IsWriteMainCard.Checked then
       begin      RW_MainCardNum:='3'+copy(MainCardNum,1,1)+'3'+copy(MainCardNum,2,1)+'59'+'4e'+'3'
         +copy(MainCardNum,5,1)+'3'+copy(MainCardNum,6,1)+'3'
                         +copy(MainCardNum,7,1)+'3'+copy(MainCardNum,8,1)+'3'+copy(MainCardNum,9,1)+'3'
                         +copy(MainCardNum,10,1);      RW2_MainCardNum:=string(RW_MainCardNum)+'20'+'20'+string(RW_MainCardNum);
         inbuff:=RW2_MainCardNum;     st := IC_Write_hex(icdev, StrToInt(edt_WritePosition_Byte.Text),22,pchar(inbuff));  //写主卡数据
          st := IC_Status(icdev);
          If st <> 0 Then begin
            Windows.Beep(300,600);
            ShowMessage('写卡失败,请确认是否正确插入卡,或重新插卡!');
            lst_ReadWriteInfo.Items.Add('>>>>>>>>>>>>>>>>>>>>写入失败的主卡号为:'+string(M_WriteCardNum));
          Exit;
      End;
          lst_ReadWriteInfo.Items.Add('成功写入主卡号:'+string(M_WriteCardNum));
          ClickNum:=ClickNum+1;
          edt_WriteCardNum.Text:=string(M_WriteCardNum);
        end
      else
       begin
         if rb_IsWriteAttachCard.Checked then
       begin
              RW_MainCardNum:='3'+copy(MainCardNum,1,1)+'3'+copy(MainCardNum,2,1)+'59'+'4e'+'3'
         +copy(MainCardNum,5,1)+'3'+copy(MainCardNum,6,1)+'3'
                         +copy(MainCardNum,7,1)+'3'+copy(MainCardNum,8,1)+'3'+copy(MainCardNum,9,1)+'3'
                         +copy(MainCardNum,10,1);
                          
              RW2_MainCardNum:=string(RW_MainCardNum)+'20'+'20'+string(RW_MainCardNum);          RW2_AttachCardNum:=RW2_MainCardNum+'3'+copy(CardEndNo,1,1)+'3'+copy(CardEndNo,2,1);;
           inbuff:=RW2_AttachCardNum;
           st := IC_Write_hex(icdev, StrToInt(edt_WritePosition_Byte.Text),24,pchar(inbuff));  // 写副卡数据
           If st <> 0 Then
           begin
               Windows.Beep(300,600);
             ShowMessage('写卡失败,请确认是否正确插入卡,或重新插卡!');
             lst_ReadWriteInfo.Items.Add('>>>>>>>>>>>>>>>>>写入失败的副卡号为:'+string(A_WriteCardNum));
          Exit;
             end;
           lst_ReadWriteInfo.Items.Add('成功写入副卡号:'+string(A_WriteCardNum));
           ClickNum:=ClickNum+1;
           edt_WriteCardNum.Text:=string(A_WriteCardNum);
         End;
          
       end;
    end;
    // 读卡号
    procedure TPCH_Write_IC_Card4428.btn_ReadCardClick(Sender: TObject);
    var READ_MainCardNum:string[28];
        READ_AttachCardNum:string[32];
    begin
      if rb_IsWriteMainCard.Checked then
    begin
         getmem(outbuff,60);
         st := IC_Read_hex(icdev, StrToInt(edt_WritePosition_Byte.Text),22,outbuff);  //读主卡卡号
          READ_MainCardNum:=copy(outbuff,2,1)+copy(outbuff,4,1)+copy(outbuff,5,2)+copy(outbuff,7,2)
                            +copy(outbuff,10,1)+copy(outbuff,12,1)+copy(outbuff,14,1)+copy(outbuff,16,1)
                            +copy(outbuff,18,1)+copy(outbuff,20,1)+'  '+copy(outbuff,26,1)+copy(outbuff,26,1)
                            +copy(outbuff,29,2)+copy(outbuff,31,2)+copy(outbuff,34,1)+copy(outbuff,36,1)
                            +copy(outbuff,38,1)+copy(outbuff,40,1)+copy(outbuff,42,1)+copy(outbuff,44,1);
          If st <> 0 Then
           begin
             Windows.Beep(300,600);
              ShowMessage('读主卡卡号失败,请确认是否正确插入卡,或重新插卡!');
              lst_ReadWriteInfo.Items.Add('读主卡卡号失败!');
              freemem(outbuff);
              Exit;
            end
          else
           begin
             lst_ReadWriteInfo.Items.Add('读主卡成功!');
             outbuff[44]:=chr(0);
             lst_ReadWriteInfo.Items.Add('>>>>>>>>>>>>数据为:'+READ_MainCardNum);
    end;
        end;    if rb_IsWriteAttachCard.Checked then
       begin
         getmem(outbuff,60);
         st := IC_Read_hex(icdev, StrToInt(edt_WritePosition_Byte.Text),24,outbuff);  //读副卡卡号
            READ_AttachCardNum:=copy(outbuff,2,1)+copy(outbuff,4,1)+copy(outbuff,5,2)+copy(outbuff,7,2)
                            +copy(outbuff,10,1)+copy(outbuff,12,1)+copy(outbuff,14,1)+copy(outbuff,16,1)
                            +copy(outbuff,18,1)+copy(outbuff,20,1)+'  '+copy(outbuff,26,1)+copy(outbuff,26,1)
                            +copy(outbuff,29,2)+copy(outbuff,31,2)+copy(outbuff,34,1)+copy(outbuff,36,1)
                            +copy(outbuff,38,1)+copy(outbuff,40,1)+copy(outbuff,42,1)+copy(outbuff,44,1)
                            +copy(outbuff,46,1)+copy(outbuff,48,1);
           If st <> 0 Then
           begin
               Windows.Beep(300,600);
               ShowMessage('读副卡卡号失败,请确认是否正确插入卡,或重新插卡!');
             lst_ReadWriteInfo.Items.Add('读副卡卡号失败!');
               freemem(outbuff);
               Exit;
             end
           else
           begin
             lst_ReadWriteInfo.Items.Add('读副卡成功!');
             outbuff[48]:=chr(0);
             lst_ReadWriteInfo.Items.Add('>>>>>>>>>>>>数据为:'+READ_AttachCardNum);
    end;
          end;
    end;//修改密码
    procedure TPCH_Write_IC_Card4428.btn_ChangeCardPWDClick(Sender: TObject);
    begin
    inbuff:=string(edt_CardPWD.Text);
     st := IC_ChangePass_4428hex(icdev,pchar(inbuff));     //修改密码
     If st <> 0 Then begin
         lst_ReadWriteInfo.Items.Add('修改密码失败!');
         Exit;
     End;
     lst_ReadWriteInfo.Items.Add('修改密码成功!');
     lst_ReadWriteInfo.Items.Add('卡密码改为'+string(edt_CardPWD.Text));
     lst_ReadWriteInfo.Items.Add('读写设备测试通过!');
    end;
    // 清除记录
    procedure TPCH_Write_IC_Card4428.btn_ClearListBoxRecClick(Sender: TObject);
    begin
      lst_ReadWriteInfo.Items.Clear;
    end;
    // 仅关闭串口
    procedure TPCH_Write_IC_Card4428.btn_ClosePortClick(Sender: TObject);
    begin
    if icdev>0 then
       begin
          st := IC_ExitComm(icdev);     //关闭串口
      icdev:=0;
          PCH_Write_IC_Card4428.btn_VerifyCardPwd.Enabled:=False;
    PCH_Write_IC_Card4428.btn_WriteCard.Enabled:=False;
    PCH_Write_IC_Card4428.btn_ReadCard.Enabled:=False;
    PCH_Write_IC_Card4428.btn_ChangeCardPWD.Enabled:=False;
          PCH_Write_IC_Card4428.btn_ClosePort.Enabled:=False;
          lst_ReadWriteInfo.Items.Add('关闭串口成功!');
      end;
    end;//退出,关闭串口
    procedure TPCH_Write_IC_Card4428.btn_ExitClick(Sender: TObject);
    begin
      close;
       if icdev>0 then
       begin
      st := IC_ExitComm(icdev);     //关闭串口
      icdev:=0;
      end;
      freemem(outbuff);
    end;procedure TPCH_Write_IC_Card4428.FormClose(Sender: TObject;
      var Action: TCloseAction);
    begin
    if icdev>0 then
       begin
      st := IC_ExitComm(icdev);     //关闭串口
      icdev:=0;
      end;
      freemem(outbuff);
      Action:=caFree;
    end;procedure TPCH_Write_IC_Card4428.edt_CardMainNoChange(Sender: TObject);
    begin
      ClickNum:=0;
    end;procedure TPCH_Write_IC_Card4428.edt_AttachCardEndNoChange(
      Sender: TObject);
    begin
      ClickNum:=0;
    end;end.
      

  14.   

    我也是第一次写IC卡的,本着交流的目的,全部源代码贴出,给您做参考,在我设备上,D7环境下全部调试通过。所有功能实现了但程序能其实可以做的更精简,有些可以写成函数精炼代码,时间紧程序逻辑上就没下台多功夫,还请同行指正!
      

  15.   

    感激各位的回复,尤其是FALLENCITY,您的程序我已收录,因为是初次接触IC卡的编程,只能先从基础开始,你的程序容以后仔细研究.再次感谢!先将几次的初步实验中遇到问题讨教各位大佬(明华USB接触式读卡器,几张4442卡).从明华随机DEMO中测得IC卡为未知型,通过供应商知是4442卡,再将随机的4442卡的程序检测确认.
    但密码检验通不过,打开源程序,发现程序中设的密码值为'B62307',IC卡出厂的密码为'FFFFFF',再通过DEMO程序将IC卡密码改为'B72307',到程序中测试通过(中间好几次折腾),但现在出现读操作通过,写操作出错,并且提示'rsct ok count=0',打开源程序,是通过下列语句所得
    counter:=0;
    st:=rsct_4442(icdev,@counter);
    这是否意味卡已锁死?
      

  16.   

    另外,再通过DEMO设卡的密码为'FFFFFF',在程序上测试(程序上设密码值为'B62307'),但却都通过,提示为'
    CSC OK',为何?请教大佬
      

  17.   

    一般IC卡修改密码过于频繁,或密码不对的情况下强行写卡,错误次数超过8次,卡就被锁死了,基本可以定位这张卡是费卡了!换一张再测试吧。先用DEMO修改密码为FFFFFF再进行程序测试吧。USB口的卡,注意它的卡状态检测函数,他同时起上电作用的。看一下开发手册对照一下。我的读卡器函数是:st := IC_Status(icdev);每进行读卡写卡修改密码前都强行上电,然后操作结束再下电,用的时候再上电,这样才会减少程序错误的。
      

  18.   

    串口通信,建议LZ向厂家所要dll