[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-devel
Subject:    Re: How to open & capture serial communication?
From:       Thorsten Schnebeck <thorsten.schnebeck () gmx ! net>
Date:       2001-09-16 22:00:56
[Download RAW message or body]

Am Montag, 17. September 2001 03:02 schrieb Boulgakov Andrei:
> Hi!
> Is there in KDE some class handling serial/parallel ports?
>

Hmm, I have here something for the serial port based on termios.
Ok, it is not HQ-KDE/QT-code, but it works quite well for our 
stepper-controller. You can do things like

  m_device=new Serial;
  if (!m_device->open("/dev/ttyS0")) {
    return false;
  }
  m_device->setSpeed(9600);
  m_device->setDataBits(8);
  m_device->setStopBits(1);
  m_device->setParity(Serial::N);
  m_device->setFlowControl(Serial::NONE);
  m_device->setReadLength(1);
  m_device->setReadTimeout(NO_TIMEOUT);

Writing:
  command="@0"+command.upper()+"\r";
  if (!m_device->write(command))  
    //error
  else

Reading works via a readNotifier-signal. This signal will be emitted when the 
input-buffer reaches a limit (setReadLength()) and gives you the serial 
buffer content, another signal you can get is a timeout-signal.
You have to connect to this signals. Look at the implementation of 
void Serial::m_slotTimerEvent() to see how this stuff works.

The notifier makes it easy to write non-blocking serial controlled widgets :-)

Bye

  Thorsten


--


["serial.h" (text/x-c++)]

/***************************************************************************
                      serial.h  -  description
                      --------
    begin:            Tue Dec 19 2000
    copyright:        (C) 2000,2001 by IFW
    email:            schnebeck@mail.ifw.uni-hannover.de
    licence:          LGPL
 ***************************************************************************/

#ifndef SERIAL_H
#define SERIAL_H

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <sys/ioctl.h>
#include <fcntl.h>
#include <signal.h>
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream.h>

#include <qobject.h>
#include <qstring.h>
#include <qtimer.h>

// substitution of TERMIOS definitions

class Serial : public QObject {
Q_OBJECT

/*HAL class to simplify usage of the serial interface
 *@author Thorsten Schnebeck
 */

public:
	enum              {DSR=TIOCM_DSR, DTR=TIOCM_DTR, RTS=TIOCM_RTS, CTS=TIOCM_CTS, \
DCD=TIOCM_CAR, RI=TIOCM_RI};  enum flowcontrol  {RTS_CTS, XON_XOFF, NONE};
	enum parity       {EVEN,ODD,N};
	static const bool VALID=false;
	static const bool TIMEOUT=true;

	Serial(QObject *parent=0, const char *name=0);
	~Serial();
	
	bool           open(const char*);
	bool           close();

	bool           getStatusBit(const int &) const;
	void           setStatusBit(const int &, bool);
	void           setSpeed(const unsigned int &);
	void           setDataBits(const unsigned short &);
	void           setStopBits(const unsigned short &);
	void           setParity(const parity &);
	void           setFlowControl(const flowcontrol &);

	void           setReadLength(const unsigned int &length) {m_readLength=length;};
	void           setReadTimeout(const unsigned int &timeout) {m_timeout=timeout;};
	void           clearReadBuffer() {m_readData="";};
	unsigned int   getReadLength() const {return m_readLength;};
	bool           write(const QString &text) {return std::write(m_serialfd, text, \
text.length());};

signals:
	void           readNotifier(QString,bool);

protected slots:
	void           m_slotTimerEvent();

protected:
	struct termios m_tty_saved;
	struct termios m_tty;

	int            m_serialfd;
	int            m_statusbit;
	unsigned int   m_speed;
	const char*    m_port;

	unsigned int   m_readLength;
	unsigned int   m_timeout;
	QString        m_readData;
	QString        m_Device;
	QTimer*        m_timer;
};
#endif


["serial.cpp" (text/x-c)]

/***************************************************************************
                    serial.cpp  -  description
                    ----------
    begin:          Tue Dec 19 2000
    copyright:      (C) 2000,2001 by IFW
    email:          schnebeck@mail.ifw.uni-hannover.de
    licence:        LGPL
 ***************************************************************************/

#include "serial.h"

Serial::Serial(QObject *parent, const char *name) : QObject(parent, name) {
	m_serialfd=-1;
	m_port="";
	m_readData="";
	m_readLength=1;
	m_timeout=0;
	m_timer = new QTimer( this );
}


Serial::~Serial() {
	delete m_timer;
	Serial::close();
}


bool Serial::getStatusBit(const int &signal) const {
	ioctl(m_serialfd, TIOCMGET, &m_statusbit);
	return (m_statusbit & signal) > 0;
}


void Serial::setStatusBit(const int &signal, bool bit) {
	ioctl(m_serialfd, TIOCMGET, &m_statusbit);
	if (bit) m_statusbit|=signal; else m_statusbit &= ~signal;
	ioctl(m_serialfd, TIOCMSET, &m_statusbit);
}


void Serial::setSpeed(const unsigned int &speed=9600) {
	tcgetattr(m_serialfd, &m_tty);
	switch(speed) {
		case 1200   : m_speed=B1200; break;
		case 2400   : m_speed=B2400; break;
		case 9600   : m_speed=B9600; break;
		case 19200  : m_speed=B19200; break;
		case 38400  : m_speed=B38400; break;
#ifdef B57600
		case 57600  : m_speed=B57600; break;
#endif
#ifdef B115200
		case 115200 : m_speed=B115200; break;
#endif
#ifdef B230400
		case 230400 : m_speed=B230400; break;
#endif
#ifdef B460800
		case 460800 : m_speed=B460800;break;
#endif
		default     : m_speed=B9600;
	}
	cfsetispeed(&m_tty, m_speed);
	cfsetospeed(&m_tty, m_speed);
	m_tty.c_cflag|=(CLOCAL | CREAD);
	tcsetattr(m_serialfd, TCSADRAIN, &m_tty);
}


void Serial::setDataBits(const unsigned short &bits=8) {
	tcgetattr(m_serialfd, &m_tty);
	m_tty.c_cflag&=~(CS5|CS6|CS7|CS8);
	switch(bits) {
		case 5  : m_tty.c_cflag|=CS5; break;
		case 6  : m_tty.c_cflag|=CS6; break;
		case 7  : m_tty.c_cflag|=CS7; break;
//default 8 data bits
		default : m_tty.c_cflag|=CS8;
  }
  tcsetattr(m_serialfd, TCSADRAIN, &m_tty);
}


void Serial::setStopBits(const unsigned short &bits=1) {
	tcgetattr(m_serialfd, &m_tty);
	m_tty.c_cflag&=~CSTOPB;
//default: 1 stop bit
	if (bits == 2) m_tty.c_cflag|=CSTOPB;
	tcsetattr(m_serialfd, TCSADRAIN, &m_tty);
}


void Serial::setParity(const parity &type=N) {
	tcgetattr(m_serialfd, &m_tty);
//default: no parity
	m_tty.c_cflag&=~(PARENB|PARODD);
	m_tty.c_iflag&=~(INPCK|ISTRIP);
	switch(type) {
		case EVEN : m_tty.c_cflag|=PARENB; m_tty.c_iflag|=(INPCK|ISTRIP); break;
		case ODD  : m_tty.c_cflag|=(PARENB|PARODD); m_tty.c_iflag|=(INPCK|ISTRIP); break;
	}
	tcsetattr(m_serialfd, TCSADRAIN, &m_tty);
}


void Serial::setFlowControl(const flowcontrol &type=NONE) {
	tcgetattr(m_serialfd, &m_tty);
//default: no flowcontrol
	m_tty.c_cflag&=~CRTSCTS;
	m_tty.c_iflag&=~(IXON|IXOFF|IXANY);
	switch(type) {
		case RTS_CTS	:	m_tty.c_cflag|=CRTSCTS; break;
		case XON_XOFF	: m_tty.c_iflag|=(IXON|IXOFF|IXANY); break;
	}
	tcsetattr(m_serialfd, TCSADRAIN, &m_tty);
}


bool Serial::open(const char* m_port) {
	if(m_serialfd >= 0) {
		cout << "Warning: serial port was already open. Closing it NOW!" << endl;
		std::close(m_serialfd);
		m_serialfd = -1;
	}
	m_serialfd=std::open(m_port, O_RDWR | O_NOCTTY | O_NDELAY);
	if (m_serialfd >= 0) {
		tcgetattr(m_serialfd, &m_tty_saved);
		m_tty=m_tty_saved;
//set default mode
		Serial::setSpeed();
		Serial::setDataBits();
		Serial::setStopBits();
		Serial::setParity();
		Serial::setFlowControl();

		m_tty.c_oflag&=~OPOST;				//raw output
		m_tty.c_lflag&=~ICANON;				// non-canonical mode
		tcsetattr(m_serialfd, TCSADRAIN, &m_tty);

		fcntl(m_serialfd, F_SETFL, 0);
		connect( m_timer, SIGNAL(timeout()), this, SLOT(m_slotTimerEvent()) );
		m_timer->start(5);
		cout << "Serial port opened!" << endl;
		return true;
	}
	else {
		cout <<"Unable to open serial port!" << endl;
		return false;
	}
}


bool Serial::close() {
	cout <<"Serial port closed!" << endl;
	m_timer->stop();
	if(m_serialfd >=0 ) {
		tcflush(m_serialfd, TCIOFLUSH);
// restore saved settings:
		if(tcsetattr(m_serialfd, TCSADRAIN, &m_tty_saved) < 0) {
			cout <<"Can't restore  settings of serial port!" << endl;;
			std::close(m_serialfd);
			m_serialfd = -1;
			return false;
		}
		std::close(m_serialfd);
		m_serialfd = -1;
	}
	return true;
}


void Serial::m_slotTimerEvent() {
	int bytes;
	int len;
	unsigned char element;
	QString data;

	if (m_timeout > 0) {
		m_timeout--;
		if (m_timeout == 0) {
			cout << "Serial read: emit Timeout!" << endl;
			emit Serial::readNotifier("", Serial::TIMEOUT);
			return;
		}
	}
	std::ioctl(m_serialfd,FIONREAD, &bytes);
	if (bytes>0) {
		len=std::read(m_serialfd, &element, 1);
		if (len <= 0)  return;
		m_readData+=element;
	}
	if (m_readData.length() >= m_readLength) {
		data=m_readData.left(m_readLength);
		m_readData=m_readData.mid(m_readLength+1);
		m_timeout=0;
//		cout << "Serial read: emit " << data << endl;
		emit Serial::readNotifier(data,Serial::VALID);
	}
}

>> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic