/* Includes ------------------------------------------------------------------*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* 标准C库头文件. */ #include #include #include #include #include #include #include #include /* 用户代码头文件. */ #include "serial.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)); cfmakeraw(&termios_new); if (tcgetattr(fd, &termios_old) != 0) { DBG(DBG_M_SERIAL, "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) { DBG(DBG_M_SERIAL, "Open SerialPort(%s) failed[error = %d, %s]!!!!!!!\r\n", devname, errno, strerror(errno)); return E_SYS_CALL; } strcpy(attr.tty, devname); attr.baudrate = baudrate; serial_attr_set(fd, &attr); DBG(DBG_M_SERIAL, "Open SerialPort(%s:%d) port success!!!\r\n", devname, baudrate); return fd; } int serial_read(int fd, unsigned char * data, int len) { int ret = -1; fd_set fs_read; int maxfd = -1; if (fd < 0 || data == NULL || len <= 0) { DBG(DBG_M_SERIAL, "Param Error, fd = %d or NULL == data or len <= 0.\r\n", fd); return E_ERROR; } 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) { DBG(DBG_M_SERIAL, "select error[%d, %s]!!!\r\n", errno, strerror(errno)); return E_SYS_CALL; } if (ret == 0) { DBG(DBG_M_SERIAL, "Timeout......\r\n"); return E_TIMEOUT; } ret = read(fd, data, len); if (ret < 0) { DBG(DBG_M_SERIAL, "read error[%d, %s]\r\n", errno, strerror(errno)); return E_SYS_CALL; } return ret; } int serial_write(int fd, unsigned char * data, int len) { if (fd < 0 || NULL == data || len <= 0) { DBG(DBG_M_SERIAL, "Param Error, fd = %d or NULL == data or len = %d.\r\n", fd, len); return E_BAD_PARAM; } 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) { DBG(DBG_M_SERIAL, "select Error[errno = %d, %s]\r\n", errno, strerror(errno)); return E_SYS_CALL; } else if (ret == 0) { DBG(DBG_M_SERIAL, "Timeout!\r\n"); return E_TIMEOUT; } if (FD_ISSET(fd, &fs_write)) { int pos = 0; while (len > 0) { ret = write(fd, data + pos, len); if (ret < 0) { DBG(DBG_M_SERIAL, "write com[fd = %d] error[errno = %d, %s]\r\n", fd, errno, strerror(errno)); return E_SYS_CALL; } len -= ret; pos += ret; } } return len; } void serial_close(int fd) { if (fd > 0) { close(fd); } }