[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