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;

        }

    }

}

 

你可能感兴趣的:(连接)