📄 serial.cpp
字号:
#include "serial.h"#ifdef _UC7400#include <sys/ioctl.h>#include <moxadevice.h>#define RS232_MODE 0#define RS485_2WIRE_MODE 1#define RS422_MODE 2#define RS485_4WIRE_MODE 3#endifusing namespace Serial ;CSerialPortDef::CSerialPortDef(CChannelSet& setChannel){ m_wChannelNo = setChannel.m_wChannelNo; m_strChannelName = setChannel.m_strChannelName; m_strComName = setChannel.m_strComName; m_dwIntervalMS = setChannel.m_dwIntervalMS; switch (setChannel.m_lBaudRate) { case 300: m_lBaudRate = BAUD_600; break; case 600: m_lBaudRate = BAUD_600; break; case 1200: m_lBaudRate = BAUD_1200; break; case 2400: m_lBaudRate = BAUD_2400; break; case 4800: m_lBaudRate = BAUD_4800; break; case 9600: m_lBaudRate = BAUD_9600; break; case 19200: m_lBaudRate = BAUD_19200; break; default: m_lBaudRate = BAUD_9600; break; } m_byStopBit = setChannel.m_byStopBit; switch (setChannel.m_byDataBit) { case 5: m_byDataBit = CHAR_SIZE_5; break; case 6: m_byDataBit = CHAR_SIZE_6; break; case 7: m_byDataBit = CHAR_SIZE_7; break; case 8: m_byDataBit = CHAR_SIZE_8; break; default: m_byDataBit = CHAR_SIZE_8; break; } switch (setChannel.m_byParity) { case 0://无 m_byParity = PARITY_NONE; break; case 1://奇 m_byParity = PARITY_ODD; break; case 2://偶 m_byParity = PARITY_EVEN; break; default: m_byParity = PARITY_NONE; break; } m_bIsMaster = setChannel.m_bIsMaster; //front if (setChannel.m_strKDL == string("CDT")) { /* if (m_bIsMaster) m_kdl = kdl_eCDTm; else m_kdl = kdl_eCDTs; */ m_kdl = kdl_eCDT; } else if (setChannel.m_strKDL == string("TA")) { m_kdl = kdl_eTA; } else if (setChannel.m_strKDL == string("ISA")) { m_kdl = kdl_eISA; } else if (setChannel.m_strKDL == string("SIMU")) { m_kdl = kdl_eSimu; } else if (setChannel.m_strKDL == string("SEPAM2000")) { m_kdl = kdl_eSepam2000; } else if (setChannel.m_strKDL == string("SEPAM1000")) { m_kdl = kdl_eSepam1000; } else if (setChannel.m_strKDL == string("PM500")) { m_kdl = kdl_ePM500; } else if (setChannel.m_strKDL == string("GDZL")) { m_kdl = kdl_eJDDY; } else if (setChannel.m_strKDL == string("GPS"))
{
m_kdl = kdl_eGPS;
} else if (setChannel.m_strKDL == string("DNP3")) { m_kdl = kdl_eDNP3; } else if (setChannel.m_strKDL == string("JA05")) { m_kdl = kdl_eJA05; } else if ((setChannel.m_strKDL == string("PMAC")) || (setChannel.m_strKDL == string("MODBUS-RTU"))) { m_kdl = kdl_ePMAC; } else if (setChannel.m_strKDL == string("INT-BUS")) { m_kdl = kdl_eINTBUS; } else if (setChannel.m_strKDL == string("CSC2000")) { m_kdl = kdl_eCSC2000; } else if (setChannel.m_strKDL == string("BWD-3K130A")) { m_kdl = kdl_eBWD_3K130A; } else if (setChannel.m_strKDL == string("DATA86")) { m_kdl = kdl_eDATA86; } else if (setChannel.m_strKDL == string("YD2")) { m_kdl = kdl_eYD2; }};bool CSerial::Open(){ bool bRet = true; // If the buffer is alreay open then we should not allow a call to another open(). if( IsOpen() == false ) { bRet = false; // Since we are dealing with the serial port we need to use the O_NOCTTY option. int flags = O_RDWR | O_NOCTTY; // Try to open the serial port. if ((m_hFile = ::open(m_pChannel->m_strComName.data(), flags) ) != -1) { if( InitializeSerialPort()) bRet = true; } } return bRet ;}void CSerial::Close(){ if (m_hFile != -1) { ::close(m_hFile); }}bool CSerial::InitializeSerialPort(){ bool bRet = false; // If we do not have a valid file descriptor then return with failure. if (-1 == m_hFile) return bRet ; #ifdef _UC7400 int mode = RS232_MODE; ioctl(m_hFile, MOXA_SET_OP_MODE, &mode); //1. Function: MOXA_SET_OP_MODE// int ioctl(fd, MOXA_SET_OP_MODE, &mode)// Description// Set the interface mode. Argument 3 mode will pass to the UART device driver and change it.// 2. Function: MOXA_GET_OP_MODE// int ioctl(fd, MOXA_GET_OP_MODE, &mode)#endif // Use non-blocking mode while configuring the serial port. int flags = fcntl(m_hFile, F_GETFL, 0) ; if (-1 == fcntl(m_hFile,F_SETFL,flags | O_NONBLOCK ) ) return bRet ; // Flush out any garbage left behind in the buffers associated // with the port from any previous operations. if (-1 == tcflush(m_hFile, TCIOFLUSH) ) return bRet; // Set up the default configuration for the serial port. if (SetParameters() == false) return bRet ; // Allow all further communications to happen in blocking mode. flags = fcntl(m_hFile, F_GETFL, 0) ; if( -1 == fcntl(m_hFile,F_SETFL,flags & ~O_NONBLOCK ) ) return bRet ; // If we get here without problems then we are good; return a value // different from -1. return true ;}bool CSerial::SetParameters(){ // Baud rate if (BAUD_INVALID == SetBaudRate((BaudRateEnum)m_pChannel->m_lBaudRate)) { cout <<"SetBaudRate failure"<<endl; return false; } // Character size. if (-1 == SetCharSize((CharSizeEnum)m_pChannel->m_byDataBit)) { cout <<"SetCharSize failure"<<endl; return false; } // Number of stop bits. if (-1 == SetNumOfStopBits(m_pChannel->m_byStopBit)) { cout <<"SetNumOfStopBits failure"<<endl; return false; } // Parity if (-1 == SetParity((ParityEnum)m_pChannel->m_byParity)) { cout <<"SetParity failure"<<endl; return false; } // Flow control if (-1 == SetFlowControl(FLOW_CONTROL_SOFT)) return false; // All done. Return a value other than -1. return true;}const BaudRateEnum CSerial::SetBaudRate(const BaudRateEnum baud_rate){ if(-1 == m_hFile) return BAUD_INVALID ; switch (baud_rate) { case BAUD_50: case BAUD_75: case BAUD_110: case BAUD_134: case BAUD_150: case BAUD_200: case BAUD_300: case BAUD_600: case BAUD_1200: case BAUD_1800: case BAUD_2400: case BAUD_4800: case BAUD_9600: case BAUD_19200: case BAUD_38400: { // Get the current terminal settings. struct termios term_setting ; if (-1 == tcgetattr(m_hFile, &term_setting)) return BAUD_INVALID ; // Modify the baud rate in the term_setting structure. cfsetispeed( &term_setting, baud_rate ) ; cfsetospeed( &term_setting, baud_rate ) ; term_setting.c_iflag = 0; term_setting.c_oflag = 0; term_setting.c_lflag = 0;// term_setting.c_cflag = CREAD; term_setting.c_cc[VMIN]=1; term_setting.c_cc[VTIME]=0; // Apply the modified termios structure to the serial port. if(-1 == tcsetattr(m_hFile, TCSANOW, &term_setting)) return BAUD_INVALID ; break ; } default: return BAUD_INVALID ; break ; } ; // // If we succeeded in setting the baud rate then we need to return // the baud rate. // return BaudRate() ;}const BaudRateEnum CSerial::BaudRate() const{ if (-1 == m_hFile ) return BAUD_INVALID ; // Get the current terminal settings. struct termios term_setting ; if (-1 == tcgetattr(m_hFile, &term_setting)) return BAUD_INVALID ; // Read the input and output baud rates. speed_t input_baud = cfgetispeed( &term_setting ) ; speed_t output_baud = cfgetospeed( &term_setting ) ; // Make sure that the input and output baud rates are // equal. Otherwise, we do not know which one to return. if(input_baud != output_baud) return BAUD_INVALID ; switch( input_baud ) { case B50: return BAUD_50 ; break ; case B75: return BAUD_75 ; break ; case B110: return BAUD_110 ; break ; case B134: return BAUD_134 ; break ; case B150: return BAUD_150 ; break ; case B200: return BAUD_200 ; break ; case B300: return BAUD_300 ; break ; case B600: return BAUD_600 ; break ; case B1200: return BAUD_1200 ; break ; case B1800: return BAUD_1800 ; break ; case B2400: return BAUD_2400 ; break ; case B4800: return BAUD_4800 ; break ; case B9600: return BAUD_9600 ; break ; case B19200: return BAUD_19200 ; break ; case B38400: return BAUD_38400 ; break ; default: return BAUD_INVALID ; // we return an invalid value in this case. break ; } assert( false ) ; return BAUD_INVALID ;}const CharSizeEnum CSerial::SetCharSize(const CharSizeEnum char_size){ if( -1 == m_hFile ) return CHAR_SIZE_INVALID ; switch(char_size) { case CHAR_SIZE_5: case CHAR_SIZE_6: case CHAR_SIZE_7: case CHAR_SIZE_8: { // Get the current terminal settings. struct termios term_setting ; if(-1 == tcgetattr(m_hFile, &term_setting)) return CHAR_SIZE_INVALID ; // Set the character size to the specified value. If the character // size is not 8 then it is also important to set ISTRIP. Setting // ISTRIP causes all but the 7 low-order bits to be set to // zero. Otherwise they are set to unspecified values and may // cause problems. At the same time, we should clear the ISTRIP // flag when the character size is 8 otherwise the MSB will always // be set to zero (ISTRIP does not check the character size // setting; it just sets every bit above the low 7 bits to zero). if(char_size == CHAR_SIZE_8) term_setting.c_iflag &= ~ISTRIP ; // clear the ISTRIP flag. else term_setting.c_iflag |= ISTRIP ; // set the ISTRIP flag. term_setting.c_cflag &= ~CSIZE ; // clear all the CSIZE bits. term_setting.c_cflag |= char_size ; // set the character size. // Set the new settings for the serial port. if( -1 == tcsetattr(m_hFile, TCSANOW, &term_setting) ) return CHAR_SIZE_INVALID ; break ; } default: return CHAR_SIZE_INVALID ; break ; } return CharSize() ;}const CharSizeEnum CSerial::CharSize() const{ if( -1 == m_hFile) return CHAR_SIZE_INVALID ; // Get the current terminal settings. struct termios term_setting ; if(-1 == tcgetattr(m_hFile, &term_setting)) return CHAR_SIZE_INVALID ; // Extract the character size from the terminal settings. int char_size = (term_setting.c_cflag & CSIZE) ; switch( char_size ) { case CS5: return CHAR_SIZE_5 ; break ; case CS6: return CHAR_SIZE_6 ; break ; case CS7: return CHAR_SIZE_7 ; break ; case CS8: return CHAR_SIZE_8 ; break ; default: // If we get an invalid character, we set the badbit for the // stream associated with the serial port. return CHAR_SIZE_INVALID ; break ; } ; return CHAR_SIZE_INVALID ;}short CSerial::SetNumOfStopBits(short stop_bits){ if (-1 == m_hFile) return 0 ; // Get the current terminal settings. struct termios term_setting ; if (-1 == tcgetattr(m_hFile, &term_setting)) return 0 ; switch (stop_bits) { case 1: term_setting.c_cflag &= ~CSTOPB ; break; case 2: term_setting.c_cflag |= CSTOPB; break ; default: return 0 ; break ; } // Set the new settings for the serial port. if(-1 == tcsetattr(m_hFile, TCSANOW, &term_setting)) return 0 ; return NumOfStopBits() ;}short CSerial::NumOfStopBits() const{ if(-1 == m_hFile) return 0 ; // Get the current terminal settings. struct termios term_setting ; if(-1 == tcgetattr(m_hFile, &term_setting)) return 0 ; // If CSTOPB is set then the number of stop bits is 2 otherwise it is 1. if( term_setting.c_cflag & CSTOPB ) return 2 ; else return 1 ;}const ParityEnum CSerial::SetParity(const ParityEnum parity){ if (-1 == m_hFile) return PARITY_INVALID ; // Get the current terminal settings. struct termios term_setting ; if (-1 == tcgetattr(m_hFile, &term_setting)) return PARITY_INVALID ; // Set the parity in the termios structure. switch( parity ) { case PARITY_EVEN: term_setting.c_cflag |= PARENB; /* Enable parity */ term_setting.c_cflag &= ~PARODD; /* 转换为偶效验*/ term_setting.c_iflag |= INPCK; /* Disnable parity checking */ break; case PARITY_ODD: term_setting.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/ term_setting.c_iflag |= INPCK; /* Disnable parity checking */ break ; case PARITY_NONE: term_setting.c_cflag &= ~PARENB; /* Clear parity enable */ term_setting.c_iflag &= ~INPCK; /* Enable parity checking */ break ; default: term_setting.c_cflag &= ~PARENB; /* Clear parity enable */ term_setting.c_iflag &= ~INPCK; /* Enable parity checking */ break ; } // Write the settings back to the serial port. if (-1 == tcsetattr(m_hFile, TCSANOW, &term_setting)) return PARITY_INVALID ; return Parity() ;}const ParityEnum CSerial::Parity() const{ if (-1 == m_hFile) return PARITY_INVALID ; // Get the current terminal settings. struct termios term_setting ; if(-1 == tcgetattr(m_hFile, &term_setting)) return PARITY_INVALID ; // Get the parity setting from the termios structure. if( term_setting.c_cflag & PARENB ) // parity is enabled. { if (term_setting.c_cflag & PARODD) // odd parity return PARITY_ODD ; else // even parity return PARITY_EVEN ; } else // no parity. return PARITY_NONE ; return PARITY_INVALID ; // execution should never reach here.}const FlowControlEnum CSerial::SetFlowControl(const FlowControlEnum flow_c){ if (-1 == m_hFile) return FLOW_CONTROL_INVALID ; // Flush any unwritten, unread data from the serial port. if (-1 == tcflush(m_hFile, TCIOFLUSH)) return FLOW_CONTROL_INVALID ; // Get the current terminal settings. struct termios tset; int retval = tcgetattr(m_hFile, &tset); if (-1 == retval) return FLOW_CONTROL_INVALID ; // Set the flow control. Hardware flow control uses the RTS (Ready // To Send) and CTS (clear to Send) lines. Software flow control // uses IXON|IXOFF if ( FLOW_CONTROL_HARD == flow_c ) { tset.c_iflag &= ~ (IXON|IXOFF); tset.c_cflag |= CRTSCTS; tset.c_cc[VSTART] = _POSIX_VDISABLE; tset.c_cc[VSTOP] = _POSIX_VDISABLE; } else { tset.c_iflag &= ~ (IXON|IXOFF);// tset.c_iflag |= IXON|IXOFF; tset.c_iflag |= IXANY; tset.c_cflag &= ~CRTSCTS;// tset.c_cc[VSTART] = CTRL_Q ; // 0x11 (021) ^q// tset.c_cc[VSTOP] = CTRL_S ; // 0x13 (023) ^s } retval = tcsetattr(m_hFile, TCSANOW, &tset); if (-1 == retval) return FLOW_CONTROL_INVALID ; return FlowControl() ;}const FlowControlEnum CSerial::FlowControl() const{ if( -1 == m_hFile) return FLOW_CONTROL_INVALID ; // Get the current terminal settings. struct termios tset ; if(-1 == tcgetattr(m_hFile, &tset)) return FLOW_CONTROL_INVALID ; // Check if IXON and IXOFF are set in c_iflag. If both are set and // VSTART and VSTOP are set to 0x11 (^Q) and 0x13 (^S) respectively, // then we are using software flow control.// if ((tset.c_iflag & IXON) && (tset.c_iflag & IXOFF) && (CTRL_Q == tset.c_cc[VSTART]) && (CTRL_S == tset.c_cc[VSTOP] )) if (tset.c_iflag & IXANY) return FLOW_CONTROL_SOFT ; else if (!((tset.c_iflag & IXON) || (tset.c_iflag & IXOFF))) // If neither IXON or IXOFF is set then we must have hardware flow // control. return FLOW_CONTROL_HARD ; // // If none of the above conditions are satisfied then the serial // port is using a flow control setup which we do not support at // present. return FLOW_CONTROL_INVALID ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -