#include #include #include #include #include #include #include #include #include "serial.h" #include "debug.h" int serial_band_convert(unsigned int baudrate) { switch (baudrate) { case 2400: return B2400; case 4800: return B4800; case 9600: return B9600; case 19200: return B19200; case 38400: return B38400; case 57600: return B57600; case 115200: return B115200; case 921600: return B921600; case 1152000: return B1152000; default: return B115200; } } int serial_attr_set(int fd, serial_attr_t * attr) { unsigned char databit = 0; unsigned char stopbit = 0; unsigned char parity = 0; unsigned char fctl = 0; int ret = -1; unsigned int baudrate = 0; struct termios termios_old; struct termios termios_new; memset(&termios_old, 0, sizeof(termios_old)); memset(&termios_new, 0, sizeof(termios_new)); //CHECK_SERIAL_PORT_FD; cfmakeraw(&termios_new); if (tcgetattr(fd, &termios_old) != 0) { perror("Setup Serial!\r\n"); return ret; } //baudrates baudrate = serial_band_convert(attr->baudrate); cfsetispeed(&termios_new, baudrate); cfsetospeed(&termios_new, baudrate); termios_new.c_cflag |= CLOCAL; termios_new.c_cflag |= CREAD; //flow control fctl = attr-> fctl; switch (fctl) { case 0: termios_new.c_cflag &= ~CRTSCTS; //no flow control break; case 1: termios_new.c_cflag |= CRTSCTS; //hardware flow control break; case 2: termios_new.c_iflag |= IXON | IXOFF | IXANY; //software flow control break; } //data bits termios_new.c_cflag &= ~CSIZE; //控制模式,屏蔽字符大小位 databit = attr->databit; switch (databit) { case 5: termios_new.c_cflag |= CS5; break; case 6: termios_new.c_cflag |= CS6; break; case 7: termios_new.c_cflag |= CS7; break; case 8: termios_new.c_cflag |= CS8; break; default: termios_new.c_cflag |= CS8; break; } //parity check parity = attr->parity; switch (parity) { case 0: //no parity check termios_new.c_cflag &= ~PARENB; break; case 1: //odd check termios_new.c_cflag |= PARENB; termios_new.c_cflag &= ~PARODD; break; case 2: //even check termios_new.c_cflag |= PARENB; termios_new.c_cflag |= PARODD; break; } //stop bits stopbit = attr->stopbit; if (stopbit == 2) { termios_new.c_cflag |= CSTOPB; } else if (stopbit == 1) { termios_new.c_cflag &= ~CSTOPB; } //other attributions default termios_new.c_oflag &= ~OPOST; termios_new.c_cc[VMIN] = 1; termios_new.c_cc[VTIME] = 1; tcflush(fd, TCIFLUSH); ret = tcsetattr(fd, TCSANOW, &termios_new); return ret; } int serial_open(const char * devname, int baudrate) { int fd; serial_attr_t attr; fd = open(devname, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd < 0) { LOG("Open SerialPort(%s) failed[error = %d, %s]!!!!!!!\n\n", devname, errno, strerror(errno)); return -1; } strcpy(attr.tty, devname); attr.baudrate = baudrate; serial_attr_set(fd, &attr); LOG("Open SerialPort(%s:%d) port success!!!\n", devname, baudrate); return fd; } #if 1 int serial_read(int fd, unsigned char * data, int len) { int ret = -1; fd_set fs_read; int maxfd = -1; //CHECK_SERIAL_PORT_FD; if (fd < 0) { LOG("error fd = %d\n", fd); return -1; } if (data == NULL || len <= 0) { LOG("Param Error, NULL == data || len <= 0.\n"); return -1; } //#if 0 FD_ZERO(&fs_read); FD_SET(fd, &fs_read); maxfd = fd + 1; struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 1000 * 1000; ret = select(maxfd, &fs_read, NULL, NULL, &tv); if (ret < 0) { LOG("select error[%d, %s]!!!\n", errno, strerror(errno)); return -1; } if (ret == 0) { LOG("Timeout......\n\n\n"); return -1; } //#endif ret = read(fd, data, len); if (ret < 0) { LOG("read error[%d, %s]\n", errno, strerror(errno)); return -1; } return ret; } #else int serial_read(int fd, unsigned char * data, int len) { int ret, fs_sel; fd_set fs_read; struct timeval time; FD_ZERO(&fs_read); FD_SET(fd, &fs_read); time.tv_sec = 1; time.tv_usec = 0; //1s //使用select实现串口的多路通信 fs_sel = select(fd + 1, &fs_read, NULL, NULL, &time); if(fs_sel) { ret = read(fd, data, len); printf("read len=%d\n", ret); print_raw_data(data, len); return ret; } return 0; // return read(fd, rcv_buf, rcv_len); } #endif #if 1 int serial_write(int fd, unsigned char * data, int len) { //CHECK_SERIAL_PORT_FD; if (fd < 0) { LOG("error fd = %d\n", fd); return -1; } if (NULL == data || len <= 0) { LOG("Param Error, NULL == data or len = %d.\n", len); return -1; } fd_set fs_write; FD_ZERO(&fs_write); FD_SET(fd, &fs_write); int maxfd = fd + 1; struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 1000 * 1000; int ret = select(maxfd, NULL, &fs_write, NULL, &tv); if (ret < 0) { LOG("select Error[errno = %d, %s]", errno, strerror(errno)); return -1; } else if (ret == 0) { LOG("Timeout!\n"); return -1; } if (FD_ISSET(fd, &fs_write)) { int pos = 0; while (len > 0) { ret = write(fd, data + pos, len); if (ret < 0) { LOG("write com[fd = %d] error[errno = %d, %s]\n", fd, errno, strerror(errno)); return -1; } len -= ret; pos += ret; } } return len; } #else int serial_write(int fd, unsigned char * data, int len) { int ret; print_raw_data(data, len); ret = write(fd, data, len); if (len == ret) { return 1; } else { tcflush(fd, TCOFLUSH); return 0; } // return write(fd, send_buf, data_len); } #endif void serial_close(int fd) { if (fd > 0) { close(fd); } }