#include "hx_serial.h" #include #include #include #include #include #include #include #include #include #include "logc/log.h" int by_serial_init(by_serial_t *serial_port, const char *dev_name) { serial_port->dev_name_len = strlen(dev_name); assert(0 < serial_port->dev_name_len); strcpy(serial_port->dev_name_str, dev_name); int fd; fd = open(serial_port->dev_name_str, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); if (fd < 0) { log_error("open uart device error"); return -1; } else { serial_port->fd = fd; by_serial_set_baudrate(serial_port, 115200); by_serial_set_parity(serial_port, 8, 1, 'N'); log_info("serial %s init successful", serial_port->dev_name_str); return 0; } } int by_serial_set_baudrate(by_serial_t *serial_port, int baudrate) { int index = 0; int status = 0; int speed_arr[] = { B115200, B38400, B19200, B9600, B4800, B2400, B1200}; int name_arr[] = { 115200, 38400, 19200, 9600, 4800, 2400, 1200}; struct termios Opt = {0}; tcgetattr(serial_port->fd, &Opt); for (index = 0; index < sizeof(speed_arr) / sizeof(int); index++) { if (baudrate == name_arr[index]) { /*设置前 flush*/ tcflush(serial_port->fd, TCIOFLUSH); cfsetispeed(&Opt, speed_arr[index]); cfsetospeed(&Opt, speed_arr[index]); /*tcsetattr(串口描述符,立即使用或者其他标示,指向 termios 的指针),通过 tcsetattr 函数把新的属性设置到串口上。*/ status = tcsetattr(serial_port->fd, TCSANOW, &Opt); if (0 != status) { log_error("tcsetattr COM error"); return -1; } /*设置后 flush*/ tcflush(serial_port->fd, TCIOFLUSH); return 0; } } return 0; } int by_serial_set_parity(by_serial_t *serial_port, int databits, int stopbits, char parity) { struct termios Opt = {0}; if (0 != tcgetattr(serial_port->fd, &Opt)) { log_error("tcgetattr COM error"); return -1; } Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/ Opt.c_oflag &= ~OPOST; /*Output*/ Opt.c_iflag &= ~ICRNL; // 禁止将输入的 CR 转换为 NL Opt.c_iflag &= ~(IXON); // 清 bit 位 关闭流控字符 /*设置数据位,取值为 7 或 8*/ Opt.c_cflag &= ~CSIZE; switch (databits) { case 7: Opt.c_cflag |= CS7; break; case 8: Opt.c_cflag |= CS8; break; default: log_error("Unsupported data size"); return -1; break; } /*设置停止位,取值为 1 或 2*/ switch (stopbits) { case 1: Opt.c_cflag &= ~CSTOPB; break; case 2: Opt.c_cflag |= CSTOPB; break; default: log_error("Unsupported stop bits"); return -1; break; } /*设置校验位,取值为 E,N,O,S*/ switch (parity) { case 'e': case 'E': { Opt.c_cflag |= PARENB; /*Enable parity*/ Opt.c_cflag &= ~PARODD; /*转换为偶效验*/ Opt.c_iflag |= INPCK; /*Disnable parity checking*/ } break; case 'n': case 'N': { Opt.c_cflag &= ~PARENB; /*Clear parity enable*/ Opt.c_iflag &= ~INPCK; /*Enable parity checking*/ } break; case 'o': case 'O': { Opt.c_cflag |= (PARODD | PARENB); /*设置为奇效验*/ Opt.c_iflag |= INPCK; /*Disnable parity checking*/ } break; case 's': /*as no parity*/ case 'S': /*as no parity*/ { Opt.c_cflag &= ~PARENB; Opt.c_cflag &= ~CSTOPB; } break; default: log_error("Unsupported parity\n"); return -1; break; } /*设置结构体输入校验位*/ if ('n' != parity) { Opt.c_iflag |= INPCK; } tcflush(serial_port->fd, TCIFLUSH); Opt.c_cc[VTIME] = 150; /*设置超时 15 秒*/ Opt.c_cc[VMIN] = 0; /*更新结构体并立即执行*/ if (0 != tcsetattr(serial_port->fd, TCSANOW, &Opt)) { log_error("tcsetattr COM error"); return -1; } return 0; } int by_serial_write(by_serial_t *serial_port, const char *buff, const int len) { int len_t; if (serial_port->fd < 0) { return -1; } len_t = write(serial_port->fd, buff, len); if (0 > len_t) { // log_error("write buff failed"); return -1; } else { // printf("write buff successful %d/%d\r\n", len_t, len); return 0; } } int by_serial_read(by_serial_t *serial_port, char *buff, const int len) { if (1 > by_serial_get_used_buffer_len(serial_port)) { return -1; } int len_t = -1; if (serial_port->fd < 0) { return -1; } len_t = read(serial_port->fd, buff, len); if (0 > len_t) { // log_error("read buff failed"); return -1; } else { // printf("read buff successful %d/%d\r\n", len_t, len); return len_t; } } int by_serial_get_used_buffer_len(by_serial_t *serial_port) { int used_len = 0; ioctl(serial_port->fd, FIONREAD, &used_len); return used_len; }