当前位置: 代码迷 >> Android >> Android NFC近场通讯03-读写MifareClassic卡
  详细解决方案

Android NFC近场通讯03-读写MifareClassic卡

热度:19   发布时间:2016-04-28 04:29:46.0
Android NFC近场通信03----读写MifareClassic卡

                                       Android NFC近场通信02----读写MifareClassic卡

一.MifareClassic卡 相关

一般来说,给予MifareClassic的射频卡,一般内存大小有3种:

1K: 16个分区(sector),每个分区4个块(block),每个块(block) 16个byte数据

2K: 32个分区,每个分区4个块(block),每个块(block) 16个byte数据

4K:64个分区,每个分区4个块(block),每个块(block) 16个byte数据

对于所有基于MifareClassic的卡来说,每个区最后一个块叫Trailer,16个byte, 主要来存放读写该区的key,可以有A,B两个KEY,每个key长6byte,默认的key一般是FF 或 0,最后一个块的内存结构如下:

Block 0  Data 16bytes
Block 1  Data 16 bytes
Block 2  Data 16 bytes
Block 3  Trailer 16 bytes
Trailer:
Key A: 6 bytes
Access Conditions: 4 bytes
Key B: 6 bytes

M1卡分为16个扇区,每个扇区由4块(块0、块1、块2、块3)组成,(我们也将16个扇区的64个块按绝对地址编号为0~63,)存贮结构如右表所示


0

0

数据块

0

1

数据块

1

2

数据块

2

3

密码A  存取控制    密码B

数据块

3

1

0

数据块

4

1

数据块

5

2

数据块

6

3

密码A  存取控制    密码B

数据块

7


 

15

0

数据块

60

1

数据块

61

2

数据块

62

3

密码A  存取控制    密码B

数据块

63


0扇区的0(即绝对地址0块),它用于存放厂商代码,已经固化,不可更改。

每个扇区的块0、块1、块2为数据块,可用于存贮数据。

每个扇区的块3为控制块,包括了密码A、存取控制、密码B。具体结构如下:

A1A2 A3 A4 A5               FF 07 8069               B0 B1 B2 B3 B4 B5

密码A6字节)          存取控制(4字节)          密码B6字节)  

每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制;

存取控制为4个字节,共32位,扇区中的每个块(包括数据块和控制块)的存取条件是由密码和存取控制共同决定的。
工作原理:

读写器向M1卡发一组固定频率的电磁波,卡片内有一个LC串联谐振电路,其频率与讯写器发射的频率相同,在电磁波的激励下,LC谐振电路产生共振,从而使电容内有了电荷,在这个电容的另一端,接有一个单向导通的电子泵,将电容内的电荷送到另一个电容内储存,当所积累的电荷达到2V时,此电容可做为电源为其它电路提供工作电压,将卡内数据发射出去或接取读写器的数据。

二.读取数据 

//tag 就是在上一篇中onNewIntent中获取的tagMifareClassic mc = MifareClassic.get(tag);        short startAddress = 0;        short endAddress = 5;        byte[] data = new byte[(endAddress - startAddress + 1 ) * ByteCountPerBlock];                try {                        mc.connect();for (short i = startAddress; i <= endAddress; i++ ,time++) {                boolean auth = false;                short sectorAddress = getSectorAddress(i);                auth = mc.authenticateSectorWithKeyA(sectorAddress, MifareClassic.KEY_DEFAULT);                if (auth){                                        //the last block of the sector is used for KeyA and KeyB cannot be overwritted                    short readAddress = (short)(sectorAddress == 0 ? i : i + sectorAddress);                                        byte[] response = mc.readBlock(readAddress);                    CombineByteArray(data, response, time * ByteCountPerBlock);                }                else{                    throw new NfcException(NfcErrorCode.TemporaryError,                            "Authorization Error.");                }            }            mc.close();                    }        catch (NfcException ne) {            throw ne;        }        catch (IOException e) {            throw new NfcException(NfcErrorCode.TemporaryError,                    "Get response, what it is not successfully.", e);        }        finally        {            try {                mc.close();            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }
三.写数据 

//tag 就是在上一篇中onNewIntent中获取的tagMifareClassic mc = MifareClassic.get(tag);            try {                mc.connect();                boolean auth = false;                short sectorAddress = 0                auth = mc.authenticateSectorWithKeyA(sectorAddress,                        MifareClassic.KEY_DEFAULT);                if (auth) {                    //the last block of the sector is used for KeyA and KeyB cannot be overwritted                                        mc.writeBlock(readAddress, dataTemp);                    mc.close();                }             }finally            {                try {                    mc.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        }

附:NFC 论坛 http://www.nfcchina.org/forum.php

  相关解决方案