基于MCU实现CPU卡读写驱动接口的设计
0 引言
当今,各类IC卡(如居民身份证、社保卡、水电气充值卡等)已成为人们日常生活中不可缺少的一部分,并为人们的生活带来了极大的便利。IC卡技术也已从最初的存储卡、逻辑加密卡发展到今天的CPU卡。与之相应的是需要配备大量的IC卡智能终端设备。目前开发的IC卡智能终端设备中的读写接口部分大多采用专用的接口芯片来实现,如TDA8007等,这使得产品的成本较高,体积也较大。本文提出一种基于设备产品的主控MCU通用引脚,直接模拟通信协议实现接触式CPU卡读写接口的低成本实用方案。
1 CPU卡的接口特性及传输协议
CPU卡也称智能卡(Smart Card),卡中的集成电路包括微处理器、EEPROM、随机存储器RAM、程序存储器ROM(Flash)以及片内操作系统(COS)。装有COS的CPU卡相当于一台微型计算机,不仅具有数据存储功能,同时具有命令处理和数据安全保护等功能。按卡与外界数据传送的形式来划分,可将CPU卡分为接触式卡、非接触式卡和双界面卡。
1.1CPU卡的触点分配
CPU卡触点的分配遵循ISO78162的规定[1],如图1所示,表1为触点的功能及工作参数说明。
1.2CPU卡使用过程
正常的用卡过程可划分为如下4个阶段[2]:
(1)把IC卡插入终端接口设备,并接通各触点;
(2)使IC卡复位并在终端和IC卡间建立通信;
(3)执行交易;
(4)释放触点并取出IC卡。
1.3传输协议
根据ISO7816-4的规定,CPU卡必须支持异步半双工字符传输协议(T=0)或异步半双工块传输协议(T=1)中的一种,且仅支持一种。读卡终端则必须同时支持T=0和T=1的两种协议[3]。目前T=0通信协议的应用最为广泛,大多数CPU卡都支持该协议,在金融交易中也采用这种通信协议,基于此,本文仅讨论T=0协议。
1.3.1协议命令
协议的命令格式如下[4]:
其中CLA表示命令类别;INS表示指令代码;P1、P2为INS的参数字节;Lc为发送数据长度, 可选字段,长度为0、1 B或3 B;Data为命令数据字段,可选字段,长度为0~N B;Le为接收数据长度,可选字段,长度为0、1 B、2 B或3 B,指出命令响应中预期的数据最大字节数;命令头由命令的前5 B组成,其中第5个字节(P3)由INS的编码而定,或是表示命令中送给CPU卡的数据,或是等待从CPU卡响应的最大数据长度。 协议响应的格式如下:
2其中Data为返回数据字段,可选字段,长度为0~N B;SW1、SW2为响应状态字节。
1.3.2过程字节
CPU卡在收到命令头后,回送一个过程字节给传输层(TTL),向TTL指明下一步必须采取的措施[2],如表2所示。
在情况Ⅰ或Ⅱ时,当TTL采取的措施实行后,它就等待着另一个过程字节。当情况为Ⅲ时,在收到第2个状态字节SW2之后,TTL必须处理如下:
(1)如果过程字节为"61",则TTL送出一条GET RESPONSE命令给IC卡,其中的最大长度为XX,XX为SW2的值。
(2)如果过程字节为"6C",则TTL立即重发前一个命令的命令头给IC卡,其长度为XX,XX是SW2之值。
(3)如果过程字节为"6X"(除了"60"、"61"和"6C")或"9X",TTL将通过命令响应返回状态码给应用层(TAL),由TAL处理,并等待下一个命令。
2 硬件接口设计
能对CPU卡进行读写操作的MCU,第一,需要有时钟输出CLKOUT功能,能输出1~5 MHz的某一频率时钟;第二,需要有一个外部中断口,用于检测插卡动作。当然,开发一个项目,比如卡式水表或燃气表,还需要考虑低功耗、LCD驱动、A/D转换、内部存储器和内部振荡器等,尽量用一颗MCU完成项目的所有功能以节约成本。
在本案中,选用了Microchip公司的8位CMOS闪存单片机PIC16LF1946芯片[5]。该芯片内置高精度振荡器,可选32 MHz、16 MHz(TYP)、8 MHz、4 MHz、2 MHz、1 MHz作为系统时钟;内置16K×14 B的闪存程序存储器,1 024 B的数据存储器(RAM),256 B数据EEPROM;自带LCD驱动器,最多能驱动4×46位段的面板;一个时钟输出引脚,输出频率为Fosc/4;还有17个10 bit分辨率的AD采样口,8个外部中断口,5个定时/计数器等功能部件;超低功耗设计,已采用该芯片开发完成的卡式燃气表,其平均电流小于8 μA。这些资源和特性满足控制系统的需求。
2.1ESAM
嵌入式安全控制模块(Embedded Secure Access Module,ESAM)其实质为DIP或者SOP芯片封装的CPU卡芯片,最早被用于IC卡电表作为钱包使用,存储充值及消费金额以及其他一些重要的参数,同时具有身份识别功能,与外部卡片进行双向身份认证。随着终端安全的日益被重视,目前ESAM被广泛应用于各种智能终端设备中,实现文件和密钥的安全存储、数字签名、数据加密解密、双向身份认证、内部分散密钥、电子钱包等多种功能[6]。ESAM的读写接口与CPU卡的读写接口完全一致。
2.2电路设计
本方案包括CPU卡接口电路和ESAM接口电路,可实现对CPU卡读写、密钥认证和数据存储等功能。原理图如图2所示。
RG1和RG3端口分别连接CPU卡的数据IO和RST,RF6和RF5端口分别连接ESAM模块的数据IO和RST。
CPU卡的工作时钟直接使用MCU的引脚输出时钟,这样就可以很好地实现双方的通信时钟同步问题。因PIC16LF1946单片机只有一个时钟输出端口(RA6),只能使用此端口同时给CPU卡和ESAM提供工作时钟,时钟工作频率设置为4 MHz,以充分利用CPU卡的高速性能。
从降低功耗和安全性方面考虑,CPU卡和ESAM的电图2电路原理图源和时钟应该由MCU来控制,RG2端口控制给卡座供电,RF7端口控制给ESAM卡供电,RG0端口控制时钟输出。使用具有中断功能的RB0端口检测卡片的插入与拔出,当有卡片插入卡座时,给卡座供电,同时输出时钟信号;当卡片拔出后应立即停止供电和关闭时钟输出。ESAM也一样,其电源和时钟在需要访问时才打开,访问结束后关闭。
3 软件函数设计
实现整个接口驱动,可设计成6个函数来完成,应用层一般只需调用上电复位函数、卡命令处理函数和下电关闭函数。
void delayETU(x):位持续时间延时函数;
void cpu_deactivation(void):下电关闭函数;
static unsigned char cpu_receivebyte(unsigned char *c):接收字符帧函数;
static unsigned char cpu_sendbyte(unsigned char c):发送字符帧函数;
unsigned char cpu_reset(unsigned char len,unsigned char *data_buffer):上电复位函数;
unsigned char cpu_protocol(unsigned char len, const unsigned char *send_cmd, unsigned char *lenr, unsigned char *receive_data, unsigned char bRespondAuto):卡命令处理函数。
3.1位持续时间的计算
终端与CPU卡之间通过改变I/O传输线上的电平来交换信息,在数据传输中每一位的持续时间称为基本时间单元(Elementary Time Unit,ETU),ETU的值由时钟频率f决定,其计算公式为:
1 ETU=372/f(1)
其中,f的单位为Hz,在卡的整个交易过程中,f的值应在1~5 MHz之间[2]。当时钟频率f选择4 MHz时,1 ETU=93 μs,这只是一个理论值,在实际应用中,受到编程语言及编译器的影响会有小幅变化,需调测出最小值和最大值,选择中间值使用。
3.2上电复位
CPU卡插入卡座前,必须确保终端的所有触点都处于低电平状态。当MCU的外部中断检测到有卡片插入卡座时,在做必要的防抖动处理后,开始进入对CPU的上电复位操作,步骤如下:
(1)给Vcc上电,延时20 μs左右等待Vcc稳定;
(2)加上CLK时钟信号;
(3)把I/O线置为接收方式;
(4)延时40 000~45 000个CLK周期,之后把RST置为高电平状态;
(5)循环检测CPU卡上I/O的复位应答信号,正常情况下,400多个CLK周期之后便能开始收到应答,如应答字节符合ISO78163的要求,则复位成功;如在40 000个CLK周期内没有收到应答,表明复位失败,需对CPU卡执行下电操作,释放各个触点。
3.3下电关闭
下电是用卡过程的最后一个步骤,在交易结束后(包括异常结束),必须按以下步骤释放各触点:
(1)置RST为低电平状态;
(2)在RST置为低电平之后,且Vcc置为低电平之前,将CLK关闭,I/O置为低电平;
(3)置Vcc为低电平去电。
3.4接收字符帧
每一个字符帧包含10个相连的数位:1位为低电平的起始位、8位数据字节和1位偶校验位。首先循环查询起始位,如果在40 000个CLK周期内没有收到低电平起始位,表明接收字符帧失败,返回接收超时失败;否则,如收到图3接收字符帧流程低电平起始位,则继续接收后续的8位数据字节和1位偶校验位。之后,比较校验位是否正确,若校验位正确则表明接收字符帧成功;若校验位错误,请求CPU卡重发字符帧,最多请求重发2次。若2次重新接收的字符帧都不正确,则返回接收失败。图3是接收字符帧的函数流程图。
3.5发送字符帧
根据ISO7816标准的规定,要发送一个字符帧,首先发送1位起始位,接着发送8位数据字节,最后发送偶校验位。之后,I/O口转为接收模式,再过一个ETU之后,检测I/O口,若为高电平则表明字符发送成功,若为低电平则表明发送错误,需要重新发送。若重发2次都还是发送错误,则返回发送失败。图4是发送字符帧的函数流程图。
3.6卡命令处理函数
在ISO7816标准中定义了多种终端与卡的信息交互命令,包括管理卡和文件的命令、数据单元处理命令、记录处理命令、数据对象处理命令、安全处理命令、传输处理命令、用于结构化卡查询语言的处理命令和在多应用环境中的应用管理命令。当然,在实际应用中并不要求所有的卡都支持全部的命令。
所有命令均是由终端应用层(TAL)通过传输层(TTL)向IC卡发出命令,TTL首先把命令头的5 B传送给IC卡,并等待着一个过程字节返回,之后再根据返回的过程字节作进一步的处理[2]。
图5是卡命令处理函数的流程图[7],按此图编写的函数可处理所有终端与卡交互命令。
4 接口测试
图6卡式燃气表控制器使用某一燃气表项目的CPU卡,对按照本文接口方案开发的卡式燃气表控制器(如图6所示)进行测试,分别测试了上电复位函数、卡命令处理函数和下电关闭函数。测试结果表明接口的设计符合ISO7816的要求。
(1)上电复位测试
把CPU卡插入卡座,控制器MCU执行cpu_reset()函数,接收到从CPU卡返回的应答数据:3B 6D 00 00 57 44 29 46 40 86 93 00 07 E2 07 45 2C。该数据符合ISO78163的复位应答要求,上电复位函数测试成功。
(2)选择应用目录命令测试
MCU执行cpu_protocol()函数,给CPU卡发送命令:00 A4 00 00 02 DF 01;CPU卡返回应答数据:6F 10 84 0E 31 50 41 59 2E 53 59 53 2E 44 44 46 30 32 90 00。
应答数据的最后2 B为状态字节SW1和SW2,其中90 00表示执行命令成功。
(3)读取用户卡号命令测试
MCU执行cpu_protocol()函数,给CPU卡发送命令:00 B0 8A 0C 08;CPU卡返回应答数据:07 55 00 01 26 70 17 06 90 00。
应答数据的前8 B为用户卡的卡编号,后2 B状态字节90 00表示执行命令成功。
(4)下电关闭测试
在MCU执行cpu_deactivation ()函数之后,使用万用表检测卡座的RST、Vcc和I/O触点均为低电平,使用示波器检测CLK触点为没有波型输出,说明CPU卡已下电关闭成功。
5 结论
本文是在具体的项目开发过程中,根据ISO7816系列标准,基于MCU通用I/O引脚实现了CPU卡读写接口的软硬件低层驱动设计,此设计方案已在实际应用中得到了验证,效果良好。读者稍加修改或不用修改便可以把本文的设计应用到其他CPU卡系统项目中。
参考文献
[1] International Standard ISO/IEC 78162. Dimensions and location of the contacts[S]. 2007.
[2] International Standard ISO/IEC 78163. Electrical interface and transmission protocols[S]. 2006.
[3] International Standard ISO/IEC 78164. Organization, security and commands for interchange[S]. 2005.
[4] 王爱英. 智能卡技术——IC卡、RFID标签与物联网(第4版)[M]. 北京:清华大学出版社, 2015.
[5] Microchip. PIC16(L)F1946/1947数据手册[Z]. 2012.
[6] 王耀. ESAM安全模块及其在卡表上的应用[J]. 城市燃气, 2003, 337(3): 1821.
[7] 陈峰,尹寒. CPU卡的接口特性、传输协议与读写程序设计[J]. 单片机与嵌入式系统应用, 2002(3): 1722.