2017-05-20 8 views
0

QSerialPortの周りにラッパーライブラリを作成しました。私は自分のデバイスと通信したい。まず、listコマンドをデバイスに送信し、そのデバイスでサポートされているコマンドのリストを返す必要があります。しかし、私のコードをデバッグしている間、私はlistコマンドがデバイスに送信されていることを観察し、デバイスはそれに適切な応答を返します(シリアルトラフィックスニファLinuxツールを使用してデバッグしました)。しかし、QSerialPort(シリアルトラフィックスニファツールは無効になっています)を使用して私のデバイスからの応答を取得していません。私はそれを数回テストした後に動作させることができません。QSerialPortを使用して何も読み取れない

マイSerial.h:

class Serial : public Print { 

public: 
    Serial(); 
    explicit Serial(const char *dev_path); 
    ~Serial(); 

    int begin(unsigned long baudrate); 
    int begin(unsigned long baudrate, uint8_t cfg); 
    void end(void); 

    int available(void) const; 
    bool availableForWrite(void) const; 
    void flush(void); 
    bool isError(void) const; 
    void reset(void); 

    unsigned long write(uint8_t c); 
    unsigned long write(uint8_t *p_data, unsigned long maxSize); 
    int read(void); 

    void close(); 

    QSerialPort &getPort() 
    { 
     return *_p_port; 
    } 

public slots: 
    void readyBe(void); 

private: 
    QSerialPort *_p_port; 
    unsigned long _baudrate; 
}; 

マイSerial.cpp:

Serial::Serial() 
{ 
    _p_port = new QSerialPort(); 
    if (_p_port == nullptr) 
     throw std::runtime_error("Can't allocate memory"); 
} 

Serial::Serial(const char *dev_path) 
{ 
    _p_port = new QSerialPort(QString(dev_path), QApplication::instance()); 
    if (_p_port == nullptr) 
     throw std::runtime_error("Can't allocate memory"); 
    // _p_port->setPortName(QString(dev_path)); 
    if (_p_port->open(QIODevice::ReadWrite) == false) { 
     throw std::runtime_error("Can't open the serial _p_port"); 
     delete _p_port; 
    } 
    _p_port->setBaudRate(QSerialPort::Baud9600); 
    _p_port->setDataBits(QSerialPort::Data8); 
    _p_port->setParity(QSerialPort::NoParity); 
    _p_port->setStopBits(QSerialPort::OneStop); 
    _p_port->setFlowControl(QSerialPort::NoFlowControl); 
} 

Serial::~Serial() 
{ 
    if (_p_port != nullptr) { 
     end(); 
     delete _p_port; 
    } 
} 

int Serial::begin(unsigned long baudrate) 
{ 
    if (_p_port->setBaudRate(baudrate, QSerialPort::AllDirections) == false) 
     return -1; 
    _baudrate = baudrate; 
    return 0; 
} 

void Serial::end() 
{ 
    if (_p_port->isOpen()) 
     _p_port->close(); 
} 

int Serial::available(void) const 
{ 
    int num_bytes = _p_port->bytesAvailable(); 
    return num_bytes; 
} 

bool Serial::availableForWrite(void) const 
{ 
    if (_p_port->isWritable()) 
     return true; 
    return false; 
} 

void Serial::flush() 
{ 
    _p_port->flush(); 
} 

unsigned long Serial::write(uint8_t c) 
{ 
    if (_p_port->putChar(c)) 
     return 1; 
    return 0; 
} 

unsigned long Serial::write(uint8_t *p_data, unsigned long maxSize) 
{ 
    return _p_port->write(reinterpret_cast<const char *>(p_data), (qint64)maxSize); 
} 

int Serial::read(void) 
{ 
    char c; 
    _p_port->getChar(&c); 
    return c; 
} 

void Serial::reset(void) 
{ 
    _p_port->clear(QSerialPort::AllDirections); 
    _p_port->clearError(); 
} 

bool Serial::isError(void) const 
{ 
    if (_p_port->error() == QSerialPort::NoError) 
     return false; 
    return true; 
} 

そして、私のmain.cppに:あなたはかなりのために必要なすべてのものを見逃している

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    MainWindow w; 
    // w.show(); 

    Serial serial("ttyACM0"); 
    if (serial.begin(115200)) 
     std::cout << "Failed to set Baud rate" << std::endl; 
    std::cout << "Sending data" << std::endl; 
    // QObject::connect(&(serial.getPort()), SIGNAL(readyRead()), &serial, SLOT(readyBe())); 
    serial.print("list\r"); 
    serial.flush(); 

    while (true) { 
     while (true) { 
      while (serial.available() == 0) { 
       if (serial.isError()) { 
        std::cout << "Error" << std::endl; 
        // serial.reset(); 
       } 
      } 

      char c = serial.read(); 
      std::cout << c; 
      if (c == '\n') 
       break; 
     } 
     std::cout << std::endl; 
    } 

    return a.exec(); 

} 
+0

「QSerialPortを使用して何も読み取れません」というのは質問ではありません。最後に疑問符を追加しても問題にはなりません。それは非常に無知なアメリカ主義であり、世界の他の地域の人々がそれを使用するのを見るのは悲しいことです。 –

+1

@MikeNakis:タイトルを編集しました。 – abhiarora

+0

あなたは 'QSerialPort'自体でエラーチェックをしているようには見えません - 何が起きているのかを確認するために利用できるさまざまなシグナルに' connect'する必要があります。 'Serial'コンストラクタで' _p_port-> open'が失敗した場合、 '_p_port'を削除する前に即座に例外をスローします。 –

答えて

1

このコードは動作する:イベントループ。現実のI/Oは非同期です。データが利用可能になったときに通知を得る手段を持たずに、ポートから「読み込む」だけでは、実際に非同期I/O要求を処理させることはできません。はい、これを可能にするいくつかの従来のAPIがありますが、スパゲッティコード、スレッドの無駄使い、パフォーマンスの低下がほとんどです。

while (serial.available() == 0)ループはノーオペレーションです。実際にはavailable()が他の値を返すことはありません。 available()は内部的にはクラスの整数メンバーとして読み込まれます。そのメンバに格納されている値を更新できるコードは決して実行しないでください。これをserial.waitForReadyRead()に変換しても、で利用可能なバイト数を更新しますが、まだイベントループが回転していないため、タイムアウトを処理できず、アプリケーションに他のイベントに反応することもできませんに反応する必要があります。 QIODevice::waitForReadyReadは、1つのことを行うことを意味します。readyReadシグナルが発射されたときに戻る。他のイベントは処理されず、コードをポートするために使用される松葉杖であり、実際にはプロダクション用に使用されるものではありません。

QSerialPortの信号で非同期でコードを再設計する必要があります。仕事はQCoreApplication::execの中から行われます - あなた自身のループはありません。この制御の逆転は、非同期I/Oを動作させるためには不可欠です。

非同期アプローチの非常に単純な例ではthis answer、より完全なアプローチではthis answerです。

関連する問題