diff --git a/src/jlinux_uart.cpp b/src/jlinux_uart.cpp new file mode 100644 index 0000000..6050236 --- /dev/null +++ b/src/jlinux_uart.cpp @@ -0,0 +1,313 @@ +/*********************************************************************** + * @file jctrl_uart.cpp + JCTRL_UART + * @brief header file + * @history + * Date Version Author description + * ========== ======= ========= ======================================= + * 2022-07-21 V1.0 Lucky,lukai@jovision.com Create + * + * @Copyright (C) 2022 Jovision Technology Co., Ltd. +***********************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jlinux_uart.h" + +struct _uart_ctx{ + int fd; +}; + +int _get_baudrate(int nBaud) +{ + switch(nBaud) + { + case 1200: + return B1200; //注:B1200为系统定义 + 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; + default: + return B2400; + } +} + + +juart_hdl_t juart_open(const char *name){ + juart_hdl_t uart = new _uart_ctx; + uart->fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY | O_EXCL|O_SYNC); + return uart; +} +int juart_close(juart_hdl_t uart){ + if(uart->fd>0) + close(uart->fd); + uart->fd = 0; + return 0; +} +int juart_get_fd(juart_hdl_t uart){ + return uart->fd; +} +int juart_set_attr(juart_hdl_t uart, JUartAttr_t *attr){ + if (uart->fd <= 0) + { + printf("jv_uart_recv_ex fd error\n"); + return -1; + } + struct termios newtio, oldtio; + memset(&oldtio, 0, sizeof(oldtio)); + /* save the old serial port configuration */ + if (tcgetattr(uart->fd, &oldtio) != 0) { + perror("set_port/tcgetattr"); + return -1; + } + memset(&newtio, 0, sizeof(newtio)); + //设置波特率 + int nBaud = _get_baudrate(attr->baudrate); + switch (nBaud) + { + case B300: + case B1200: + case B2400: + case B4800: + case B9600: + case B19200: + case B38400: + case B57600: + case B115200: + cfsetospeed(&newtio, nBaud); + cfsetispeed(&newtio, nBaud); + break; + default: + printf("jv_uart_set_attr:Unsupported baudrate!\n"); + return -1; + } + /* ignore modem control lines and enable receiver */ + newtio.c_cflag |= CLOCAL | CREAD; + newtio.c_cflag &= ~CSIZE; + /* set character size */ + switch (attr->datawidth) { + case 5: + newtio.c_cflag |= CS5; + break; + case 6: + newtio.c_cflag |= CS6; + break; + case 7: + newtio.c_cflag |= CS7; + break; + case 8: + default: + newtio.c_cflag |= CS8; + break; + } + /* set the stop bits */ + switch (attr->stopbit) { + default: + case 1: + newtio.c_cflag &= ~CSTOPB; + break; + case 2: + newtio.c_cflag |= CSTOPB; + break; + } + /* set the parity */ + switch (attr->parity) { + case 'o': + case 'O': + case 1: + newtio.c_cflag |= PARENB; + newtio.c_cflag |= PARODD; + newtio.c_iflag |= INPCK; + break; + case 'e': + case 'E': + case 2: + newtio.c_cflag |= PARENB; + newtio.c_cflag &= ~PARODD; + newtio.c_iflag |= INPCK; + break; + case 'n': + case 'N': + case 0: + default: + newtio.c_cflag &= ~PARENB; + newtio.c_iflag &= ~INPCK; + break; + } + /* Raw input */ + newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + /* Software flow control is disabled */ + newtio.c_iflag &= ~(IXON | IXOFF | IXANY); + /* Raw ouput */ + newtio.c_oflag &=~ OPOST; + /* set timeout in deciseconds for non-canonical read */ + newtio.c_cc[VTIME] = 0; + /* set minimum number of characters for non-canonical read */ + newtio.c_cc[VMIN] = 0; + /* flushes data received but not read */ + tcflush(uart->fd, TCIFLUSH); + /* set the parameters associated with the terminal from + the termios structure and the change occurs immediately */ + if ((tcsetattr(uart->fd, TCSANOW, &newtio)) != 0) { + perror("set_port/tcsetattr"); + return -1; + } + return 0; +} +int juart_send(juart_hdl_t uart, char *data, int len){ + if (uart->fd > 0) + { + int ret = write(uart->fd, data, len); + if (ret == len) + return 0; + } + return -1; +} +int _modbus_rtu_select(juart_hdl_t uart, struct timeval *tv) +{ + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(uart->fd, &rfds); + int s_rc; + while ((s_rc = select(uart->fd+1, &rfds, NULL, NULL, tv)) == -1) { + if (errno == EINTR) { + fprintf(stderr, "A non blocked signal was caught\n"); + /* Necessary after an error */ + FD_ZERO(&rfds); + FD_SET(uart->fd, &rfds); + } else { + return -1; + } + } + if (s_rc == 0) { + /* Timeout */ + errno = ETIMEDOUT; + return -1; + } + return s_rc; +} +int juart_recv(juart_hdl_t uart, char *data, int len, int timeout){ + if (uart->fd > 0) + { + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = timeout*1000; + if(_modbus_rtu_select(uart, &tv) > 0){ + return read(uart->fd, data, len); + } + return -1; + }else{ + usleep(timeout*1000); + } + return -1; + +} + + +/** + *@brief 接收串口数据扩展接口,从收到start开始接收,到收到stop返回 + *@param handle 句柄 + *@param data 接收数据缓存 + *@param len 缓存大小 + *@param start 数据头标志:前nstart个字节 + *@param nstart 数据头字节数 + *@param stop 数据截止标志:后nstop个字节 + *@param nstop 数据截止标志的字节数 + */ +extern "C" int juart_recv_ex(juart_hdl_t handle, char *data, int len, char *start, int nstart, char *stop, int nstop, int timeout); +int juart_recv_ex(juart_hdl_t uart, char *data, int len, char *start, int nstart, char *stop, int nstop, int timeout){ + if (uart->fd <= 0) + { + printf("jv_uart_recv_ex fd error\n"); + return -1; + } + int offset = 0; + int offset_end = 0; + int bytes_read = 0; + while (1) + { + bytes_read = read(uart->fd, &data[offset], 1); + if (bytes_read == 1 && offset < nstart && data[offset] == start[offset]) + { + offset++; + } + if (offset == nstart) + break; + if (bytes_read < 1) + usleep(0); + } + while (offset < len) + { + if (data[offset] == stop[offset_end]) + { + offset_end++; + } + if (offset_end == nstop) + break; + bytes_read = read(uart->fd, &data[offset], 1); + if (bytes_read == 1) + { + offset++; + } + else + { + usleep(0); + } + } + return offset; +} + +/** + *@brief 设置rs485模式 + *@param handle 句柄 + *@param mode 0:发送后立刻置为接收状态;非0:发送后保持发送状态 + *@return 0 成功 + */ +int juart_set_rs485(juart_hdl_t handle, int mode) +{ + struct serial_rs485 rs485; + if (ioctl(handle->fd, TIOCGRS485, &rs485) == -1) + { + printf("TIOCGRS485 ioctl error.\n"); + return -1; + } + rs485.flags |= SER_RS485_ENABLED; + if (mode == 0) + { + rs485.flags &= ~SER_RS485_RTS_ON_SEND; + rs485.flags |= SER_RS485_RTS_AFTER_SEND; + } + else + { + rs485.flags |= SER_RS485_RTS_ON_SEND; + rs485.flags &= ~SER_RS485_RTS_AFTER_SEND; + } + rs485.delay_rts_before_send = 0; + rs485.delay_rts_after_send = 0; + if (ioctl(handle->fd, TIOCSRS485, &rs485) == -1) + { + printf("TIOCSRS485 ioctrl error.\n"); + return -1; + } + return 0; +} \ No newline at end of file