{背景}
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