FM1702SL和mifare IC卡
/*因FM1702SL和mifare IC卡的手册内容过多,所以这里只是记录我自己在实际编程过程中遇到的感到困惑的地方和拨开云雾的一些见解*/ (操蛋的手册 在网上找到任意一篇 免费 的调试这两个东西的文章都会在开头吐槽一番,我当然也不会落伍啊)
(注意带括号的地方,都是我遇到的一些坑,或值得注意的地方)
FM1702SL与主控板之间的通信可以采用SPI方式,FM1702的FIFO用于保存微处理器和FM1702之间通信的数据(之前一直不知道,spi的数据给的是FIFO还是EEPROM,并且是通过FIFODATA寄存器操作)与天线之间的联系通过TX1,TX2 ,RX引脚传输到FIFO中
FM1702SL中涉及到地址操作:EEPROM(512B) ,FIFO(64B), REG(64个)
FM1702的内部寄存器按功能不同分成8组,每组为一页,包含8个寄存器 ,每个寄存器有一个地址,并且相应位的读写权限时不同的
其中涉及的函数SPI_TRANS(uchar rw,uchar addr,uchar data) //(注意此处data只是标识符,在实际编程中不可以这样写,为关键词)
先发送地址,一般是0x02即FIFODATA寄存器的地址需要对最高位进行读写标识的处理,为1是读,为0是写 addr|=0x80;即为读操作 addr&=0x7f;几位写操作,然后发送数据
/*使用FM1702SL前先初始化SPI接口*/ 在初始化SPI接口时,看别人写的程序,有一个地方一开始搞不懂,就是传入的地址 addr 总是先进行 addr<<=1; 如果这样是必须的,那么原来addr的bit7,bit6一定是0,才不会破坏原本的数据,也就是说addr就没有大于0x00ffffff(即63)的(最后一位bit0必须是0,bit7是读写模式位)所以我猜测,addr<<=1,是让bit0=0;
SPI环形总线结构,在sck控制下,两个双向移位寄存器进行数据交换,这里划重点(数据交换) 上升沿 从机采样(MOSI) 下降沿 从机输出 (MISO) 所谓交换,就是以数据换数据(可以用无用数据换取有用数据)


从第二张图可以看到在sclk 0-1 的时候 mosi miso 上已经有了master MSB , slaver MSB 并且,slaver 已经接收到MOSI的值,等到sclk1-0时,master接收到MISO的值
FM1702SL的行为由一个内部状态机决定,该状态机可执行一组专门的指令集。将某条指令代码写入指令寄存器可启动一个相应的命令的执行。某些指令执行需携带参数和(或)数据,这些参数或数据主要通过FIFO进行交换。
这个是我看到的一篇大致介绍读卡过程的文章,对于完全不知道怎么下手的我来说有启发性 : https://blog.csdn.net/lindabell/article/details/8481607
1.配置FM1702芯片,包括复位等
2.寻卡
3.读取卡号 卡号虽然唯一,但根据读卡器译码格式不同,输出的卡号会有几种不同的格式
4.选卡
5.密码认证
6.读写卡
M1卡容量8K ,分为16个扇区(512B)每个扇区4块,每块16B,以块为存取单位(按绝对地址编号为0-63)每个扇区 块0-2为数据块,块3为控制块。每个扇区有独立的一组密码和存取控制,每张卡有唯一的序列号(32bit),读写距离《10Cm
M1射频卡与读写器的通讯

1.复位应答(Answer to request) M1射频卡的通信协议和通信波特率是定义好的,当有卡片进入读写器的操作范围时 ,读写器以特定的协议与他通讯,从而确定该卡是否为M1射频卡,即验证卡的型号
返回卡的型号,如mifare 8k std card : 0x04,在别的文章里也有说是UID的长度,即0x04为32bit的长度

也就是说在上图中的命令格式帧中,proprietary coding is 0100 UID size is 00 bit frame anticollision is 00000 当回送ATQA时,高位先发送
2.防冲突机制(Anticollision loop) 当有多张卡进入读写器的操作范围时,防冲突机制会从中选择一张卡进行操作,未选中的处于空闲模式等待下一次选卡,该过程返回被选卡的序列号
正常情况下,读写器只能在某一时刻的磁场中对一张卡进行读写操作,当多张卡(也可以时 多种卡 (卡号长度不同等)级联CT为88)同时进入读写器的射频磁场时,读写器需要 选出 唯一的一张卡进行读写,这就是防冲突(这是非接触式卡片特有的问题)这里只介绍符合ISO14443A的mifare中使用的 面向比特的防冲突机制 。其原理是基于卡片有一个全球唯一的序列号(32bit)。卡号的每一位都是0/1 的组合,由于是全球唯一的卡号,所以任意两张卡的序列号至少有一位是不同的。当多张卡同时存在于磁场中,在读写器发送卡呼叫命令后,这些卡同时应答。然后读写器发送防冲突命令,这些卡收到命令后发送自己的序列号。假设设置的冲突位是 1 ,即让当这些卡回送的序列号某一位开始出现冲突(某一位有的卡是0,有的卡是1)时的该位为1的卡继续发送,经过多次防冲突循环,就只剩下一张卡。(实际上是通过曼彻斯特码检测冲突的)(这种卡有一个缺点,由于全球唯一,长度固定,所以可发行的数量也就有限,即2^32张卡)Type-A型防冲突机制,面向位的防冲突

PCD为选择的防冲突类型和串联级别分配了带有编码的SEL,SEL第一次赋值‘93’,表示防冲突级别一。(还有95级别2 97级别3)。PCD分配了带有值为‘20’的NVB(即SEL+NVB为2byte,'20'中的2是指frame length/8 0是指frame length%8)
http://blog.sina.com.cn/s/blog_9ed067ad0100z47e.html 这里会有一个介绍SELECT 和 ANTI区别的内容
(1)PCD设置SEL编码和选择碰撞级别。(当SEL编码为0x93时,表示碰撞级别一;当SEL编码为0x95时,表示碰撞级别二;当SEL编码为0x97时,表示碰撞级别三)。
(2)PCD设置NVB的初始值为0x20。表示传输的字节(SEL和NVB)数为2*8 / 8 = 2,传输的比特位为 2*8 % 8 = 0;
(3)PCD发送SELECT命令,传输SEL和NVB。
(4)所有在RF中的PICC发送ATQA进行响应REQA。
(5)假定所有的PICC都有自己独特的UID序列。如果只有一张PICC进行响应,那么ATQA中的碰撞比特位为0;否则进行第(6)步到第(10)步。
(6)PCD根据ATQA识别PICC的UID中碰撞的位置。
(7)根据传输的字节数和比特位数重新设置NVB的值,PCD需要设置碰撞响应规则是以比特位1进行,还是以比特位0进行。
(8)PCD发送SELECT命令,传输重新设置好的SEL和NVB。
(9)只有PICC的UID等于PCD发送SELECT命令的UID时,表示防碰撞过程成功。
(10)如果还没选出PICC中的UID,即还有多张卡响应,那么重复第(6)步到第9步,进行更高级别的碰撞。
(11)如果更高级别的碰撞发生了,PCD应将NVB设置成0x70,表示传输了7字节。7 = 1 + 1 + 5(1个字节SEL,1个字节NVB和5个字节【可能是1个字节的CT(0x88)加上3个字节的UID,再加上一个字节的BCC(前面四个传输字节异或结果);也可能是四个字节的UID加上一个字节的BCC(前面四个字节UID异或的结果)】)。 BCC即异或校验
(12)PCD发送SELECT命令,传输1个字节SEL,1个字节NVB和5个字节UID。
(13)PICC响应SAK,PCD匹配5个字节的UID。 4BYTE UID+1BYTE BCC 实际上,4byteUID的数据格式有不同的表现形式
(14)如果UID是完整的,PICC传输的SAK清除碰撞级别比特位和从准备态(READY State)切换到激活态(ACTIVE State)或者从类准备态(READY* State)切换到类激活态(ACTIVE* State)。
(15)PCD会检查SAK去决定是否进行更高层次的防碰撞过程,如果需要则会提升碰撞级别。


3.选择卡片(select tag) 选择被选中卡的序列号,并返回卡的容量代码 (QAQ,怪我自己脑残,传参不对,返回的不是一个字节的容量代码)
4. 3次相互确认(3 pass authentication) 选中要处理的卡片之后,读写器就确定要访问的扇区号,并对 该扇区密码进行验证,在三次相互认证之后可以通过加密流进行通信。(选择一个扇区就需要对这个扇区进行密码校验)
为了能够成功进行卡的认证以及后续对存储与EEPROM中的数据进行操作,FM1702SL必须能够获得正确的密钥。当一张卡按照ISO14443A协议被选中后,用户可以按照标准协议继续操作。这种情况下,必须执行卡片认证,即Authent1 和Authent2指令,成功认证后与卡的通讯处于加密状态。
在认证过程中,FM1702从内部的 密钥缓冲器 中读取密钥,不需要指明密钥存储地址,所以必须在认证开始之前保证在密钥缓冲器中已有密钥。密钥可以通过两个方式加载:用LoadKeyE2指令从EEPROM中加载;直接由外部处理器通过LoadKey指令从FIFO中加载。
操作三重认证指令:
(在做writeE2 和readE2时,注意禁止读取0x80-0x1ff 的密码存储区,禁止写入到0x00区。当选择的地址超过0x1ff时则把所选地址和0x1ff相与后作为实际操作地址)
1.通过LoadKeyE2/LoadKey加载密钥到内部密钥缓冲器 (使用LoadKey 必须是先把 12 字节的密钥传递到FIFO中,并且密钥的格式需满足规定)
2.启动Authent1指令,结束以后,检查错误标志
3.Authent1成功后,启动Authent2指令,结束后,检查错误标志以及Crypto1On标志来判断执行结果
对数据块的操作 block0-2 is data block .The data blocks can be configured by the access bits as 1: read/write blocks 2: value blocks(Value blocks can be used for e.g. electronic purse applications, where additional commands like increment and decrement for direct control of the stored value are provided.)
A value block can only be generated through a write operation in the value block format:
读(read) 读一个块 需要地址
写(write) 写一个块 需要地址,两次响应
加(increment) 对数值块进行加值
减(decrement) 对数值块进行减值
存储(restroe) 将块中内容保存到数据寄存器中
传输(transfer) 将数据寄存器中的内容写入到块中
中止(halt) 将卡置于暂停工作状态
(注意在往FM1702的EEPROM中写操作的时候,不要随便写寄存器值的区域,说实话,为什么不把这个区域变成只读的,,地址超出范围还与上0xff,,没注意就把寄存器初始值给改了,,怎么调试都是行不通的,很难想到这里,得亏我把几个可能的误操作想了一小下,重新写入初始值,才可以)
本文来自博客园,作者:pie_thn,转载请注明原文链接:https://www.cnblogs.com/pie-o/p/13081698.html

浙公网安备 33010602011771号