13.56MHz读写卡模块通信接口及选型指南

周立功单片机 ? 2018-01-25 09:09 ? 次阅读

心博天下娱乐平台 www.syycw.cn 周立功教授新书《面向AMetal框架与接口的编程(上)》,对AMetal框架进行了详细介绍,通过阅读这本书,你可以学到高度复用的软件设计原则和面向接口编程的开发思想,聚焦自己的“核心域”,改变自己的编程思维,实现企业和个人的共同进步。

第六章为重用外设驱动代码,本文内容为6.4 读写卡模块。

6.4 读写卡模块

>>> 6.4.1 基本功能

ZLG600A 是ZLG 提供的符合14443 标准的13.56MHz 读写卡模块,支持Plus CPU、Mifare DesfireCPU 卡、Mifare 1 S50/S70、Mifare 0 ultralight、Mifare Pro 卡,还支持ISO7816 协议读写接触式IC 卡。可以搭载两个天线满足不同位置的多卡读写要求,连接从机数多达127 个,支持I2C、UART、RS-232C、RS-485 多种接口。具备主动检测卡进入功能,当检测到卡时,则产生中断且通过串口、I2C 输出数据。

ZLG600A 系列读写卡模块选型指南详见表6.18,电源电压为5V,平均电流为77mA,TypeA、TypeB 和PLUS CPU卡读卡距离分别为7.5cm、4cm 和5cm。

表6.18 选型指南表

由于RS-232C 和RS-485 与UART通信方式完全相同,仅在硬件上增加了一些转换电路,因此后面不再特别说明。在这里仅介绍I2C 和UART 两种通信方式,其引脚含义详见表6.19。

表6.19 通信接口定义

注:方形焊盘为第1 管脚,3.3V 模块J1-5 接3.3V 电源,5V 模块J1-5 接5V 电源。

当使用UART 通信时,只需要连接J1 中的电源引脚和TXD、RXD 引脚,其它引脚悬空,将LPC824 的USART0、USART1 或USART2 与ZLG600A 相连。当使用I2C 通信时,需要连接J1 中的电源引脚和SCL、SDA 引脚。由于I2C 从机不能主动向I2C 主机发送数据,因此需要使用INT 引脚,用于从机通知主机处理事务。其它未使用的引脚通过10K 的上拉电阻与高电平相连,将LPC824 的I2C0、I2C1、I2C2 或I2C3 与ZLG600A 相连。注:SCL 和SDA 模块内部都有上拉电阻,使用I2C 通信时无需再外接上拉电阻。

>>> 6.4.2 初始化

AMetal 已经提供了ZLG600A 的驱动函数,在使用其它各功能函数前必须先完成初始化,其初始化函数详见表6.20。

表6.20 ZLG600A 初始化接口函数

初始化ZLG600A 意在获取ZLG600A 的实例句柄(handle),虽然初始化函数不同,但返回值均为ZLG600A 的实例句柄,该实例句柄将作为其它功能接口函数handle 的实参。因此,无论选择I2C 或UART 通信方式,只要基于实例句柄编程,则应用程序与具体的通信方式无关。即便底层通信方式改变了,仅需在获取实例句柄时换一个初始化函数,而应用程序“一行代码”都不用修改。

1. UART 初始化

使用UART 时,其初始化函数原型为:

  • p_dev 为指向am_zlg600_uart_dev_t 类型实例的指针;

  • p_devinfo 为指向am_zlg600_uart_devinfo_t 类型实例信息的指针。

(1)实例

定义am_zlg600_uart_dev_t 类型(am_zlg600.h)实例如下:

其中,g_zlg600_uart_dev 为用户自定义的实例,其地址作为p_dev 的实参传递。

(2)实例信息

实例信息主要描述了ZLG600A 使用UART 通信时的相关信息,包括UART 缓冲区信息、波特率等信息。其类型am_zlg600_uart_devinfo_t 定义(am_zlg600.h)如下:

实例信息主要包含帧格式、ZLG600A 模式、波特率和缓冲区信息。

  • 帧格式

frame_fmt 表示初始化时ZLG600A 使用的帧格式,为了兼容早期产品,ZLG600A 支持新帧格式和旧帧格式,其对应的宏详见表6.21。在初始化完成后,可以通过相应的接口函数修改ZLG600A 使用的帧格式。但在初始化时,要知道ZLG600A 当前使用的帧格式,出厂默认使用的帧格式为旧帧格式,frame_fmt 的值设置为:AM_ZLG600_FRAME_FMT_OLD。

表6.21 帧格式对应的宏(am_zlg600.h)

注:若本次初始化完成后,通过后续相关功能接口函数更换使用的帧格式(如将旧帧格式更换为新帧格式),那么在系统下次启动调用ZLG600A 初始化函数时,需要确保frame_fmt成员的值为更新后的帧格式(如新帧格式)。

  • ZLG600A 模式

now_mode 为初始化时使用的模式,ZLG600A 支持3 种模式:自动侦测模式、I2C 模式、UART 模式。其对应的宏详见表6.22,出厂默认为自动侦测模式。

表6.22 模式对应的宏(am_zlg600.h)

注:由于在自动侦测模式下,为了使用UART 通信,需要Host 连续发送两次0x20(两次的时间间隔需要30us 以上),便于ZLG600A 检测有效波特率,将会使得每次初始化ZLG600A 的耗费时间较长。因此在本次初始化完成后,通过后续接口函数将模式固定为UART 模式。更新模式后,系统在下次启动调用ZLG600A 初始化函数时,需确保now_mode 成员的值为更新后的模式(如UART 模式)。

在自动侦测模式下,UART、I2C 接口均处于接收状态。若ZLG600A 从UART 通信线上检测到有效的波特率(需要Host 连续发送两次0x20,且两次的时间间隔在30us 以上,便于ZLG600 检测到有效波特率),则模块使用UART 通信方式;若模块从I2C 总线上接收到匹配的从机地址,则模块使用I2C 通信方式。只要其中一个接口先收到有效数据,模块将以此方式与主机通信,且关闭另外一种接口。

在UART 通信模式下,通信接口固定为UART,关闭I2C 接口,无需Host再连续发送两次0x20 检测ZLG600A 波特率。在I2C 通信模式下,关闭UART接口。在完成初始化后,可以通过相应的接口函数修改ZLG600A 使用的模式。但在初始化时,要知道ZLG600A 当前使用的模式,出厂默认使用的模式为自动侦测模式,now_mode 的值设置为:

AM_ZLG600_MODE_AUTO_CHECK。

  • 波特率

baudrate 为UART 波特率,支持波特率的宏定义详见表6.23。在自动侦测模式下,可以选择表中任一有效的波特率,ZLG600A 会自动检测使用的波特率。若处于UART 模式,波特率将为固定的值,该值为配置ZLG600A 是UART 模式时使用的波特率。

表6.23 支持的UART 波特率对应的宏(am_zlg600.h)

由于出厂默认模式为自动侦测模式,因此该值为任一有效的波特率,如定义波特率为115200,则该值为:AM_ZLG600_BAUDRATE_115200。

  • 缓冲区信息

当选择UART 方式通信时,发送和接收都需要一个保存数据的缓冲区,以提高数据处理的效率和确保接收数据不会因为正在处理事务而丢失。缓冲区的大小由用户根据实际情况指定,建议在64 字节以上,一般设置为128 字节。p_uart_rxbuf 和rxbuf_size 描述了接收缓冲区的首地址和大小,p_uart_txbuf 和txbuf_size 描述了发送缓冲区的首地址和大小。如果设置128 字节的缓冲区供发送和接收使用,其定义如下:

其中,g_zlg600_uart_txbuf[128]为用户自定义的数组空间供发送使用,充当发送缓冲区,其地址(数组名g_zlg600_uart_txbuf 或首元素地址& g_zlg600_uart_txbuf[0])作为实例信息中p_uart_txbuf 成员的值,数组大小(这里为128)作为实例信息中txbuf_size 成员的值。同理,g_zlg600_uart_rxbuf[128]充当接收缓冲区,其地址作为实例信息中p_uart_rxbuf 成员的值,数组大小作为实例信息中rxbuf_size 成员的值。基于此,实例信息定义如下:

(3)UART 句柄uart_handle

若选择LPC824 的USART1 与ZLG600A 通信,则可以通过LPC82x 的USART1 实例初始化函数am_lpc82x_usart1_inst_init()获得UART 句柄。即:

获得的UART 句柄即可直接作为uart_handle 的实参传递。

(4)实例句柄

ZLG600A 初始化函数am_zlg600_uart_init()的返回值即为ZLG600A 实例的句柄,该句柄将作为其它功能接口的第一个参数(handle)的实参。

其类型am_zlg600_handle_t(am_zlg600.h)定义如下:

若返回值为NULL,说明初始化失败;若返回值不为NULL,说明返回一个有效的handle。

基于模块化编程思想,将初始化相关的实例、实例信息等的定义存放到对应的配置文件中,通过头文件引出实例初始化函数接口,源文件和头文件的程序范例分别详见程序清单6.98 和程序清单6.99。

程序清单6.98 ZLG600A(串口通信)实例初始化函数实现(am_hwconf_zlg600.c)

程序清单6.99 ZLG600A(串口通信)实例初始化函数声明(am_hwconf_zlg600.h)

后续只需要使用无参数的实例初始化函数,即可获取ZLG600A 的实例句柄。即:

2. I2C 初始化

使用I2C 通信方式时,其初始化函数原型为:

  • p_dev 为指向am_zlg600_i2c_dev_t 类型实例的指针;

  • p_devinfo 为指向am_zlg600_i2c_devinfo_t 类型实例信息的指针。

(1)实例

定义am_zlg600_i2c_dev_t 类型(am_zlg600.h)实例如下:

其中,g_zlg600_i2c_dev 为用户自定义的实例,其地址作为p_dev 的实参传递。

(2)实例信息

实例信息主要描述了ZLG600A 使用I2C 通信时的相关信息,包括I2C 缓冲区信息、波特率等信息。其类型am_zlg600_i2c_devinfo_t 的定义(am_zlg600.h)如下:

实例信息主要包含帧格式、ZLG600A 模式、7 位I2C 从机地址和中断引脚信息。

frame_fmt 的含义与使用UART 通信方式时一致,对于出厂设置的模块,frame_fmt 的值应设置为:AM_ZLG600_FRAME_FMT_OLD。

now_mode 的含义与使用UART 通信方式时一致,对于出厂设置的模块,now_mode 的值应设置为:AM_ZLG600_MODE_AUTO_CHECK。在本次初始化完成后,若通过后续接口函数将模式固定为I2C 模式。则系统在下次启动调用ZLG600A 初始化函数时,必须确保now_mode 成员的值为更新后的I2C 模式。

slv_addr 为ZLG600A 的7 位I2C 从机地址,出厂默认值为0x59,数据手册中描述为0xB2,该值为8 位地址,右移一位,即移除表示读写方向的位后,值即为0x59。在本次初始化完成后,若通过后续接口函数修改I2C 地址。则系统在下次启动调用ZLG600A 初始化函数时,必须确保slv_addr 成员的值为更新后的I2C 地址。

int_pin 为ZLG600A 的INT 引脚与实际微控制器(如LPC824)连接的引脚号。比如,选择LPC824 的PIO0_13 与ZLG600A 的 INT 引脚相连,则该值应设置为PIO0_13。

基于此,实例信息定义如下:

(3)I2C 句柄i2c_handle

若选择LPC824 的I2C1 与ZLG600A 通信,则通过LPC82x 的I2C1 实例初始化函数am_lpc82x_i2c1_inst_init()获得I2C 句柄。即:

获得的I2C 句柄即可直接作为i2c_handle 的实参传递。

(4)实例句柄

am_zlg600_i2c_init()与am_zlg600_uart_init()的返回值相同,该返回值为ZLG600A 实例的句柄,该句柄将作为其它功能接口的第一个参数(handle)的实参。若返回值为NULL,说明初始化失败;若返回值不为NULL,说明返回一个有效的handle。

基于模块化编程思想,将初始化相关的实例、实例信息等的定义存放到对应的配置文件中,通过头文件引出实例初始化函数接口,源文件和头文件的程序范例分别详见程序清单6.100 和程序清单6.101。

程序清单6.100 新增ZLG600A 的I2C 通信方式的实例初始化函数(am_hwconf_zlg600.c)

程序清单6.101 am_hwconf_zlg600.h 文件内容更新

后续只需要使用无参数的实例初始化函数,即可获取到ZLG600A 的实例句柄。即:

>>> 6.4.3 设备控制类接口函数

ZLG600A 支持多种IC 卡,比如,Mifare S50/S70、ISO7816-3、ISO14443(PICC)、PLUSCPU 卡等,每种卡都有对应的命令。命令与接口函数基本上是一一对应的关系,ZLG600A的命令较多,分为以下5 类:设备控制类命令、Mifare S50/S70 卡类命令、ISO7816-3 类命令、ISO14443(PICC)卡类命令和PLUS CPU 卡类命令。

设备控制类接口函数与具体卡片没有直接关系,主要用于直接操作ZLG600A,比如,获取ZLG600A 的设备信息和存储IC 卡密钥等,详见表6.24。

表6.24 ZLG600A 设备控制类接口函数(am_zlg600.h)

1. 读取设备信息

该函数意在获取ZLG600A 的基本信息,包括产品信息和版本信息等,获取的信息为字符串,比如,“ZLG600A V1.00”。其函数原型为:

其中,p_info 为获取信息的指针,由于字符串长度为20 字节,因此需要提供一个长度为20 字节的内存空间,以便存放获取到的信息。若返回值为AM_OK,说明获取信息成功,反之失败,范例程序详见程序清单6.102。

程序清单6.102 读取ZLG600A 设备信息范例程序

假定选择UART 通信方式,即可使用am_zlg600_uart_inst_init()实例初始化函数获取ZLG600A 的实例句柄。同时包含标准C 头文件string.h,便于使用strcmp()函数判断字符串是否为“ZLG600A V1.00”?

由于这次使用的是ZLG600A V1.00 模块,因此获取的信息一定为“ZLG600A V1.00”。如果你使用的是其它型号或版本的模块,则要注意将比较信息的字符串修改,否则就算成功读取信息,比较结果也是不相等的。

2. 装载IC 卡密钥

卡片内存储的数据均是加密的,必须验证成功后才能读写数据。验证就是将用户提供的密钥与卡片内部存储的密钥对比,只有相同才认为验证成功。ZLG600A 提供了用于存储卡片验证的密钥的E2PROM,装载IC 卡密钥的作用就是将密钥存放到指定的E2PROM 存储区,其函数原型为:

其中,key_type 为密钥类型,密钥一般分为2 类,其分别为TypeA 和TypeB。其对应的宏详见表6.25。ZLG600A 能保存A 类型密钥16组,B 类型密钥16 组。

表6.25 密钥类型(am_zlg600.h)

注:之所以存在两类密钥,是由于实际卡片中往往存在两类密钥,两类密钥可以更加方便地进行权限管理,比如,TypeA 验证成功后只能读,而TypeB 只有验证成功后才能写入,但权限可以自定义设置。

key_sec 为保存的区号,由于ZLG600A 能保存A 类密钥16 组和B 类密钥16 组,因此每种类型保存的区域有16 个,其对应区号为0 ~ 15。

p_key 指向了实际待保存密钥的缓冲区,key_length 为密钥的长度,密钥最大长度为16 字节。保存一组6 字节长度的A 类型密钥至区号0 的范例程序详见程序清单6.103。

程序清单6.103 装载密钥范例程序

当后续需要验证卡片时,只需要指定密钥存放的E2PROM 区号0,无需再将密钥发送给ZLG600A。

>>> 6.4.4 操作接口函数

Mifare 卡是一种符合ISO14443 标准的A 型卡,其接口函数详见表6.26。

表6.26 Mifare S50/S70 接口函数(am_zlg600.h)

经常使用的公交卡、房卡、水卡和饭卡等均是Mifare 卡。比如,S50 和S70,它们的区别在于容量的不同。S50 为1Kbyte,共16 个扇区,每个扇区4 块,每块16 字节。S70 为4Kbyte,共40 个扇区,前32 个扇区每个扇区4 块,每块16 字节,后8 个扇区每个扇区16 块,每块16 字节。

1. 自动检测

  • 设置自动检测回调函数

当有卡片靠近ZLG600A 时,将会自动调用用户设定的回调函数,读取卡片的相关信息,因此需要先设置一个回调函数。其函数原型为:

其中,pfn_callback 为指向回调函数的指针,p_arg 为回调函数的参数。若返回AM_OK,表示设置成功,反之失败,范例程序详见程序清单6.104。

程序清单6.104 设置自动检测回调函数范例程序

程序中定义了一个detect_flag 变量,表示是否检测到卡片。如果初始值为0,说明未检测到卡片。在设置自动检测回调函数时,将其地址作为回调函数的p_arg 参数。因此在回调函数中,p_arg 实质上是指向detect_flag 的指针,通过该指针将detect_flag 设置为1,表明当前检测到卡片。

  • 启动自动检测

当设置好回调函数后,即可启动自动检测。其函数原型为:

其中,p_info 为指向自动检测相关信息的指针,其类型am_zlg600_auto_detect_info_t 定义如下:

该信息结构体包含检测模式、天线模式、请求模式和密钥验证相关的信息。

  • 检测模式

ad_mode 表示检测模式,用于配置检测相关动作。当检测到卡片时,是否挂起该卡片,若选择挂起,设置ad_mode 的值为AM_ZLG600_MIFARE_CARD_AD_HALT(am_zlg600.h),则在检测到一次该卡片后,就将该卡片挂起,后续检测将忽略该卡片。若需再次检测该卡片,必须将卡片远离ZLG600A 后重新靠近才有效。若设置ad_mode 的值为0,则不会挂起卡片,每次自动检测均可以检测到靠近的卡片。

举个简单的例子可能更容易理解,在平常刷公交卡时,当卡片靠近刷卡器时,会扣费一次,刷卡成功。若公交卡不离开刷卡器,则不会再次扣费,此时卡片已经被刷卡器挂起了,不会再被识别到。若将公交卡离开刷卡器后再次靠近,将可能再次扣费。

当ad_mode 的值均设置为AM_ZLG600_MIFARE_CARD_AD_HALT 时,则可以避免重复检测到同一张卡片。

  • 天线模式

tx_mode 设置天线的工作模式,ZLG600A 有2 个天线TX1 和TX2,4 种工作模式:仅使用TX1、仅使用TX2、TX1 和TX2 交替使用、TX1 和TX2 同时使用,各种模式对应的tx_mode 的值宏定义详见表6.27。

表6.27 天线工作模式(am_zlg600.h)

  • 请求模式

req_mode 表示请求模式,即检测所有的卡还是只检测空闲卡,对应的值宏定义详见表6.28,一般来讲只检测空闲卡。

表6.28 请求模式(am_zlg600.h)

  • 密钥验证

由于绝大部分卡片在检测到卡片时,都要先读取一块数据,因此可以将读取数据作为自动检测的一个附加功能。即在检测到卡片时,自动读取1 块(16 字节)数据。由于读取数据前均需要验证,这就需要在启动自动检测时,指定密钥验证相关的信息。

所谓密钥验证就是将用户提供的密钥与卡片内部存储的密钥对比,只有相等方能验证成功。auth_mode 指定了3 种验证模式,其对应的宏表6.29。

表6.29 验证模式(am_zlg600.h)

如果在自动检测到卡片时,不需要读取数据,则应该将auth_mode 的值设置为AM_ZLG600_MIFARE_CARD_AUTH_NO。由于不会用到信息结构体中key_type、key[16]、key_len、nblock 四个成员的值,因此无需设置。

如果需要读取数据,则必须将auth_mode 置为AM_ZLG600_MIFARE_CARD_AUTH_E2或AM_ZLG600_MIFARE_CARD_AUTH_DIRECT,其主要区别是验证密钥存放位置不同。

如果使用“直接验证”(AM_ZLG600_MIFARE_CARD_AUTH_DIRECT)的方式,则信息结构体的key[16]包含了实际的密钥,key_len 表示了密钥的长度。

如果使用“E2 验证”(AM_ZLG600_MIFARE_CARD_AUTH_E2)方式,则验证密钥存放在ZLG600A 的E2PROM 中。此时,信息结构体的key[16] 仅使用了首元素key[0],其值为密钥在E2PROM 中的区号(0 ~ 15)。自动检测时,将使用ZLG600A 中E2PROM 对应区号中的密钥进行验证。key_len 表示密钥的长度。显然,若使用“E2 验证”,则需要确保已经使用am_zlg600_ic_key_load()将密钥存放到了ZLG600A 中E2PROM 相应的区域。

信息结构体中的nblock 指定了要验证的块,即读取数据的块,只有该块被验证成功后,才能读取数据。Mifare S50 和Mifare S70 卡片包含的块数目详见表6.30。

表6.30 常见卡片的块数目(am_zlg600.h)

假定无需读取数据,可以定义自动检测信息如下:

定义好相关信息后,可以使用启动函数启动自动检测,即:

  • 读取卡片信息

当启动自动检测后,若前面注册的回调函数被调用,表明检测到卡片,此时可以使用该接口读取卡片的信息。其函数原型为:

其中,p_card_info 为指向卡片信息的指针,用于获取卡片信息。卡片信息的类型am_zlg600_mifare_card_info_t(am_zlg600.h)定义如下:

该信息结构体包含了天线驱动模式、卡片唯一序列号和读取的数据等相关的信息。

  • 天线驱动模式

tx_mode 表示天线的驱动模式,在启动自动检测时,天线的模式有4 种:仅使用TX1、仅使用TX2、TX1 和TX2 交替使用、TX1 和TX2 同时使用。若启动自动检测时使用的模式为TX1 和TX2 交替使用,那么该值将会被设置为实际检测到卡片的天线。tx_mode 可能被设置的值详见表6.31。

表6.31 读取到的天线驱动模式(am_zlg600.h)

当TX1 和TX2 同时使用时,将无法区分具体检测到卡片的天线。

  • 片唯一序列号

每张卡片都具有一个唯一序列号,即UID。所有卡片的UID 都是不相同的。卡的序列号长度有三种:4 字节、7 字节和10 字节。uid_len 表明了读取到的UID 的长度,uid[10]中存放了读取到的UID(字节数)。

  • 读取的数据

在启动自动检测时,指定了读取卡片数据相关的验证信息,若auth_mode 不为AM_ZLG600_MIFARE_CARD_AUTH_NO,且对应的密钥正确,验证成功,将读取启动自动检测时信息结构体的nblock 成员指定的块(由信息结构体的nblock 指定)的数据。读取的数据存放在card_data[16]数组中,读取卡片信息的范例程序详见程序清单6.105。

程序清单6.105 读取卡片信息范例程序

读取卡片信息成功后,将通过调试串口打印出读取到的UID 信息。并翻转LED1 灯的状态,指示读取一次卡片信息成功。

2. 卡片验证

由于卡片内存储的数据是加密的,因此必须验证成功后才能读写数据。验证方式有“E2验证”和“直接验证”,它们的区别是用于验证的密钥存放的位置不同。

  • E2 验证

用于验证的密钥是存放在ZLG600A 的E2PROM 中,其函数原型为:

其中,key_type 的类型是密钥类型,它的值为AM_ZLG600_IC_KEY_TYPE_A 或AM_ZLG600_IC_KEY_TYPE_B,分别代表A 类型密钥和B 类型密钥。

p_uid 为指向UID 高4 字节缓冲区的指针,若UID 为4 字节,其值为获取的UID 的首元素地址,即&card_info.uid[0];若UID 为7 字节,其值为获取的UID 的第3 号元素的地址,即&card_info.uid[3];若UID 为10 字节,其值为获取的UID 的第6 号元素的地址,即&card_info.uid[6]。key_sec 为密钥存放在ZLG600A 的E2PROM 中的区号,该值应该与使用am_zlg600_ic_key_load()函数存储对应密钥时使用的区号一致。

nblock 指定本次验证的块号,返回值为AM_OK 时表明验证成功,反之失败,使用区号0 中的A 类密钥验证块1 的范例程序详见程序清单6.106。

程序清单6.106 E2 验证范例程序

自动检测获取卡片信息card_info 详见程序清单6.101,调用am_zlg600_ic_key_load()将密钥存放在在0 区的E2PROM 中的程序详见程序清单6.103。

实际上绝大部分卡都是4 字节的,而7 或10 字节的UID 卡极少。如果确定使用的卡片UID 为4 字节,则p_uid 的值为&card_info.uid[0]。

  • 直接验证

用于验证的密钥是由接口函数提供,其函数原型为:

其中,key_type、p_uid、nblock 的含义与“E2 验证”相同,由于需要直接提供密钥,因此使用p_key 指向密钥存放的缓冲区,key_len 表示密钥的长度。返回值为AM_OK,表明验证成功,反之失败,直接使用6 字节密钥进行验证的范例程序详见程序清单6.107。

程序清单6.107 直接验证范例程序

程序使用6 字节全0xFF 作为密钥验证块1,之所以这样,是因为Mifare S50/S70 卡片的密钥出厂默认为全0xFF,且密钥长度为6 字节。对于出厂默认设置,使用A 类密钥和B类密钥验证均可。对于一些有权限控制的卡片,如验证A 类密钥后仅只读,验证B 类密钥后可写,则需要根据实际情况进行验证,密钥和权限控制的修改后面会进一步介绍。

3. 读写数据

若验证成功,则开始读写已验证的块。读写数据都是以块为单位的,其大小为16 字节。

  • 读取数据

读取数据就是读取某一块的数据,其函数原型为:

其中,nblock 指定读取的块号,p_buf 为指向存放数据的缓冲区,缓冲区大小为16 字节。返回值为AM_OK 时,表明读取数据成功,反之失败。如程序清单6.108 所示为读取块1 数据的范例程序。

程序清单6.108 读取数据范例程序

  • 写入一块数据

写入数据就是将数据写入到某一块,其函数原型为:

其中,nblock 指定写入的块号,p_buf 为指向写入数据的缓冲区,缓冲区大小为16 字节。返回值为AM_OK 时,说明写入数据成功,反之失败。如程序清单6.109 所示为写入16 字节数据至块1 的范例程序。

程序清单6.109 写入数据范例程序

如程序清单6.110 所示是展示卡片自动检测、验证和读写数据的综合测试范例程序。

程序清单6.110 ZLG600 综合测试范例程序

程序每检测到一次卡片(detect_flag 的值为1),将读取一次信息,然后使用调试串口打印UID 的值,接着进行读写检测。若读写检测失败,表明验证失败,很可能密钥不是初始密钥,已经被修改过了。

由于读取UID 并不需要验证,因此,当测试程序运行时,将常见的公交卡、门禁卡、饭卡等卡靠近ZLG600A,均可以读取卡片的UID。由于这些卡片的密钥并不知晓,因此读写数据测试很可能会失败。

>>> 6.4.5 密钥和权限控制

Mifare S50/S70 卡的初始密钥全为0xFF,显然,对于实际产品来讲,希望能够更改其密钥为其它值。由于存在密钥A和密钥B,可以对每个密钥设定不一样的权限,如验证密钥A后仅只读,验证密钥B 后可写。下面以Mifare S50 为例,介绍密钥和权限控制的修改方法。

密钥和权限控制是针对扇区而言的,即一个扇区的密钥是相同的,不同扇区的密钥可以不同。S50 共计16 个扇区,每个扇区4 块,每块16 字节,前3块为普通的数据块,最后一块(尾块)为密钥和权限控制块。对最后一块存储的数据进行修改,即可完成密钥和权限控制的修改。操作最后一块的存储数据时要格外小心,数据稍有错误,就可能导致扇区被锁死。尾块的前6 字节为A 密钥,后6字节为B 密钥,中间4 字节用于权限控制,详见图6.11。

图6.11 尾块格式

如需修改密钥和控制权限,重点在理解字节6、7 和8(字节9 是一个普通的数据)的含义。3 个字节共计24 位,每6 位(分别为C1、C2、C3、

由于存在此关系,因此实际控制位的含义仅通过C1、C2、C3 三个位即可确定。控制尾块和数据块的控制位含义是不同的。对于尾块,其控制了密钥A、密钥B 以及控制区域的访问权限。控制位的含义详见表6.32。

表6.32 尾块控制位含义

表中,“×”表示任何情况下都无权限,“KeyA”表示通过密钥A 验证后可以取得权限,KeyB 表示通过密钥B 验证后可以取得权限,“KeyA | B”表示通过密钥A 或者密钥B 验证后均可取得权限。由此可见,密钥A 的安全性很高,任何情况下都无法读出。特殊情况下,当C1C2C3 的值为000、010 或001 时,验证密钥A 后即可读取密钥B 区域的数据。

无论什么情况,验证密钥A 后,均可获得控制区域的读权限。通过读取控制区域,可以知道当前C1、C2、C3 的值,以判断需要验证哪个密钥后可以获得密钥区域或控制区域的写权限,进而修改密钥和控制区域的值。比如,当前的C1、C2、C3 的值为0、1、1,为了修改密钥A,则需要先验证密钥B,验证密钥B 后,即可对尾块进行写入,写入时其它数据保持不变,仅修改前6 字节(KeyA 区域)的值即可完全对密钥A 的修改。

对于数据块,C1、C2、C3 控制了对块中存储数据的操作权限,详见表6.33。

表6.33 数据块控制位含义

同样,表中“×”表示任何情况下都无权限,“KeyA”表示通过密钥A 验证后可以取得权限,KeyB 表示通过密钥B 验证后可以取得权限,“KeyA | B”表示通过密钥A 或者密钥B 验证后均可取得权限。

加值操作(相当于充值)和减值操作(相当于消费)是对块中存放的值进行增加和减少操作,加值和减值均有对应的命令可以直接使用。例如,当前块1 的C1、C2、C3 控制位的值为0、0、0(默认值),只要密钥A 或密钥B 验证通过后,均可取得数据块的读、写、加值、减值的权限。可以根据实际需要,修改尾块中相应控制位的值(修改时,需确保具有写入控制区域的权限),以对数据进行保护。

需要注意的是,凡是表中标识验证密钥B 后可以取得权限的,在特殊情况下验证密钥B后可能并不能取得权限。在介绍尾块控制位含义时,当C1、C2、C3 的值为000、010 或001时,KeyB 区域将可能被读取,详见表6.32。这些情况下,由于密钥B 可能被读取,为了确保安全,此时密钥B 验证将无效,即使密钥B 验证通过,同样无法取得相应的权限。

周立功单片机 技术专区

原文标题:周立功:重用外设驱动代码——读写卡模块

文章出处:【微信号:Zlgmcu7890,微信公众号:周立功单片机】欢迎添加关注!文章转载请注明出处。

关注电子发烧友微信

有趣有料的资讯及技术干货

下载发烧友APP

打造属于您的人脉电子圈

关注发烧友课堂

锁定最新课程活动及技术直播
收藏 人收藏
分享:

评论

相关推荐

是距离还是速度,让设计RS485系统陷入困境

网络设计人员知道,RS-485 标准在实现稳健可靠的通信方面具有良好的历史记录,并因此成了工业网络中....

的头像 电子设计 发表于 04-08 09:17 ? 1642次阅读
是距离还是速度,让设计RS485系统陷入困境

RS485通讯接口芯片UN3485特点

RS485芯片已经广泛应用于工业控制,安防系统,智能仪器仪表,多媒体网络,机电一体化产品及多个领域。....

的头像 EDA设计智汇馆 发表于 04-08 09:16 ? 508次阅读
RS485通讯接口芯片UN3485特点

解决芯片量产问题,MCU成最大焦点

随着越来也多的电子厂商不断为物联网(IoT)推出新产品,全球MCU出货量正出现巨大成长动能。特别是当....

的头像 ZLG致远电子 发表于 03-30 08:49 ? 1426次阅读
解决芯片量产问题,MCU成最大焦点

滤芯防伪技术,可以分布式读取8处防伪标签

空气净化器、净水器市场发展迅猛,很多品牌商都抢占到了自己的份额。但在实际使用过程中却发现很多用户长期....

的头像 周立功单片机 发表于 03-28 08:29 ? 652次阅读
滤芯防伪技术,可以分布式读取8处防伪标签

Ladview和东方马达进行485转USB通讯,但是读取不到字节数是怎么回事?

发表于 03-28 08:16 ? 218次阅读
Ladview和东方马达进行485转USB通讯,但是读取不到字节数是怎么回事?

二到四线转换器连接至全双工总线注意要点

多点数据通信网络,例如:Profibus、Modbus 和 BACnet 等通常均要求具备 RS-4....

的头像 电子设计 发表于 03-26 08:47 ? 2985次阅读
二到四线转换器连接至全双工总线注意要点

LONWORKS现场总线技术与RS485总线技术的优劣

现场总线形成真正分散在现场的完整控制系统,提高了控制系统运行的可靠性,丰富了控制设备的信息内容,,提....

的头像 鼎酷IOT部落 发表于 03-24 11:31 ? 781次阅读
LONWORKS现场总线技术与RS485总线技术的优劣

一款跨界核心板,让物联网设计如MCU系统便捷

M1052跨界核心板让设计者如开发普通MCU系统般简便,却拥有528MHz主频处理器的“不凡”性能。

的头像 ZLG致远电子 发表于 03-23 08:29 ? 1815次阅读
一款跨界核心板,让物联网设计如MCU系统便捷

三句话讲清环路分析,轻松检测控制系统稳定性

尽管环路分析是检测控制系统稳定性的重要手段,但是测试过程中有诸多细节需要注意。如何快速理解环路分析的....

的头像 ZLG致远电子 发表于 03-21 08:04 ? 981次阅读
三句话讲清环路分析,轻松检测控制系统稳定性

CRC16 校验 常用的RS485通讯可以使用

发表于 03-20 19:00 ? 180次阅读
CRC16 校验   常用的RS485通讯可以使用

面对大烧录量和严格性能要求,如何高效快速生产汽车零组件

一辆光鲜亮丽的汽车上有琳琅满目的电子部件,每一个电子部件往往都拥有它自己的芯片,每个芯片又有它独立的....

的头像 ZLG致远电子 发表于 03-19 08:44 ? 2231次阅读
面对大烧录量和严格性能要求,如何高效快速生产汽车零组件

关于rs485的代码问题

发表于 03-14 14:20 ? 166次阅读
关于rs485的代码问题

周立功现身说法:谈工程师如何克服职业痛点培养对市场的前瞻性

为什么很多工程师创业失败?其根本原因不是资金,而是因为不了解市场,对市场缺乏一定前瞻性的认识,做出来....

的头像 工程师人生 发表于 03-14 10:53 ? 273次阅读
周立功现身说法:谈工程师如何克服职业痛点培养对市场的前瞻性

Labview基于VISA实现RS232、RS485 Modbus的通讯(带CRC校验)

发表于 03-14 10:28 ? 1004次阅读
Labview基于VISA实现RS232、RS485 Modbus的通讯(带CRC校验)

Zigbee无线模块在流速计上的应用方案

新时代的智慧城市,要求全面提升监控力度和智能化管理水平。我国广阔的水域,将会建设更多无人值班监测点,....

的头像 ZLG致远电子 发表于 03-12 09:40 ? 1993次阅读
Zigbee无线模块在流速计上的应用方案

如何通过技巧快速进行选型?电源设计浅谈

电容是开关电源中的再普通不过的器件,它可以用来降低纹波噪声,可以用来提高电源的稳定性以及瞬态响应性,....

的头像 ZLG致远电子 发表于 03-10 09:34 ? 2964次阅读
如何通过技巧快速进行选型?电源设计浅谈

ZLG携手NXP举行i.MX RT 跨界处理器全国巡回研讨会

2018年3月20号—4月3号,ZLG将携手NXP在全国6大城市(广州、深圳、上海、杭州、南京、北京....

的头像 ZLG致远电子 发表于 03-09 15:24 ? 803次阅读
ZLG携手NXP举行i.MX RT 跨界处理器全国巡回研讨会

隔离式全双工高速数据链路应用设计方案

追求更高的数据吞吐量、更短的响应时间和更低的安装成本,是推动工业网络设计持续改进的驱动力。

的头像 瑞萨电子 发表于 03-05 11:23 ? 1589次阅读
隔离式全双工高速数据链路应用设计方案

MCU+MPU双处理器架构在电力馈线终端中应用

目前市面上大多电力FTU产品均采用MCU+MPU双处理器架构,以利用MCU的实时性和MPU上运行的稳....

的头像 周立功单片机 发表于 03-05 08:41 ? 1341次阅读
MCU+MPU双处理器架构在电力馈线终端中应用

一个好电源设计,为何要非常重视输出纹波噪声

纹波噪声是衡量电源的一个重要指标,一个好的电源必须要把输出纹波噪声控制在一个合理的范围内。但一般有哪....

的头像 ZLG致远电子 发表于 03-05 08:35 ? 1685次阅读
一个好电源设计,为何要非常重视输出纹波噪声

以太网无法取代CAN的原因是什么?

CAN总线通过物理信号来进行连接,而以太网则是交换机连接。CAN总线的结构非常简单,仅需拉两条线而已....

发表于 03-02 09:48 ? 190次阅读
以太网无法取代CAN的原因是什么?

详解RS232、RS485、RS485、串口&握手

详解RS232、RS485、RS485、串口&握手。RS232基础知识计算机与计算机或计算机与终端之....

的头像 EDN电子技术设计 发表于 03-01 09:35 ? 721次阅读
详解RS232、RS485、RS485、串口&握手

工业通讯现场,为何最担心浪涌产生的瞬态过压和过流!

各位工程师在工业通讯现场,最担心的是通讯网络因浪涌产生的瞬态过压和过流,导致总线通讯网络出现发送错误....

的头像 周立功单片机 发表于 02-28 08:42 ? 1249次阅读
工业通讯现场,为何最担心浪涌产生的瞬态过压和过流!

如何解决照明灯具的测试测量痛点

家用照明灯具在出厂时,都是需要经过测量装备严格的检测,当照明灯在正常工作或特定模式下时,电压、电流和....

的头像 电子发烧友网工程师 发表于 02-20 03:28 ? 1831次阅读
如何解决照明灯具的测试测量痛点

电压波动与电压闪变对比分析

电压闪变与波动,两个形影不离的兄弟,经常一起出现在我们的视野中。闪变外向,我们可以从外表觉察到它的变....

的头像 电子发烧友网工程师 发表于 02-16 09:40 ? 900次阅读
电压波动与电压闪变对比分析

如何确保对吸尘器的心脏进行可靠“体检”

人类正是由于心脏不断地跳动才得以生存;吸尘器也是一样,只有心脏安好,才能更好的吸尘。人类为了确保身....

的头像 电子发烧友网工程师 发表于 02-15 03:33 ? 896次阅读
如何确保对吸尘器的心脏进行可靠“体检”

485总线为什么要隔离_RS485总线隔离原因如何测试揭秘

您在使用CAN或RS-485总线进行调试时,是否遇到过偶尔通信出错?或者接收不到数据?一直正常使用的....

发表于 02-14 05:49 ? 263次阅读
485总线为什么要隔离_RS485总线隔离原因如何测试揭秘

RS485通讯的正确接线方式介绍

485总线由于其布线简单,稳定可靠从而广泛的应用于视频监控,门禁对讲,楼宇报警等各个领域中,但是,在....

发表于 02-08 16:04 ? 2020次阅读
RS485通讯的正确接线方式介绍

CAN总线与RS485总线协议转换器的设计

本协议转换器完成RS485与CAN协议的相互转换,完成数据的双向传输,并能通过RS232接口连接到上....

发表于 02-08 15:28 ? 655次阅读
CAN总线与RS485总线协议转换器的设计

485通讯协议程序怎么写(51单片机的485通信程序案例)

RS-485收发器采用平衡发送和差分接收,因此具有抑制共模干扰的能力,加上收发器具有高的灵敏度,能检....

发表于 02-08 11:27 ? 640次阅读
485通讯协议程序怎么写(51单片机的485通信程序案例)

485通讯协议怎么使用(传统光电隔离的典型电路实例)

RS485通信网络接口是1种总线式的结构,上位机(以个人电脑为例)和下位机都挂在通信总线上,RS48....

发表于 02-08 11:07 ? 276次阅读
485通讯协议怎么使用(传统光电隔离的典型电路实例)

组建RS-485总线网络时,终端电阻实战案例

RS-485总线具有结构简单、成本低等优点,但各位工程师在组建RS-485总线网络时,为提升整个网络....

的头像 周立功单片机 发表于 02-08 09:51 ? 2353次阅读
组建RS-485总线网络时,终端电阻实战案例

分析电能质量分析仪一个案例中的测试效果

小到家庭,大到企业,能耗问题一直以来都是大家所关注重视的问题。中国企业的能耗一直很高,国家也努力促使....

的头像 ZLG致远电子 发表于 02-08 09:44 ? 2122次阅读
分析电能质量分析仪一个案例中的测试效果

ZLG致远电子E6000率先支持新国标 电压暂降和短时中断的定义

国家标准2013年第25号批准发布公告,由国网福建电科院负责编制的国家标准《电能质量电压暂降与短时中....

的头像 电子发烧友网工程师 发表于 02-05 11:11 ? 1759次阅读
ZLG致远电子E6000率先支持新国标 电压暂降和短时中断的定义

电子产品性能提升中,如何防止“安全”掉链子

最火手游“王者荣耀”将玩家分成“青铜、白银、黄金...”等段位。笔者从青铜开始打到最强王者。是不是电....

的头像 ZLG致远电子 发表于 02-05 09:44 ? 1934次阅读
电子产品性能提升中,如何防止“安全”掉链子

互联网温控器芯片应用及整体方案

LG致远电子基于NXP的KL16、Semtech的SX1278芯片开发的低功耗、高性能的LoraNe....

的头像 周立功单片机 发表于 02-05 09:19 ? 1838次阅读
互联网温控器芯片应用及整体方案

一款优质电源必然具备:启动性设计

一款优质电源必然具备启动性能好、转换效率高等特点,但你有没有想过宽压电源的输入电压范围那么广,而电源....

的头像 ZLG致远电子 发表于 02-02 09:33 ? 4468次阅读
一款优质电源必然具备:启动性设计

为什么你的手机实际内存比标称内存要少很多

现在市面上存在NAND FLASH和eMMC这两种的大容量存储介质,就是各类移动终端及手机的主要存储....

发表于 01-29 07:40 ? 589次阅读
为什么你的手机实际内存比标称内存要少很多

如何使用RTC实时时钟进行应用场景开发

虽然该程序的逻辑与程序清单6.70 所示的应用程序基本一致,但由于使用的接口是特殊功能控制接口,与具....

的头像 周立功单片机 发表于 01-25 09:15 ? 1730次阅读
如何使用RTC实时时钟进行应用场景开发

对于PPI和MPI通信的详细解析

首先,这里对S7-200通讯性能做一个整体介绍,请看CPU200和扩展模块示意图(上图),CPU20....

的头像 工控云学堂 发表于 01-22 15:18 ? 1683次阅读
对于PPI和MPI通信的详细解析

键盘与数码管接口典型应用电路及寄存器

当矩阵扩大到一定数目时,逐行扫描的方法会显得费时,如果需要对2 个以上的按键“同时”操作时,则处理起....

的头像 周立功单片机 发表于 01-22 09:27 ? 2174次阅读
键盘与数码管接口典型应用电路及寄存器

如何理解软件设计原则和面向接口编程的开发思想

面向通用接口的编程,虽然面向接口的编程简单易懂,但无法做到最大程度上地重用应用程序,这是导致软件开发....

的头像 周立功单片机 发表于 01-22 09:11 ? 2787次阅读
如何理解软件设计原则和面向接口编程的开发思想

设计一个处理工资单数据包,继承与多态不可忽略!

虽然各种排序的实现不一样,但它们的共性都是“排序”,这就是抽象的基础。

的头像 周立功单片机 发表于 01-19 10:18 ? 2950次阅读
设计一个处理工资单数据包,继承与多态不可忽略!

温度传感器通用接口应用案例分析

对AMetal框架进行了详细介绍,通过阅读这本书,你可以学到高度复用的软件设计原则和面向接口编程的开....

的头像 周立功单片机 发表于 01-19 10:14 ? 3736次阅读
温度传感器通用接口应用案例分析

数码管与矩阵键盘联合应用设计

AMetal 提供了数码管和矩阵键盘联合使用的驱动,其本质上就是数码管驱动和矩阵键盘驱动的简单整合,....

的头像 周立功单片机 发表于 01-19 09:31 ? 2395次阅读
数码管与矩阵键盘联合应用设计

详细剖析交流充电桩上电源和RS485隔离原理

较直流桩而言, 交流 桩少了大功率的 电源模块 ,充电的功率也小很多,电磁环境相对友好,但仍不可轻视....

的头像 电子设计 发表于 01-18 07:28 ? 3008次阅读
详细剖析交流充电桩上电源和RS485隔离原理

在LED通用接口的设计中,HC595主要作用

当前接口中的am_hc595_handle_t 类型为void *类型,最终,其需要是指向对象的指针....

的头像 周立功单片机 发表于 01-17 08:34 ? 2757次阅读
在LED通用接口的设计中,HC595主要作用

深入理解AMetal,掌握蜂鸣器和温度采集接口设计

在接口实现中,没有与硬件相关的实现代码,仅仅是简单的调用了抽象方法。抽象方法需要由具体的温度采集设备....

的头像 周立功单片机 发表于 01-17 08:29 ? 2837次阅读
深入理解AMetal,掌握蜂鸣器和温度采集接口设计

以CAN与RS485为例总结各自优势 解疑“为什么CAN能取代RS485”

近年来CAN总线逐渐被工程师认知,并以其突出特点,逐渐在取代RS485等总线,本文将以CAN与RS4....

的头像 ZLG致远电子 发表于 01-15 14:58 ? 1932次阅读
以CAN与RS485为例总结各自优势 解疑“为什么CAN能取代RS485”

一款基于法拉电容的UPS电路设计思路

您是否有遇到使用中的程序无故丢失?产品调试非常稳定,布置到现场后频繁系统崩溃和数据遗失,亦或产品应用....

的头像 ZLG致远电子 发表于 01-15 09:06 ? 2203次阅读
一款基于法拉电容的UPS电路设计思路

通用数码管与面向通用接口编程设计

数码管的各个段可以组合显示出多种图形,使用该函数可以自定义字符的解码函数

的头像 周立功单片机 发表于 01-10 09:13 ? 2723次阅读
通用数码管与面向通用接口编程设计

手机蓝牙转串口硬件和ANDROID的APK程序开发

发表于 01-10 09:05 ? 293次阅读
手机蓝牙转串口硬件和ANDROID的APK程序开发

RS-485网络为何需要加终端电阻

RS-485总线具有结构简单、成本低等优点,但各位工程师在组建RS-485总线网络时,为提升整个网络....

的头像 ZLG致远电子 发表于 01-10 06:52 ? 3375次阅读
RS-485网络为何需要加终端电阻

labview上位机,周立功USBCAN1卡,传输指令给电机驱动器

发表于 01-07 13:00 ? 447次阅读
labview上位机,周立功USBCAN1卡,传输指令给电机驱动器

求问如何实现多个DSP28335之间的SCI通讯

发表于 12-26 17:26 ? 533次阅读
求问如何实现多个DSP28335之间的SCI通讯

请教485多机通讯问题

发表于 12-25 15:14 ? 281次阅读
请教485多机通讯问题

手机蓝牙转串口硬件和ANDROID的APK程序开发

发表于 12-22 16:23 ? 797次阅读
手机蓝牙转串口硬件和ANDROID的APK程序开发

蓝牙转串口硬件设计和ANDROID的APK程序开发

发表于 12-21 14:54 ? 273次阅读
蓝牙转串口硬件设计和ANDROID的APK程序开发