由于串口通讯需要自己写代码进行测试,同时要轮询测试各波特率是否工作正常。按照网上的代码,运行后总是或多或少有一些问题,后来借鉴APUE中关于tty_raw代码部分进行修改,终于可以正常运行,通讯不丢数,不修改数据。
同时在测试数据位为5,6时发现结果不正确,然后与其它同事了解后,发现串口下数据位5bit代表只会发送一个字节5bit。而不会自己进行拆分然后重组,得到原来的数据。例如,发送0xff,数据位5时,收到0x1f,数据位6时,收到0x3f,数据位7时,收到0x7f,数据位8时,收到0xff。同时串口配置的关键代码向大家公开,供借鉴使用。
struct BaudRate{ int speed; int bitmap; }; struct BaudRate baudlist[] = { { 50, B50 }, { 75, B75 }, { 110, B110 }, { 134, B134 }, { 150, B150 }, { 200, B200 }, { 300, B300 }, { 600, B600 }, { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, { 4800, B4800 }, { 9600, B9600 }, { 19200, B19200 }, { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 }, { 230400, B230400 }, { 460800, B460800 }, { 500000, B500000 }, { 576000, B576000 }, { 921600, B921600 }, { 1000000, B1000000 }, { 1152000, B1152000 }, { 1500000, B1500000 }, { 2000000, B2000000 }, { 2500000, B2500000 }, { 3000000, B3000000 }, { 3500000, B3500000 }, { 4000000, B4000000 }, }; int comDatabits[] = { 5, 6, 7, 8 }; int comStopbits[] = { 1, 2 }; int comParity[] = { 'n', 'o', 'e' };
int set_com(int fd,int speed,int databits,int stopbits,int parity) { int i; struct termios opt; if( tcgetattr(fd ,&opt) != 0) { perror("get attr failed!\n"); return -1; } for (i = 0; i < sizeof(baudlist) / sizeof(baudlist[0]); i++) { struct BaudRate *rate = &baudlist[i]; if (speed == rate->speed) { cfsetispeed(&opt, rate->bitmap); cfsetospeed(&opt, rate->bitmap); break; } } // //修改控制模式,保证程序不会占用串口 // opt.c_cflag |= CLOCAL; // //修改控制模式,使得能够从串口中读取输入数据 // opt.c_cflag |= CREAD; opt.c_cflag &= ~CSIZE; switch (databits) { case 5: opt.c_cflag |= CS5; break; case 6: opt.c_cflag |= CS6; break; case 7: opt.c_cflag |= CS7; break; case 8: opt.c_cflag |= CS8; break; default: printf("Unsupported data size\n"); return -1; } switch(parity) { case 'n': case 'N': opt.c_cflag &= ~PARENB; opt.c_iflag &= ~INPCK; break; case 'o': case 'O': opt.c_cflag |= (PARODD|PARENB); opt.c_iflag |= INPCK; break; case 'e': case 'E': opt.c_cflag |= PARENB; opt.c_cflag &= ~PARODD; opt.c_iflag |= INPCK; break; default: printf("Unsupported parity\n"); return -1; } switch(stopbits) { case 1: opt.c_cflag &= ~CSTOPB; break; case 2: opt.c_cflag |= CSTOPB; break; default: printf("Unsupported stop bits\n"); return -1; } opt.c_iflag &= ~(IXON | IXOFF | IXANY | BRKINT | ICRNL | INPCK | ISTRIP); opt.c_lflag &= ~(ICANON | ECHO | ECHOE | IEXTEN | ISIG); opt.c_oflag &= ~OPOST; opt.c_cc[VTIME] = 100; opt.c_cc[VMIN] = 0; tcflush(fd, TCIOFLUSH); if (tcsetattr(fd, TCSANOW, &opt) != 0) { perror("set attr failed!\n"); return -1; } return 0; }