在线时间4061 小时
UID3441752
注册时间2017-11-21
NXP金币759548
TA的每日心情 | 开心 前天 15:16 |
---|
签到天数: 266 天 [LV.8]以坛为家I
管理员
- 积分
- 31903
- 最后登录
- 2024-3-28
|
本文的内容来自恩智浦专家王晓华的这本专著——《RCC、MST和NFC标准及技术应用》,这部分内容只是安全的移动支付体系中很小的一部分,希望了解更多移动支付的技术,请阅读这本被众多专家推荐的专著。
读完本文者将有幸获得具有王晓华先生亲笔签名的这本书。
磁安全传输(MST)是一种通过发出磁信号,模拟传统的磁条卡的技术。其应用目标是把现有磁条卡的一些业务,除现有大量市场存量的银行磁条卡外,还有积分卡、优惠券、会员卡等集成到支持MST的智能设备中。
MST的电路原理和实现过程,本质上和磁头去读磁条卡的磁道原理是一样的。磁条卡需要通过接触的方式,通过刷卡动作,使卡片的磁力线传导至磁头上去,从而把数据读回来;而MST则是通过线圈产生变化的磁力线并传递到磁头,然后磁头通过解码电路,把数据正常解析出来。
目前大部分的磁条卡业务应用,并没有把三个磁道的功能都使用上,主要还在是在1 - 2个磁道之间进行工作,所以对于大部分的MST使用场景,原来商户的基础设施并不需要进行修改或者升级就可以支持,但是有些支付场景下的基础设备,还是需要更新POS端的系统才可以顺利支持MST方式支付。
MST电磁发送电路对比磁头读卡电路本质是有一些相似的,只是前者需要把磁道的数据译码成差分曼切斯特F2F编码,能后再通过驱动电路带动线圈产生电磁场,从而把数据发送出去;而后者比较像一个相反的过程,即磁头通过接受磁卡中的磁化感应到磁头,磁头再把信号送回给到差分曼切斯特F2F解码器,解码器把最终的数据解出来。
F2F编码示意图
磁头读取磁卡中磁道的数据,是磁头在接触到磁卡中的磁道时或者MST信号时,使磁头上的磁路发生了磁通变化,并且根据电磁感应定律,磁头线圈产生感应电势,这个过程也就是磁数据转换成了电信号,磁头线圈两端产生电压信号,解码电路通过解码数据后,也就完成了磁卡信息的读出过程。
目前磁卡领域基本都是使用差分曼切斯特编码,可采用的编码方式有,调频制(FM Frequency Modulation)、调相制(PM Phase Modulation)和改进调频制式(MFM Modified Frequency Modulation)。其中改进调频制式MFM主要的目的,还是为了在不提高物理磁卡磁道的密度基础下,能提高两倍的记录数据密度量。
MST的应用与磁卡应用的主要区别就是,前者可以通过类似非接触到磁头的方式进行通讯,后者则要通过磁头接触磁卡磁道的方式进行数据交换,但是其本质的电磁原理还是一样的。MST的线圈靠近磁头时,与传统的POS的磁头线圈产生了互感,从而实现非接触的方式进行电磁通讯。
为方便解说清楚工作原理,这里我们以恩智浦的LPC5410x做为主机端为例来实现F2F编码数据格式,然后通过一颗双通道的H桥电机驱动芯片连接到线圈进行输出,这颗驱动芯片以德州仪器公司的DRV8833为例。
MST硬件连接示意框图
上图示例的主机端采用WLCSP49封装的LPC5410x,芯片非常小巧,只有3.3x3.3x0.54mm3,适合做到卡片封装中。
DRV8833中的AIN1、AIN2控制AOUT1、AOUT2的输出状态,BIN1、BIN2控制BOUT1、BOUT2的输出状态。本例中,AIN1&BIN1和AOUT1&BOUT1并联在一起,AIN2&BIN2和AOUT2&BOUT2并联在一起,它们的逻辑控制关系就会只有四种,如下表:
主机端LPC5410x通过控制GPIO管脚PIO0_25、PIO0_26和PIO0_27,实现控制A桥和B桥的能量输出,从而控制后端线圈电路输出电磁信号。
MST的线圈由DRV8833控制,当AIN1输出1且AIN2输出0时,线圈中的AOUT1&BOUT1被接通到高电平,而AOUT2&BOUT2则被接通到地,线圈中产生从AOUT1&BOUT1到AOUT2&BOUT2的电流,并产生对应方向的电磁场;反之,当AIN1输出0且AIN2输出1时,线圈中产生从AOUT2&BOUT2到AOUT1&BOUT1的电流,电势和电流改变了方向,于是也就产生反向的电磁场。
根据F2F制编码的标准,当MST发送二进制数据“0”时,需要改变一次线圈中的电流方向并保持一段时间不变,该段时间即为一个完整的位周期;当MST发送二进制数据“1”时,需要改变一次线圈中电流方向并维持1/2位周期的时间不变,然后再改变一次线圈中的电流方向并维持1/2位周期的时间不变。
正常在标准的银行卡磁卡刷卡时,产生的F2F编码数据信号的位周期在500us左右,考虑到MST是通过非接触感应的方式传递磁信号给到磁头,过程中有可能有些传输时间消耗,所以我们这里就暂时把位周期时间设定在400us内,那么如上面的逻辑控制框图,主机端LPC5410x的PIO0_25去控制AIN1和BIN1、PIO0_26去控制AIN2和BIN2,那么想要发送“101”的数据可以参考如下的代码设计:
#define LPC_IOCON_BASE 0x4001C000UL
#define LPC_GPIO_PORT_BASE 0x1C000000UL
#define __STATIC_INLINE static inline
#ifdef __cplusplus
#define __I volatile /*!< Defines 'read only' permissions */
#else
#define __I volatile const /*!< Defines 'read only' permissions */
#endif
#define __O volatile /*!< Defines 'write only' permissions */
#define __IO volatile /*!< Defines 'read / write' permissions
typedef unsigned int uint32_t;
/**
* @brief LPC5410X IO Configuration Unit register block structure
*/
typedef struct {
__IO uint32_t PIO[2][32];
/*!< LPC5410X IOCON Structure */
} LPC_IOCON_T;
/**
* @brief Array of IOCON pin definitions passed to Chip_IOCON_SetPinMuxing() must be in this format
*/
typedef struct {
uint32_t port : 8; /* Pin port */
uint32_t pin : 8; /* Pin number */
uint32_t modefunc : 16; /* Function and mode */
} PINMUX_GRP_T;
/**
* @brief GPIO port register block structure
*/
typedef struct {
/*!< GPIO_PORT Structure */
__IO uint8_t B[128][32];
/*!< Offset 0x0000: Byte pin registers ports 0 to n; pins PIOn_0 to PIOn_31 */
__IO uint32_t W[32][32];
/*!< Offset 0x1000: Word pin registers port 0 to n */
__IO uint32_t DIR[32];
/*!< Offset 0x2000: Direction registers port n */
__IO uint32_t MASK[32];
/*!< Offset 0x2080: Mask register port n */
__IO uint32_t PIN[32];
/*!< Offset 0x2100: Portpin register port n */
__IO uint32_t MPIN[32];
/*!< Offset 0x2180: Masked port register port n */
__IO uint32_t SET[32];
/*!< Offset 0x2200: Write: Set register for port n Read: output bits for port n */
__O uint32_t CLR[32];
/*!< Offset 0x2280: Clear port n */
__O uint32_t NOT[32];
/*!< Offset 0x2300: Toggle port n */
} LPC_GPIO_T;
/**
* IOCON function and mode selection definitions
* See the User Manual for specific modes and functions supported by the
* various LPC15XX pins.
*/
#define IOCON_FUNC0 0x0
/*!< Selects pin function 0 */
#define IOCON_FUNC1 0x1
/*!< Selects pin function 1 */
#define IOCON_FUNC2 0x2
/*!< Selects pin function 2 */
#define IOCON_FUNC3 0x3
/*!< Selects pin function 3 */
#define IOCON_FUNC4 0x4
/*!< Selects pin function 4 */
#define IOCON_FUNC5 0x5
/*!< Selects pin function 5 */
#define IOCON_FUNC6 0x6
/*!< Selects pin function 6 */
#define IOCON_FUNC7 0x7
/*!< Selects pin function 7 */
#define IOCON_MODE_INACT (0x0 << 3)
/*!< No addition pin function */
#define IOCON_MODE_PULLDOWN (0x1 << 3)
/*!< Selects pull-down function */
#define IOCON_MODE_PULLUP (0x2 << 3)
/*!< Selects pull-up function */
#define IOCON_MODE_REPEATER (0x3 << 3)
/*!< Selects pin repeater function */
#define IOCON_HYS_EN (0x1 << 5)
/*!< Enables hysteresis */
#define IOCON_GPIO_MODE (0x1 << 5)
/*!< GPIO Mode */
#define IOCON_I2C_SLEW (0x1 << 5)
/*!< I2C Slew Rate Control */
#define IOCON_INV_EN (0x1 << 6)
/*!< Enables invert function on input */
#define IOCON_ANALOG_EN (0x0 << 7)
/*!< Enables analog function by setting 0 to bit 7 */
#define IOCON_DIGITAL_EN (0x1 << 7)
/*!< Enables digital function by setting 1 to bit 7(default) */
#define IOCON_STDI2C_EN (0x1 << 8)
/*!< I2C standard mode/fast-mode */
#define IOCON_FASTI2C_EN (0x3 << 8)
/*!< I2C Fast-mode Plus and high-speed slave */
#define IOCON_INPFILT_OFF (0x1 << 8)
/*!< Input filter Off for GPIO pins */
#define IOCON_INPFILT_ON (0x0 << 8)
/*!< Input filter On for GPIO pins */
#define IOCON_OPENDRAIN_EN (0x1 << 10)
/*!< Enables open-drain function */
#define IOCON_S_MODE_0CLK (0x0 << 11)
/*!< Bypass input filter */
#define IOCON_S_MODE_1CLK (0x1 << 11)
/*!< Input pulses shorter than 1 filter clock are rejected */
#define IOCON_S_MODE_2CLK (0x2 << 11)
/*!< Input pulses shorter than 2 filter clock2 are rejected */
#define IOCON_S_MODE_3CLK (0x3 << 11)
/*!< Input pulses shorter than 3 filter clock2 are rejected */
#define IOCON_S_MODE(clks) ((clks) << 11)
/*!< Select clocks for digital input filter mode */
#define IOCON_CLKDIV(div) ((div) << 13)
/*!< Select peripheral clock divider for input filter sampling clock, 2^n, n=0-6 */
#define LPC_IOCON ((LPC_IOCON_T *) LPC_IOCON_BASE)
#define LPC_GPIO ((LPC_GPIO_T *) LPC_GPIO_PORT_BASE)
STATIC const PINMUX_GRP_T pinmuxing[] = {
{0, 25, (IOCON_FUNC0 | IOCON_MODE_PULLDOWN | IOCON_DIGITAL_EN)},
{0, 26, (IOCON_FUNC0 | IOCON_MODE_PULLDOWN | IOCON_DIGITAL_EN)},
{0, 27, (IOCON_FUNC0 | IOCON_MODE_PULLDOWN | IOCON_DIGITAL_EN)},
};
__STATIC_INLINE void Chip_IOCON_PinMuxSet(LPC_IOCON_T *pIOCON, uint8_t port, uint8_t pin, uint32_t modefunc)
{
pIOCON->PIO[port][pin] = modefunc;
}
__STATIC_INLINE void Chip_GPIO_WritePortBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t pin, bool setting)
{
pGPIO->B[port][pin] = setting;
}
/* Set all I/O Control pin muxing */
void Chip_IOCON_SetPinMuxing(LPC_IOCON_T *pIOCON, const PINMUX_GRP_T *pinArray, uint32_t arrayLength)
{
uint32_t ix;
for (ix = 0; ix < arrayLength; ix++ ) {
Chip_IOCON_PinMuxSet(pIOCON, pinArray[ix].port, pinArray[ix].pin, pinArray[ix].modefunc);
}
}
/* Set Direction for a GPIO port */
void Chip_GPIO_SetDir(LPC_GPIO_T *pGPIO, uint8_t portNum, uint32_t bitValuet)
{
pGPIO->DIR[portNum] ^= bitValue;
}
#define PORT_PIN_MST 0
#define PIN_AIN1_BIN1 25
#define PIN_AIN2_BIN2 26
#define PIN_NSLEEP 27
//参考程序入口
Chip_IOCON_SetPinMuxing(LPC_IOCON, pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T));
//初始化LPC5410,让PIO0_25、PIO0_26和PIO0_27三个管脚配置成GPIO的属性
Chip_GPIO_WritePortBit(LPC_GPIO, PORT_PIN_MST, PIN_NSLEEP,1);
//让DRV8833进入正常的工作模式
Chip_GPIO_WritePortBit(LPC_GPIO, PORT_PIN_MST, PIN_AIN1_BIN1,1);
Chip_GPIO_WritePortBit(LPC_GPIO, PORT_PIN_MST, PIN_AIN2_BIN2,0);
//先配置PIO0_25、PIO0_26为输出AIN1&BIN1和AIN2一高一低
usleep_mS(1);
//然后开始发送数据
//Sent 1,两次取反
Chip_GPIO_SetDir(LPC_GPIO, PORT_PIN_MST, 0x06000000);
//AIN1&BIN1 取反,AIN2&BIN2 取反
usleepy_uS(200);
Chip_GPIO_SetDir(LPC_GPIO, PORT_PIN_MST, 0x06000000);
//AIN1&BIN1 取反,AIN2&BIN2 取反
usleep_uS(200);
//Sent 0,取反保持
Chip_GPIO_SetDir(LPC_GPIO, PORT_PIN_MST, 0x06000000);
//AIN1&BIN1 取反,AIN2&BIN2 取反
usleep_uS(400);
//Sent 1,两次取反
Chip_GPIO_SetDir(LPC_GPIO, PORT_PIN_MST, 0x06000000);
//AIN1&BIN1 取反,AIN2&BIN2 取反
usleep_uS(200);
Chip_GPIO_SetDir(LPC_GPIO, PORT_PIN_MST, 0x06000000);
//AIN1&BIN1 取反,AIN2&BIN2 取反
usleep_uS(200);
Chip_GPIO_SetDir(LPC_GPIO, PORT_PIN_MST, 0x06000000);
//AIN1&BIN1 取反,AIN2&BIN2 取反
usleep_uS(200);
这是在嵌入式平台中的应用案例说明,在有些Android移动端的平台中AIN1&BIN1和AIN2&BIN2的管脚会连接到主机端支持安全访问中去,这样至少可以在kernel层面上,避免当系统获取ROOT权限后被恶意程序发送逻辑控制电平。
站长从王晓华先生处获得10本他本人签名的这本书,特意送给MCU加油站的粉丝们,供有需要的朋友学习参考。
请点击以下图片填写新书申请表格(截止时间为7月6日24时),在收到所有有效的申请之后,将由王晓华先生随机选出10位幸运者,我们将在7月15日之前为幸运者寄送一本书。
|
|