请选择 进入手机版 | 继续访问电脑版
查看: 1139|回复: 0

基于LPC5410x的MST磁传输的软硬件实现

[复制链接]
  • TA的每日心情
    开心
    前天 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3296

    主题

    6541

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    31903
    最后登录
    2024-3-28
    发表于 2019-7-2 08:48:13 | 显示全部楼层 |阅读模式
    本文的内容来自恩智浦专家王晓华的这本专著——《RCC、MST和NFC标准及技术应用》,这部分内容只是安全的移动支付体系中很小的一部分,希望了解更多移动支付的技术,请阅读这本被众多专家推荐的专著。
    读完本文者将有幸获得具有王晓华先生亲笔签名的这本书。
    601.png
    磁安全传输(MST)是一种通过发出磁信号,模拟传统的磁条卡的技术。其应用目标是把现有磁条卡的一些业务,除现有大量市场存量的银行磁条卡外,还有积分卡、优惠券、会员卡等集成到支持MST的智能设备中。


    MST的电路原理和实现过程,本质上和磁头去读磁条卡的磁道原理是一样的。磁条卡需要通过接触的方式,通过刷卡动作,使卡片的磁力线传导至磁头上去,从而把数据读回来;而MST则是通过线圈产生变化的磁力线并传递到磁头,然后磁头通过解码电路,把数据正常解析出来。


    目前大部分的磁条卡业务应用,并没有把三个磁道的功能都使用上,主要还在是在1 - 2个磁道之间进行工作,所以对于大部分的MST使用场景,原来商户的基础设施并不需要进行修改或者升级就可以支持,但是有些支付场景下的基础设备,还是需要更新POS端的系统才可以顺利支持MST方式支付。



    MST电磁发送电路对比磁头读卡电路本质是有一些相似的,只是前者需要把磁道的数据译码成差分曼切斯特F2F编码,能后再通过驱动电路带动线圈产生电磁场,从而把数据发送出去;而后者比较像一个相反的过程,即磁头通过接受磁卡中的磁化感应到磁头,磁头再把信号送回给到差分曼切斯特F2F解码器,解码器把最终的数据解出来。
    602.png
    F2F编码示意图


    磁头读取磁卡中磁道的数据,是磁头在接触到磁卡中的磁道时或者MST信号时,使磁头上的磁路发生了磁通变化,并且根据电磁感应定律,磁头线圈产生感应电势,这个过程也就是磁数据转换成了电信号,磁头线圈两端产生电压信号,解码电路通过解码数据后,也就完成了磁卡信息的读出过程。


    目前磁卡领域基本都是使用差分曼切斯特编码,可采用的编码方式有,调频制(FM Frequency Modulation)、调相制(PM Phase Modulation)和改进调频制式(MFM Modified Frequency Modulation)。其中改进调频制式MFM主要的目的,还是为了在不提高物理磁卡磁道的密度基础下,能提高两倍的记录数据密度量。


    MST的应用与磁卡应用的主要区别就是,前者可以通过类似非接触到磁头的方式进行通讯,后者则要通过磁头接触磁卡磁道的方式进行数据交换,但是其本质的电磁原理还是一样的。MST的线圈靠近磁头时,与传统的POS的磁头线圈产生了互感,从而实现非接触的方式进行电磁通讯。



    为方便解说清楚工作原理,这里我们以恩智浦的LPC5410x做为主机端为例来实现F2F编码数据格式,然后通过一颗双通道的H桥电机驱动芯片连接到线圈进行输出,这颗驱动芯片以德州仪器公司的DRV8833为例。
    603.png
    MST硬件连接示意框图


    上图示例的主机端采用WLCSP49封装的LPC5410x,芯片非常小巧,只有3.3x3.3x0.54mm3,适合做到卡片封装中。



    DRV8833中的AIN1、AIN2控制AOUT1、AOUT2的输出状态,BIN1、BIN2控制BOUT1、BOUT2的输出状态。本例中,AIN1&BIN1和AOUT1&BOUT1并联在一起,AIN2&BIN2和AOUT2&BOUT2并联在一起,它们的逻辑控制关系就会只有四种,如下表:
    604.png
    主机端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日之前为幸运者寄送一本书。
    605.png
    606.png
    607.png


    作者:王晓华   文章出处:恩智浦MCU加油站


    签到签到
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-3-28 18:17 , Processed in 0.130146 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表