I.Mx6 使用串口连接PSAM卡的注意事项

{背景}

1. 使用模拟方式与PSAM卡进行通信,对时序的要求非常严格,在自己的代码中一定要做好相关延时尤其是每个etu的时间

要测量准确。

2. 使用串口方式与PSAM卡直连,是硬件级的通信,写起来相对容易一些。

{遇到的问题}

1. 串口应用收不到PSAM卡的复位信息

2. 串口的TX 在RX 有数据时发出干扰数据

{解决方案}

1、问题一的解决方案

设置串口为8个数据位,2位停止位,偶校验位。

set_Parity(uart_fd, 8, 2, ‘E‘)

设置串口参数为原始模式,这样才能正确收到PSAM复位信息

options.c_lflag &= ~(ICANON); // config as original mode. 

2. 问题二的解决方案

设置串口参数关闭回显,这样TX 就不会再出现干扰信息。

options.c_lflag &= ~(ECHO | ECHONL | ISIG); // disable echo

{参考代码}

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <sys/time.h>

#define TRUE 1
#define FALSE -1

int speed_arr[] = { B230400, B115200, B38400, B19200, B9600, B4800, B2400,
B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = { 230400, 115200, 38400, 19200, 9600, 4800, 2400, 1200, 300,
        38400, 19200, 9600, 4800, 2400, 1200, 300, };

void set_speed(int fd, int speed)
{
    int i;
    int status;
    struct termios Opt;
    tcgetattr(fd, &Opt);

    for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
    {
        if (speed == name_arr[i]) {
            tcflush(fd, TCIOFLUSH);
            // set baudrate
            cfsetispeed(&Opt, speed_arr[i]);
            cfsetospeed(&Opt, speed_arr[i]);
            status = tcsetattr(fd, TCSANOW, &Opt);
            if (status != 0) {
                perror("tcsetattr fd1");
            }

            return;
        }
        tcflush(fd, TCIOFLUSH);
    }
}

/**
 *@brief  设置串口数据位,停止位和校验位
 *@param  fd     类型  int  打开的串口文件句柄
 *@param  databits 类型  int 数据位 取值为7或者8
 *@param  stopbits 类型  int 停止位 取值为1或者2
 *@param  parity  类型  int  奇偶校验位 取值 N, E, O, S
 */
int set_Parity(int fd, int databits, int stopbits, int parity)
{
    struct termios options;
    if (tcgetattr(fd, &options) != 0) {
        perror("SetupSerial 1");
        return (FALSE);
    }

    options.c_cflag &= ~CSIZE;
    switch (databits) {
    case 7:
        options.c_cflag |= CS7;
        break;

    case 8:
        options.c_cflag |= CS8;
        break;

    default:
        fprintf(stderr, "Unsupported data size\n");
        return FALSE;
    }

    switch (parity) {
    case ‘n‘:
    case ‘N‘:
        options.c_cflag &= ~PARENB; /* Clear parity enable */
        options.c_iflag &= ~INPCK; /* Enable parity checking */
        options.c_iflag &= ~(ICRNL | IGNCR);
        options.c_lflag &= ~(ICANON);
        break;

    case ‘o‘:
    case ‘O‘:
        options.c_cflag |= (PARODD | PARENB);  // 设置为奇校验位
        options.c_iflag |= INPCK; /* Disnable parity checking */
        break;

    case ‘e‘:
    case ‘E‘:
        options.c_cflag |= PARENB; // Enable parity check
        options.c_cflag &= ~PARODD; // config as even parity check
        options.c_iflag |= INPCK; // enable input parity check
        options.c_oflag &= ~OPOST; // output for raw mode
        options.c_lflag &= ~(ICANON); // config as original mode. MUST be configured.
        options.c_lflag &= ~(ECHO | ECHONL | ISIG); // disable echo
        break;

    case ‘S‘:
    case ‘s‘: /*as no parity*/
        options.c_cflag &= ~PARENB;
        options.c_cflag &= ~CSTOPB;
        break;

    default:
        fprintf(stderr, "Unsupported parity\n");
        return FALSE;
    }

    // set stop bits
    switch (stopbits) {
    case 1:
        options.c_cflag &= ~CSTOPB;
        break;

    case 2:
        options.c_cflag |= CSTOPB;
        break;

    default:
        fprintf(stderr, "Unsupported stop bits\n");
        return FALSE;
    }

    /* Set input parity option */
    if (parity != ‘n‘) {
        options.c_iflag |= INPCK;
    }

    //options.c_cc[VTIME] = 150; // 15 seconds
    options.c_cc[VTIME] = 50; // 5 seconds
    options.c_cc[VMIN] = 0;

    options.c_iflag &= ~(ICRNL | IXON);
    tcflush(fd, TCIFLUSH); /* Update the options and do it NOW */

    if (tcsetattr(fd, TCSANOW, &options) != 0) {
        perror("SetupSerial 3");
        return FALSE;
    }
    return TRUE;
}

int OpenDev(char *Dev)
{
    int fd = open(Dev, O_RDWR);
    if (-1 == fd) {
        perror("Can‘t Open Serial Port");
        return -1;
    } else {
        return fd;
    }
}

int CloseDev(int Dev)
{
    int fd = close(Dev);

    if (-1 == fd) {
        perror("Can‘t close Serial Port");
        return -1;
    } else {
        return fd;
    }
}

//
// input: e.g. "/dev/ttymxc3"
// output: valid uart_fd or -1 for open error, -2 for set parity error
//
int uart_cfg(char *which_uart, int speed)
{
    int uart_fd;

    if (which_uart == NULL) {
        perror("input parameter invalid.");
    }

    uart_fd = OpenDev(which_uart);
    if (uart_fd > 0) {
        set_speed(uart_fd, speed);
        printf("open success, 9600\n");
    } else {
        printf("Open Failure!\n");
        return -1;
    }

    if (set_Parity(uart_fd, 8, 2, ‘E‘) == FALSE) {
        printf("Set Parity Error\n");
        return -2;
    } else {
        printf("parity set as 8,2,E\n");
    }

    return uart_fd;
}

void psam_send_cmd(int fd, unsigned char *cmd_buf, unsigned int cmd_len) {
    if (cmd_buf == NULL || cmd_len == 0 || fd < 0) {
        perror("Invalid parameter.");
    }

    if (write(fd, cmd_buf, cmd_len) != cmd_len) {
        printf("send psam cmd failed!\n");
    }
}

void psam_get_cmd_response(int fd, int res_len) {
    int i = 0;
    int read_byte = 0;
    unsigned char res = 0;

    for (i = 0; i < res_len; i++) {
        read_byte = read(fd, &res, 1);
        if (read_byte > 0) {
            printf("%2x ", res);
        } else {
            break;
        }
    }
    printf("\n");
}

int main(int argc, char **argv)
{
    int nread = 0;
    int uart_fd = 0;

    // open uart3
    int current_speed = 9600;
    char *dev = "/dev/ttymxc3";
    uart_fd = uart_cfg(dev, current_speed);
    if (uart_fd < 0) {
        perror("uart cfg error.");
        exit(1);
    }

    printf("\nWelcome to PSAM CARD tests\n\n");

    unsigned char cmd_pps[4] = { 0xFF, 0x10, 0x95, 0x7A };
    unsigned char cmd_get_rand[5] = { 0x00, 0x84, 0x00, 0x00, 0x08 };
    unsigned char cmd_select_3F00[7] = { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 };
    unsigned char cmd_select_0015[7] = { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x00, 0x15 };
    unsigned char cmd_get_num[5] = { 0x00, 0xB0, 0x96, 0x00, 0x06 };
    unsigned char res = 0x00;

    int choice = 0;
    int speed_choice = 0;
    while (1)
    {
        if (choice != ‘\n‘) {
            printf("\n");
            printf("Input you select.\n");
            printf("\t=== Psam Test ===\n");
            printf("\t a. pps to 115200\n");
            printf("\t b. get_rand_number\n");
            printf("\t c. get_psam_number\n");
            printf("\t d. Test Rest ATR\n");
            printf("\t f. set baudrate\n");
        }
        choice = getchar();

        switch (choice) {
        case ‘a‘: // pps cmd
            printf("pps selected.\n");
            psam_send_cmd(uart_fd, cmd_pps, 4);
            psam_get_cmd_response(uart_fd, 19);
            set_speed(uart_fd, 115200);
            printf("*** Current speed is 115200\n");
            break;

        case ‘b‘:
            printf("get_rand_number selected.\n");
            psam_send_cmd(uart_fd, cmd_get_rand, 5);
            psam_get_cmd_response(uart_fd, 11);
            break;

        case ‘c‘: // attention: if cmd length larger than 5 bytes, send 5 bytes first, __FIXME__
            printf("get_psam_number selected.\n"); //
            // select 3F00
            printf("1) select 3F00\n");
            psam_send_cmd(uart_fd, cmd_select_3F00, 7);
            psam_get_cmd_response(uart_fd, 15);
            printf("\n");

            // select 0015
            printf("2) select 0015\n");
            psam_send_cmd(uart_fd, cmd_select_0015, 7);
            psam_get_cmd_response(uart_fd, 20);
            printf("\n");

            // read psam number
            printf("3) get psam number\n");
            psam_send_cmd(uart_fd, cmd_get_num, 5);
            psam_get_cmd_response(uart_fd, 20);
            printf("\n");

            break;

        case ‘d‘:
            psam_get_cmd_response(uart_fd, 15);
            break;

        case ‘f‘: {
            if (choice != ‘\n‘) {
                printf("\t current speed is %d\n", current_speed);
                printf("\n");
                printf("\t=== baudrate set ===\n");
                printf("\t 1. 115200\n");
                printf("\t 2. 38400\n");
                printf("\t 3. 9600\n");
                printf("\t 9. Exit\n");
                printf("\n");
            }

            scanf("%d", &speed_choice);
            switch (speed_choice) {
            case 1: // 115200
                current_speed = 115200;
                set_speed(uart_fd, 115200);
                printf("*** Current speed is 115200\n");
                break;

            case 2: // 38400
                current_speed = 38400;
                set_speed(uart_fd, 38400);
                printf("*** Current speed is 38400\n");
                break;

            case 3: // 9600
                current_speed = 9600;
                set_speed(uart_fd, 9600);
                printf("*** Current speed is 9600\n");
                break;

            case 9:
                break;
            }
        }
            break;
        default:
            break;
        }
    }
}
时间: 2024-11-05 00:12:03

I.Mx6 使用串口连接PSAM卡的注意事项的相关文章

社保系列7——PSAM卡

PSAM卡用于商户POS.网点终端.直联终端等端末设备上,负责机具的安全控管.PSAM卡具有一定的通用性.经过个人化处理的PSAM卡能在不同的机具上使用. PSAM卡支持多级发卡的机制,各级发卡方在卡片主控密钥和应用主控密钥的控制下创建文件和装载密钥. 1. 文件结构 社会保障DES算法环境: FID=3F00,AID=7378312E73682EC9E7BBE1B1A3D5CF:FID = DF01,AID = D15600000590 社会保障SSF33算法环境: FID=DDF1,AID=

PSAM卡

PSAM卡 终端安全控制模块,符合<中国金融集成电路(IC卡)PSAM卡规范>, 包括普通PSAM卡和高速PSAM卡. PSAM符合以下标准及规范: 识别卡,带触点的集成电路卡标准 <ISO/IEC 7816-1/2/3/4> <中国人民银行PSAM卡规范> PSAM具有以下主要特征: 支持一卡多应用,各应用之间相互独立(多应用.防火墙功能). 支持多种文件类型 包括二进制文件,定长记录文件,变长记录文件,循环文件,钱包文件 . 在通讯过程中支持多种安全保护机制(信息的

012开发板串口连接

步骤一:连线 将开发板和PC机通过USB转串口线连接起来: 步骤二:安装USB转串口驱动 一般买板子时都会自带驱动,如果自带的驱动不能安装,遇到问题,可以网上搜索别人的经验: 自己安装CH340-USB转串口驱动CH341SER时出现了问题,明明显示驱动安装成功: 但是,在设备管理器中,该串口前面还是有黄色的叹号: 后来,在网上搜索之后,找到好心人分享的经验:http://blog.csdn.net/gsj0791/article/details/17664861 下载并且安装了PL2303_P

IC卡、M1卡、CPU卡、SAM卡、PSAM卡的联系与区别

一. 技术方面(非接触式IC卡)  1. 逻辑加密卡又叫存储卡,卡内的集成电路具有加密逻辑和EEPROM(电可擦除可编程只读存储器).  2. CPU卡又叫智能卡,卡内的集成电路包括中央处理器(CPU).EEPROM.随机存储器(ROM).以及固化在只读存储器(ROM)中的片内操作系统(COS),有的卡内芯片还集成了加密运算协处理器以提高安全性和工作速度,使其技术指标远远高于逻辑加密卡. 3. CPU卡由于具有微处理功能,使得在交易速度以及数据干扰方面远远高于逻辑加密卡,且允许多张卡片同时操作,

PSAM卡与CPU(用户卡)的操作过程

最近我一直在研究关于通过国密PSAM卡作为安全模块来读写cpu(用户卡)的问题 其实,两者都是卡片,或者说都是从设备.它们之间是无法相互访问的. 实际上,PSAM 卡是作为秘密密钥的载体,专门执行加密和数字签名等任务. 从应用的角度来看,终端设备比如说 ATM 机,我们可以把他看作包含 PSAM 才构成整体.而用户卡,对 ATM 机来说,则是外部设备.当需要对用户卡片进行操作的时候,实际上终端设备是交替地访问用户卡和 PSAM,按协议流程来完成安全协议规定的操作. 比如说外部认证,是要让卡片确认

常见存储的串口连接管理方法

各大存储厂商的存储大多有一个COM接口,作为存储工程师提供一些重要配置的接口,COM接口的功能非常强大,可以直接与设备连接,实现对设备的配置,调试,数据传输等一系列操作.本文我们主要讲解通过COM口对设备IP进行管理与配置.下面以常见IBM的DS4700存储和戴尔MD3200存储为例,讲解一下通过COM接口管理IP的步骤. DS4700串口管理IP配置 1.  串口线(console线)连接,COM线连接存储,其另一端是公头的9针接口,需要一条9针母头的接口转USB接口的COM线,连接到管理电脑

没有鼠标,没有键盘,没有显示器,没有网络,仅通过串口连接控制树莓派

准备 树莓派开发板 (点此购买) (已刷入官方Raspbian系统) USB转串口板 (点此购买) 杜邦线 (4根) 连线 串口板 树莓派 -------------------- VCC +5V(非必须) RX TXD(GPIO15) TX RXD(GPIO14) GND Ground 树莓派引脚分布图 (以40PIN GPIO为例,兼容26PIN GPIO) 串口终端软件安装与连接 [Ubuntu Linux环境下]  1. 安装ckermit sudo apt-get install ck

树莓派zero 使用usb串口连接

使用minicom连接bash$ lsusbBus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hubBus 001 Device 004: ID 04f2:b5c0 Chicony Electronics Co., LtdBus 001 Device 003: ID 0cf3:e500 Atheros Communications, Inc.Bus 001 Device 014: ID 0525:a4a7 Netchip Tec

RS323串口连接仪器,接收仪器信息

SerialPort sp1 = new SerialPort(); getBloodPressur(); public void getBloodPressur() { try { string[] str = SerialPort.GetPortNames(); if (str == null) { MessageBox.Show("仪器未连接,请确认连接是否正常!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.E