zoukankan      html  css  js  c++  java
  • 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
    ");
            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
    ");
            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
    ");
            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
    ");
        } else {
            printf("Open Failure!
    ");
            return -1;
        }
    
        if (set_Parity(uart_fd, 8, 2, 'E') == FALSE) {
            printf("Set Parity Error
    ");
            return -2;
        } else {
            printf("parity set as 8,2,E
    ");
        }
    
        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!
    ");
        }
    }
    
    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("
    ");
    }
    
    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("
    Welcome to PSAM CARD tests
    
    ");
    
        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 != '
    ') {
                printf("
    ");
                printf("Input you select.
    ");
                printf("	=== Psam Test ===
    ");
                printf("	 a. pps to 115200
    ");
                printf("	 b. get_rand_number
    ");
                printf("	 c. get_psam_number
    ");
                printf("	 d. Test Rest ATR
    ");
                printf("	 f. set baudrate
    ");
            }
            choice = getchar();
    
            switch (choice) {
            case 'a': // pps cmd
                printf("pps selected.
    ");
                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
    ");
                break;
    
            case 'b':
                printf("get_rand_number selected.
    ");
                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.
    "); // 
                // select 3F00
                printf("1) select 3F00
    ");
                psam_send_cmd(uart_fd, cmd_select_3F00, 7);
                psam_get_cmd_response(uart_fd, 15);
                printf("
    ");
    
                // select 0015
                printf("2) select 0015
    ");
                psam_send_cmd(uart_fd, cmd_select_0015, 7);
                psam_get_cmd_response(uart_fd, 20);
                printf("
    ");
            
                // read psam number
                printf("3) get psam number
    ");
                psam_send_cmd(uart_fd, cmd_get_num, 5);
                psam_get_cmd_response(uart_fd, 20);
                printf("
    ");
                
                break;
    
            case 'd':
                psam_get_cmd_response(uart_fd, 15);
                break;
    
            case 'f': {
                if (choice != '
    ') {
                    printf("	 current speed is %d
    ", current_speed);
                    printf("
    ");
                    printf("	=== baudrate set ===
    ");
                    printf("	 1. 115200
    ");
                    printf("	 2. 38400
    ");
                    printf("	 3. 9600
    ");
                    printf("	 9. Exit
    ");
                    printf("
    ");
                }
    
                scanf("%d", &speed_choice);
                switch (speed_choice) {
                case 1: // 115200
                    current_speed = 115200;
                    set_speed(uart_fd, 115200);
                    printf("*** Current speed is 115200
    ");
                    break;
    
                case 2: // 38400
                    current_speed = 38400;
                    set_speed(uart_fd, 38400);
                    printf("*** Current speed is 38400
    ");
                    break;
    
                case 3: // 9600
                    current_speed = 9600;
                    set_speed(uart_fd, 9600);
                    printf("*** Current speed is 9600
    ");
                    break;
    
                case 9:
                    break;
                }
            }
                break;
            default:
                break;
            }
        }
    }
  • 相关阅读:
    HTML的BODY内标签介绍
    前端HTML基础和head部分
    pymysql模块
    数据库基础五
    数据库基础四
    数据库基础三
    数据库基础二
    数据库基础一
    洛谷P5055 可持久化文艺平衡树 (可持久化treap)
    BZOJ
  • 原文地址:https://www.cnblogs.com/aqing1987/p/4329092.html
Copyright © 2011-2022 走看看