//--------------------------------------------------------------------- #include /*标准输入输出定义*/ #include /*标准函数库定义*/ #include #include /*Unix 标准函数定义*/ #include #include //--------------------------------------------------------------------- #include /*PPSIX 终端控制定义*/ #include /*文件控制定义*/ #include /*Unix 标准函数定义*/ #include #include #include "uart_driver.h" Uart_Driver::Uart_Driver(QObject *parent) : QThread(parent) { } //--------------------------------------------------------------------- /** *@brief 设置串口通信速率 *@param fd 类型 int 打开串口的文件句柄 *@param speed 类型 int 串口速度 *@return void */ //--------------------------------------------------------------------- //--------------------------------------------------------------------- int speed_arr[] = { B115200, B57600, B38400, B19200, B9600}; int name_arr[] = { 115200, 57600, 38400, 19200, 9600}; void Uart_Driver::set_speed(int fd, int speed) { int status; struct termios Opt; tcgetattr(fd, &Opt); for ( unsigned int i= 0; i < sizeof(speed_arr) / sizeof(int); i++) { if(speed == name_arr[i]) { tcflush(fd, TCIOFLUSH); cfsetispeed(&Opt, speed_arr[i]); cfsetospeed(&Opt, speed_arr[i]); status = tcsetattr(fd, TCSANOW, &Opt); if(status != 0) { perror("tcsetattr fd1"); return; } tcflush(fd,TCIOFLUSH); } } } //--------------------------------------------------------------------- /** *@brief 设置串口数据位,停止位和效验位 *@param fd 类型 int 打开的串口文件句柄 *@param databits 类型 int 数据位 取值 为 7 或者8 *@param stopbits 类型 int 停止位 取值为 1 或者2 *@param parity 类型 int 效验类型 取值为N,E,O,,S */ //--------------------------------------------------------------------- int Uart_Driver::set_Parity(int fd,int databits,int stopbits,int parity) { struct termios options; if(tcgetattr(fd, &options) != 0) { perror("SetupSerial 1"); return(-1); } //--------------- 二进制传输模式 ------------------------- options.c_iflag = 0; options.c_oflag = 0; //------------------------------------------------------ options.c_cflag &= ~CSIZE; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);/*Input*/ options.c_oflag &= ~OPOST;/*Output*/ switch (databits) /*设置数据位数*/ { case 7: options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: fprintf(stderr,"Unsupported data size\n"); return (-1); } switch (parity) { case 'n': case 'N': options.c_cflag &= ~PARENB; /* Clear parity enable */ options.c_iflag &= ~INPCK; /* Enable parity checking */ break; case 'o': case 'O': options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'e': case 'E': options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD; /* 转换为偶效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'S': case 's': /*as no parity*/ options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; break; default: fprintf(stderr,"Unsupported parity\n"); return (-1); } /* 设置停止位*/ switch (stopbits) { case 1: options.c_cflag &= ~CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break; default: fprintf(stderr,"Unsupported stop bits\n"); return (-1); } /* Set input parity option */ if (parity != 'n') options.c_iflag |= INPCK; tcflush(fd, TCIFLUSH); options.c_cc[VTIME] = 0; /* 0.1S */ options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ if (tcsetattr(fd,TCSANOW,&options) != 0) { perror("SetupSerial 3"); return (-1); } return (0); } //--------------------------------------------------------------------- int Uart_Driver::OpenDev(const char *Dev) { FD = open(Dev, O_RDWR|O_NOCTTY|O_NDELAY); return FD; } //--------------------------------------------------------------------- void Uart_Driver::SetDevAttr(int bitrate, char bitlen, char stopbitlen, char checktype) { if(FD < 0) return; set_speed(FD, bitrate); if(set_Parity(FD, bitlen, stopbitlen, checktype) < 0) { qDebug("Set Parity Error\n"); } if(fcntl(FD, F_SETFL, FNDELAY) < 0)//非阻塞,覆盖前面open的属性 { qDebug("fcntl failed\n"); } } //--------------------------------------------------------------------- int Uart_Driver::WriteDev(void *buf, int len) { if(FD < 0) return 0; return write(FD, (char *)buf, len); } //--------------------------------------------------------------------- int Uart_Driver::ReadDev(void *buf, int len) { if(FD < 0) return 0; char *pbuff = (char *)buf; return (read(FD, pbuff, len)); } //--------------------------------------------------------------------- //--------------------------------------------------------------------- int Uart_Driver::ReadData(void *buf, const int len, const int timeout_ms) { quint16 rx_len = 0; quint16 rx_time_out = 0; quint8 *p_rxdata = (quint8 *)buf; quint8 rx_databuff[512] = {0}; quint16 bytes = 0; int timeout_5ms = timeout_ms/5; while(1) { ioctl(FD, FIONREAD, &bytes); //确认字节数 if(bytes > 512){ bytes = 512; } if(bytes > 0){ int rlen = ReadDev(&rx_databuff, bytes); if(rlen > 0){ for(int i=0;i0 && rx_time_out>40) //收到了部分字节后,字节之间超时 x*5ms { qDebug("rx_len = %d",rx_len); /* qDebug("******* 5 ********"); for(int n=0;n<5;n++){ qDebug("0x%2X",rx_databuff[n]); } */ return rx_len; } if(rx_time_out > timeout_5ms) //接收超时 timeout_5ms * 5ms { return CommRxError; } } if(rx_len >= len){ return CommOK; } rx_time_out++; msleep(5); } } void Uart_Driver::ClearRxBuff(void) { int bytes = 0; int rxlen = 0; char tmp[64] = {0}; while(1) { ioctl(FD, FIONREAD, &bytes); //确认字节数 if(bytes > 0){ rxlen = ReadDev(tmp, 64); if(rxlen>0) continue; else return; } else return; } } int Uart_Driver::ModBusRead( const quint8 device_addr,const quint16 data_addr,const quint16 read_data_num, void *read_data_buf, const quint16 timeout_ms) { int res = CommOK; quint8 txData[16] = {0}; quint8 rxData[264] = {0}; txData[0] = device_addr; txData[1] = FUNC_CODE_READ; txData[2] = data_addr/256; txData[3] = data_addr%256; txData[4] = read_data_num/256; txData[5] = read_data_num%256; unsigned short crc = CRC16::CalModbusCRC16(txData,6); txData[6] = (quint8)(crc>>8); txData[7] = (quint8)crc; const quint16 tx_data_len = 8; quint16 rx_data_len = 0; /* if(device_addr>1){ for(int n=0;n<8;n++){ qDebug("0x%02X",txData[n]); } } */ ClearRxBuff(); if(tx_data_len != WriteDev(txData, tx_data_len)) res = CommTxError; rx_data_len = read_data_num*2+5; if(rx_data_len>264) rx_data_len = 264; if(CommOK == res) { res = ReadData(rxData, rx_data_len, timeout_ms); } if(CommOK == res) { crc = rxData[rx_data_len-2]; crc = (crc<<8) + rxData[rx_data_len-1]; if(crc == CRC16::CalModbusCRC16(rxData, rx_data_len-2)) { if(NULL != read_data_buf) { quint8 *pRecvData = (quint8 *)read_data_buf; for (quint8 i = 3; i48) wrdatanum = 48; quint16 lenth = 0; txData[lenth++] = device_addr; txData[lenth++] = FUNC_CODE_MULTI_WRITE; //多点写 txData[lenth++] = data_addr/256; txData[lenth++] = data_addr%256; txData[lenth++] = wrdatanum/256; txData[lenth++] = wrdatanum%256; txData[lenth++] = wrdatanum*2; for(int i=0;i>8); txData[lenth++] = (quint8)crc; /* qDebug("******* 4 ********"); for(int n=0;n 0) { int dl = res; if(dl >= 5) { crc = rxData[dl-2]; crc = (crc<<8) + rxData[dl-1]; if(crc == CRC16::CalModbusCRC16(rxData, dl-2)) { res = CommOK; } else { res = CommDataError; } } else res = CommDataError; } if(CommOK != res){ qDebug("ModBusMultiWrite error,devaddr:%d,errorcode:%d",device_addr,res); } return res; } int Uart_Driver::ModBusSingleWrite( const quint8 device_addr,const quint16 data_addr, const quint16 wr_data, const quint16 timeout_ms ) { int res = CommOK; quint8 txData[16] = {0}; quint8 rxData[16] = {0}; txData[0] = device_addr; txData[1] = FUNC_CODE_SINGLE_WRITE; txData[2] = data_addr/256; txData[3] = data_addr%256; txData[4] = wr_data/256; txData[5] = wr_data%256; unsigned short crc = CRC16::CalModbusCRC16(txData,6); txData[6] = (quint8)(crc>>8); txData[7] = (quint8)crc; const quint16 rx_data_len = 8; const quint16 tx_data_len = 8; quint16 rx_data = 0; ClearRxBuff(); if(tx_data_len != WriteDev(txData, tx_data_len)) res = CommTxError; if(CommOK == res) { res = ReadData(rxData, rx_data_len, timeout_ms); } if(CommOK == res) { crc = rxData[rx_data_len-2]; crc = (crc<<8) + rxData[rx_data_len-1]; if(crc == CRC16::CalModbusCRC16(rxData, rx_data_len-2)) { rx_data = (quint16)(rxData[4]<<8)+rxData[5]; if(0 == rx_data) //pass==1 res = CommWrFailError; } else { res = CommDataError; } } if(CommOK != res){ qDebug("ModBusSingleWrite error,devaddr:%d,errorcode:%d",device_addr,res); } return res; } int Uart_Driver::Tx_Rx_Data(void *txdata, const int txlen, void *rxdata, const int timeout_ms) { ClearRxBuff(); WriteDev(txdata, txlen); quint16 rx_len = 0; quint16 rx_time_out = 0; quint8 *p_rxdata = (quint8 *)rxdata; quint8 rx_databuff[512] = {0}; quint16 bytes = 0; int timeout_5ms = timeout_ms/5; while(1) { ioctl(FD, FIONREAD, &bytes); //确认字节数 if(bytes > 512){ bytes = 512; } if(bytes > 0){ int rlen = ReadDev(&rx_databuff, bytes); if(rlen > 0){ for(int i=0;i0 && rx_time_out>40) //收到了部分字节后,字节之间超时 x*5ms { return rx_len; } if(rx_time_out > timeout_5ms) //接收超时 timeout_5ms * 5ms { return 0; } } rx_time_out++; msleep(5); } return 0; } int Uart_Driver::Tx_Rx_Data_ESP32(void *txdata, const int txlen, void *rxdata, const int rxlen) { ClearRxBuff(); WriteDev(txdata, txlen); quint16 rx_len = 0; quint16 rx_time_out = 0; quint8 *p_rxdata = (quint8 *)rxdata; quint8 rx_databuff[512] = {0}; quint16 bytes = 0; while(1) { ioctl(FD, FIONREAD, &bytes); //确认字节数 if(bytes > 512){ bytes = 512; } if(bytes > 0){ int rlen = ReadDev(&rx_databuff, bytes); if(rlen > 0){ for(int i=0;i= rxlen){ return 0; } if(rx_len>0 && rx_time_out>40) //收到了部分字节后,字节之间超时 x*5ms { return rx_len; } if(rx_time_out > 120) //接收超时 x * 5ms { return -1; } } rx_time_out++; msleep(5); } return 0; } int Uart_Driver::ReadData_ESP32(void *rxdata, const int timeout_ms) { quint16 rx_len = 0; quint16 rx_time_out = 0; quint8 *p_rxdata = (quint8 *)rxdata; quint8 rx_databuff[512] = {0}; quint16 bytes = 0; int timeout_5ms = timeout_ms/5; while(1) { ioctl(FD, FIONREAD, &bytes); //确认字节数 if(bytes > 512){ bytes = 512; } if(bytes > 0){ //qDebug("bytes = %d",bytes); int rlen = ReadDev(&rx_databuff, bytes); if(rlen > 0){ //qDebug("rlen = %d",rlen); for(int i=0;i0) { if(rx_time_out>timeout_5ms){ return rx_len; } } else{ return 0; } } rx_time_out++; msleep(5); } return 0; }