- UID
- 811198
|

在当前的金融POS终端及相关领域,ISO7816通讯协议得到了广泛应用。英创的工控主板EM9161,可在其异步串口的基础上,通过简单的设置,就可把串口转为符合ISO7816协议的接口,实现与各种智能卡的通讯。本文主要介绍采用EM9161的COM2口,实现ISO7816通讯的基本方法。

上图表示EM9161作为ISO7816主控方与智能卡的连接示意图,其中原COM2口的数据发送管脚TXD2作为ISO7816的半双工数据信号DIO;原COM2口的RTS2n控制线作为ISO7816的时钟信号SCK。两个信号线的电平均为3.3V的TTL信号电平。
应用程序进行ISO7816通讯的基本流程为:
1.按标准方法打开串口“COM2:”,并设置相应串口参数;
2.通过DeviceIoControl(…)函数使能ISO7816通讯模式,并设置相关参数;
3.设置波特率,注意在使能ISO7816模式后,必须重新设置波特率;
4.进行数据通讯,数据帧的奇偶校验位需要与通讯对端匹配;
5.通过DeviceIoControl(…)函数禁止ISO7816通讯模式;
6.按标准方法关闭串口“COM2:”。
为了实现从通常的异步串口到ISO7816的转换,EM9161的串口驱动增加了2个IOCTL功能如下:
#include <winioctl.h>
#define IOCTL_SERIAL_ENABLE_ISO7816 \
CTL_CODE(FILE_DEVICE_SERIAL_PORT,40,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_SERIAL_DISABLE_ISO7816 \
CTL_CODE(FILE_DEVICE_SERIAL_PORT,41,METHOD_BUFFERED,FILE_ANY_ACCESS)
使能ISO7816的DeviceIoControl调用,需要同时设置相应的参数。这些参数包括ISO7816的协议类型,帧数据的应答规范等,定义相应的参数如下:
#define AT91C_US_USMODE_ISO7816_0 0x4 // ISO7816 protocol: T = 0
#define AT91C_US_USMODE_ISO7816_1 0x6 // ISO7816 protocol: T = 1
#define AT91C_US_INACK (0x1 << 20) // Inhibit Non Acknowledge
#define AT91C_US_DSNACK (0x1 << 21) // Disable Successive NACK
此外ISO的波特率按如下公式计算:
BR = (DI / FI)× SCK
上式中的SCK = 串口波特率×FI / DI,例如串口波特率为9600,FI / DI = 372,则SCK时钟频率为3.57MHz。在EM9161中,对DI和FI的设置,是通过设置(FI/DI)这个比值来实现的,其中有效的值如下表所示:
FI
| DI=1
| DI=2
| DI=4
| DI=8
| DI=16
| DI=32
| DI=12
| DI=20
| 372
| 372
| 186
| 93
| 47
| 23
| 12
| 31
| 19
| 558
| 558
| 279
| 140
| 70
| 35
| 17
| 47
| 28
| 774
| 774
| 372
| 186
| 93
| 47
| 23
| 62
| 37
| 1116
| 1116
| 558
| 279
| 140
| 70
| 35
| 93
| 56
| 1488
| 1488
| 744
| 372
| 186
| 93
| 47
| 124
| 74
| 1806
| 1806
| 930
| 465
| 233
| 116
| 58
| 155
| 93
| 512
| 512
| 256
| 128
| 64
| 32
| 16
| 43
| 26
| 768
| 768
| 384
| 192
| 96
| 48
| 24
| 64
| 38
| 1024
| 1024
| 512
| 256
| 128
| 64
| 32
| 85
| 51
| 1536
| 1536
| 768
| 384
| 192
| 96
| 48
| 128
| 77
| 2048
| 2048
| 1024
| 512
| 256
| 128
| 64
| 171
| 102
|
选择蓝色区域的值,可得到对应的黄色区域的FI和绿色区域的DI,由此可计算相应的波特率。
在具体的调用中,参数的传递是通过两个DWORD实现的,代码如下:
DWORD dwMode, dwFI_DI_Ratio;
DWORD pBuf[2];
dwMode = AT91C_US_USMODE_ISO7816_0;
dwFI_DI_Ratio = 372;
pBuf[0] = dwMode;
pBuf[1] = dwFI_DI_Ratio;
if (!DeviceIoControl ( m_hSer, // 串口handle
IOCTL_SERIAL_ENABLE_ISO7816, // 命令码
pBuf, sizeof(pBuf), // input buffer
NULL, 0, // output buffer
NULL, NULL ))
{
printf('IOCTL_SERIAL_ENABLE_ISO7816 failed!\r\n');
}
关闭ISO7816通讯模式比较简单,没有任何参数:
if (!DeviceIoControl ( m_hSer, // 串口handle
IOCTL_SERIAL_DISABLE_ISO7816, // 命令码
NULL, 0,
NULL, 0,
NULL, NULL ))
{
printf('IOCTL_SERIAL_DISABLE_ISO7816 failed!\r\n');
}
设置了ISO模式后,应用程序仍然可以像操作普通串口那样,进行数据的读写,只是需要注意的是ISO7816的半双工模式的,所以数据通讯的过程更像是RS485的过程。用户可参考英创网站的《RS485接口通讯的WinCE编程要点》一文,来规划自己的应用程序。
[查看全文]
[关于英创]
[更多文章]
[技术论坛]
本文PDF格式下载 |
|