📄 serialport.cpp
字号:
// Make sure that the serial port is open. // if ( ! this->IsOpen() ) { throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ; } // // Get the current port settings. // termios port_settings ; if ( tcgetattr( mFileDescriptor, &port_settings ) < 0 ) { throw std::runtime_error( strerror(errno) ) ; } // // If CSTOPB is set then we are using two stop bits, otherwise we // are using 1 stop bit. // if ( port_settings.c_cflag & CSTOPB ) { return SerialPort::STOP_BITS_2 ; } return SerialPort::STOP_BITS_1 ;}inlinevoidSerialPort::SerialPortImpl::SetFlowControl( const SerialPort::FlowControl flowControl ) throw( SerialPort::NotOpen, std::invalid_argument ){ // // Make sure that the serial port is open. // if ( ! this->IsOpen() ) { throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ; } // // Get the current port settings. // termios port_settings ; if ( tcgetattr( mFileDescriptor, &port_settings ) < 0 ) { throw std::runtime_error( strerror(errno) ) ; } // // Set the flow control. // switch( flowControl ) { case SerialPort::FLOW_CONTROL_HARD: port_settings.c_cflag |= CRTSCTS ; break ; case SerialPort::FLOW_CONTROL_NONE: port_settings.c_cflag &= ~(CRTSCTS) ; break ; default: throw std::invalid_argument( ERR_MSG_INVALID_FLOW_CONTROL ) ; break ; } // // Apply the modified settings. // if ( tcsetattr( mFileDescriptor, TCSANOW, &port_settings ) < 0 ) { throw std::invalid_argument( strerror(errno) ) ; } return ;}inlineSerialPort::FlowControlSerialPort::SerialPortImpl::GetFlowControl() const throw( SerialPort::NotOpen ){ // // Make sure that the serial port is open. // if ( ! this->IsOpen() ) { throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ; } // // Get the current port settings. // termios port_settings ; if ( tcgetattr( mFileDescriptor, &port_settings ) < 0 ) { throw std::runtime_error( strerror(errno) ) ; } // // If CRTSCTS is set then we are using hardware flow // control. Otherwise, we are not using any flow control. // if ( port_settings.c_cflag & CRTSCTS ) { return SerialPort::FLOW_CONTROL_HARD ; } return SerialPort::FLOW_CONTROL_NONE ;}inlineboolSerialPort::SerialPortImpl::IsDataAvailable() const throw( SerialPort::NotOpen, std::runtime_error ){ // // Make sure that the serial port is open. // if ( ! this->IsOpen() ) { throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ; } // // Check if any data is available in the input buffer. // return ( mInputBuffer.size() > 0 ? true : false ) ;}inlineunsigned charSerialPort::SerialPortImpl::ReadByte(const unsigned int msTimeout) throw( SerialPort::NotOpen, SerialPort::ReadTimeout, std::runtime_error ){ // // Make sure that the serial port is open. // if ( ! this->IsOpen() ) { throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ; } // // Get the current time. Throw an exception if we are unable // to read the current time. // struct timeval entry_time ; if ( gettimeofday( &entry_time, NULL ) < 0 ) { throw std::runtime_error( strerror(errno) ) ; } // // Wait for data to be available. // const int MICROSECONDS_PER_MS = 1000 ; const int MILLISECONDS_PER_SEC = 1000 ; // while( 0 == mInputBuffer.size() ) { // // Read the current time. // struct timeval curr_time ; if ( gettimeofday( &curr_time, NULL ) < 0 ) { throw std::runtime_error( strerror(errno) ) ; } // // Obtain the elapsed time. // struct timeval elapsed_time = curr_time - entry_time ; // // Increase the elapsed number of milliseconds. // int elapsed_ms = ( elapsed_time.tv_sec * MILLISECONDS_PER_SEC + elapsed_time.tv_usec / MICROSECONDS_PER_MS ) ; // // If more than msTimeout milliseconds have elapsed while // waiting for data, then we throw a ReadTimeout exception. // if ( ( msTimeout > 0 ) && ( elapsed_ms > msTimeout ) ) { throw SerialPort::ReadTimeout() ; } // // Wait for 1ms (1000us) for data to arrive. // usleep( MICROSECONDS_PER_MS ) ; } // // Return the first byte and remove it from the queue. // unsigned char next_char = mInputBuffer.front() ; mInputBuffer.pop() ; return next_char ;}inlinevoidSerialPort::SerialPortImpl::Read( SerialPort::DataBuffer& dataBuffer, const unsigned int numOfBytes, const unsigned int msTimeout ) throw( SerialPort::NotOpen, SerialPort::ReadTimeout, std::runtime_error ){ // // Make sure that the serial port is open. // if ( ! this->IsOpen() ) { throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ; } // // Empty the data buffer. // dataBuffer.resize(0) ; // if ( 0 == numOfBytes ) { // // Read all available data if numOfBytes is zero. // while( this->IsDataAvailable() ) { dataBuffer.push_back( ReadByte(msTimeout) ) ; } } else { // // Reserve enough space in the buffer to store the incoming // data. // dataBuffer.reserve( numOfBytes ) ; // for(int i=0; i<numOfBytes; ++i) { dataBuffer.push_back( ReadByte(msTimeout) ) ; } } return ;}inlineconst std::stringSerialPort::SerialPortImpl::ReadLine( const unsigned int msTimeout, const char lineTerminator ) throw( SerialPort::NotOpen, SerialPort::ReadTimeout, std::runtime_error ){ std::string result ; char next_char = 0 ; do { next_char = this->ReadByte( msTimeout ) ; result += next_char ; } while( next_char != lineTerminator ) ; return result ;}inlinevoidSerialPort::SerialPortImpl::WriteByte( const unsigned char dataByte ) throw( SerialPort::NotOpen, std::runtime_error ){ // // Make sure that the serial port is open. // if ( ! this->IsOpen() ) { throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ; } // // Write the byte to the serial port. // this->Write( &dataByte, 1 ) ; return ;}inlinevoidSerialPort::SerialPortImpl::Write(const SerialPort::DataBuffer& dataBuffer) throw( SerialPort::NotOpen, std::runtime_error ){ // // Make sure that the serial port is open. // if ( ! this->IsOpen() ) { throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ; } // // Nothing needs to be done if there is no data in the buffer. // if ( 0 == dataBuffer.size() ) { return ; } // // Allocate memory for storing the contents of the // dataBuffer. This allows us to write all the data using a single // call to write() instead of writing one byte at a time. // unsigned char* local_buffer = new unsigned char[dataBuffer.size()] ; if ( 0 == local_buffer ) { throw std::runtime_error( std::string(__FUNCTION__) + ": Cannot allocate memory while writing" "data to the serial port." ) ; } // // Copy the data into local_buffer. // std::copy( dataBuffer.begin(), dataBuffer.end(), local_buffer ) ; // // Write data to the serial port. // try { this->Write( local_buffer, dataBuffer.size() ) ; } catch( ... ) { // // Free the allocated memory. // delete [] local_buffer ; throw ; } // // Free the allocated memory. // delete [] local_buffer ; return ;}inlinevoidSerialPort::SerialPortImpl::Write( const unsigned char* dataBuffer, const unsigned int bufferSize ) throw( SerialPort::NotOpen, std::runtime_error ){ // // Make sure that the serial port is open. // if ( ! this->IsOpen() ) { throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ; } // // Write the data to the serial port. Keep retrying if EAGAIN // error is received. // int num_of_bytes_written = -1 ; do { num_of_bytes_written = write( mFileDescriptor, dataBuffer, bufferSize ) ; } while ( ( num_of_bytes_written < 0 ) && ( EAGAIN == errno ) ) ; // if ( num_of_bytes_written < 0 ) { throw std::runtime_error( strerror(errno) ) ; } // // :FIXME: What happens if num_of_bytes_written < bufferSize ? // return ;}inlinevoidSerialPort::SerialPortImpl::HandlePosixSignal( int signalNumber ){ // // We only want to deal with SIGIO signals here. // if ( SIGIO != signalNumber ) { return ; } // // Check if any data is available at the specified file // descriptor. // int num_of_bytes_available = 0 ; if ( ioctl( mFileDescriptor, FIONREAD, &num_of_bytes_available ) < 0 ) { /* * Ignore any errors and return immediately. */ return ; } // // If data is available, read all available data and shove // it into the corresponding input buffer. // for(int i=0; i<num_of_bytes_available; ++i) { unsigned char next_byte ; if ( read( mFileDescriptor, &next_byte, 1 ) > 0 ) { mInputBuffer.push( next_byte ) ; } else { break ; } } return ;}namespace{ const struct timeval operator-( const struct timeval& firstOperand, const struct timeval& secondOperand ) { /* * This implementation may result in undefined behavior if the * platform uses unsigned values for storing tv_sec and tv_usec * members of struct timeval. */ // // Number of microseconds in a second. // const int MICROSECONDS_PER_SECOND = 1000000 ; struct timeval result ; // // Take the difference of individual members of the two operands. // result.tv_sec = firstOperand.tv_sec - secondOperand.tv_sec ; result.tv_usec = firstOperand.tv_usec - secondOperand.tv_usec ; // // If abs(result.tv_usec) is larger than MICROSECONDS_PER_SECOND, // then increment/decrement result.tv_sec accordingly. // if ( abs( result.tv_usec ) > MICROSECONDS_PER_SECOND ) { int num_of_seconds = (result.tv_usec / MICROSECONDS_PER_SECOND ) ; result.tv_sec += num_of_seconds ; result.tv_usec -= ( MICROSECONDS_PER_SECOND * num_of_seconds ) ; } return result ; }} ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -