0

シリアルポートから (ファイル /dev/ttyUSB0 から) データを読み取る QSocketNotifier があります。ただし、QSocketNotifier は文字列を切り刻むように見えます... CuteCom ( Debian のようなシステムではapt-get source cutecom ) からいくつかのコードを取得し、それを端末専用プログラムに実装しようとしました。それで、ここまでです:

main.cpp:

#include <QtCore/QCoreApplication>
#include <QSocketNotifier>
#include <QTimer>
#include <QDebug>

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

using namespace std;

QSocketNotifier *m_notifier;
QString output_buffer="";
int m_fd;
char m_buf[4096];

class Timer : public QTimer {
  Q_OBJECT
public:
  explicit Timer(QObject *parent = 0) : QTimer(parent) {

  }
public slots:
    void readData(int fd){
        if (fd!=m_fd)
           return;

        int bytesRead=::read(m_fd, m_buf, 4096);

        if (bytesRead<0)
        {
           cerr << "read result: " << bytesRead << endl;
           return;
        }
        // if the device "disappeared", e.g. from USB, we get a read event for 0 bytes
        else if (bytesRead==0)
        {
           disconnectTTY();
           return;
        }

        const char* c=m_buf;
        qDebug() << "THEY CAME " << bytesRead << " bytes!";
        QString text="";
        for (int i=0; i<bytesRead; i++)
        {
            // also print a newline for \r, and print only one newline for \r\n
            if ((isprint(*c)) || (*c=='\n') || (*c=='\r'))
            {
                text+=(*c);
            }
            else
            {
                char buf[64];
                unsigned int b=*c;
                snprintf(buf, 16, "\\0x%02x", b & 0xff);
                text+=buf;
            }
         c++;
        }
        addOutput(text);
    }
    void addOutput(QString text){
        output_buffer+=text;
        this->setSingleShot(true);
        this->start(100);
    }
    void process_input(){
        //this function processes the input strings.
        cout << QString(output_buffer).toLocal8Bit().data();
        output_buffer.clear();
    }
    void create_avg(){
        cout << "I will create the average in the future!\n";
    }
    void disconnectTTY(){
        delete m_notifier;
        m_notifier=0;
    }
    void connect_normal_timer()
    {
        connect(this, SIGNAL(timeout()), this, SLOT(process_input()));
    }
    void connect_avg_maker_timer()
    {
        connect(this ,SIGNAL(timeout()), this, SLOT(create_avg()));
    }
    void disconnect_from_slot()
    {
        disconnect(this, 0, this, 0);
    }
    void create_notifier(){
        m_notifier=new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
        connect(m_notifier, SIGNAL(activated(int)), this, SLOT(readData(int)));
    }
};

void open_device(QString device){
    m_fd=open(device.toLatin1(), O_RDONLY | O_NDELAY | O_NONBLOCK);//O_NDELAY);
    if(m_fd<0){
        cerr << QString("Cannot open device '"+device+"'\n").toLocal8Bit().data();
        exit(1);
    }
   tcflush(m_fd, TCIOFLUSH);
}

Timer timer;
Timer avg_maker;

#include "main.moc"


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    /*
      SETTING UP TIMERS
    */

    timer.connect_normal_timer();
    avg_maker.connect_avg_maker_timer();

    /*
      OPENING DEVICE
    */

    open_device("/dev/ttyUSB0");

    /*
      CREATE SOCKET READER
    */
    timer.create_notifier();

    avg_maker.start(3000);
    return a.exec();
}

そこで、2 つのタイマーをセットアップし、/dev/ttyUSB0 を読み取り専用で開き、QSocket 通知機能を接続します。問題は、(真ん中の) みじん切りの文字列しか得られず、実際の大きな文字列が得られないことです! 何が問題を引き起こしているのかはわかりませんが、上記のプログラムはうまく動作しませんが、キュートコムはうまく動作します!

実際の問題が何であるかはわかりませんが、実際にこのプログラムを引き起こすチェックはなく (文字列フィルタリングを適用していません)、QSocketNotifier は実際には文字列の最初と最後の部分のみを送信することを知っています (決して文字列全体)。

これが難しいことはわかっていますが、誰かが助けてくれれば... ありがとう!

4

1 に答える 1

0

open_device() 関数は次のようにする必要があります。

void open_device(QString device){
    m_fd=open(device.toLatin1(), O_RDONLY | O_NDELAY);
    if(m_fd<0){
        cerr << QString("Cannot open device '"+device+"'\n").toLocal8Bit().data();
        exit(1);
    }
   tcflush(m_fd, TCIOFLUSH);
   int n = fcntl(m_fd, F_GETFL, 0);
   fcntl(m_fd, F_SETFL, n & ~O_NDELAY);
   if (tcgetattr(m_fd, &m_oldtio)!=0)
   {
      cerr << "tcgetattr() 2 failed" << endl;
   }

   struct termios newtio;

   if (tcgetattr(m_fd, &newtio)!=0)
   {
      cerr << "tcgetattr() 3 failed" << endl;
   }

   speed_t _baud=B9600;

   cfsetospeed(&newtio, (speed_t)_baud);
   cfsetispeed(&newtio, (speed_t)_baud);

   newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8;
   newtio.c_cflag |= CLOCAL | CREAD;

   newtio.c_cflag &= ~(PARENB | PARODD);

   newtio.c_cflag &= ~CRTSCTS;

   newtio.c_cflag &= ~CSTOPB;

   newtio.c_iflag=IGNBRK;

   newtio.c_iflag &= ~(IXON|IXOFF|IXANY);

   newtio.c_lflag=0;
   newtio.c_oflag=0;

   newtio.c_cc[VTIME]=1;
   newtio.c_cc[VMIN]=60;

   if (tcsetattr(m_fd, TCSANOW, &newtio)!=0)
   {
      cerr << "tcsetattr() 1 failed" << endl;
   }

   int mcs=0;
   ioctl(m_fd, TIOCMGET, &mcs);
   mcs |= TIOCM_RTS;
   ioctl(m_fd, TIOCMSET, &mcs);

   if (tcgetattr(m_fd, &newtio)!=0)
   {
      cerr << "tcgetattr() 4 failed" << endl;
   }

   newtio.c_cflag &= ~CRTSCTS;

   if (tcsetattr(m_fd, TCSANOW, &newtio)!=0)
   {
      cerr << "tcsetattr() 2 failed" << endl;
   }
}
于 2012-07-26T07:00:06.627 に答える