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;
        }
    }
}

 

posted @ 2015-03-11 10:12  阿青1987  阅读(603)  评论(0编辑  收藏  举报