C++ (Qt)mcu->Send("Команда");if(mcu->Read()=m_Ok);//Получаем ответ{ //Команда прошла успешно}
C++ (Qt)#ifndef MCU_H#define MCU_H #include <QObject> class QSerialPort;class QTimer; class MCU : public QObject{ Q_OBJECTpublic: explicit MCU( QObject *parent = nullptr ); void addRequest( int val ); private slots: void nextRequest(); void readyData(); void timeout(); private: QSerialPort *m_port; QTimer *m_timer; using RequestQueue = QList<int>; RequestQueue m_requests;}; #endif // MCU_H
C++ (Qt)#include "mcu.h"#include <QSerialPort>#include <QTimer> MCU::MCU( QObject *parent ) : QObject( parent ), m_port( new QSerialPort( this ) ), m_timer( new QTimer( this ) ){ // Настраиваем порт connect( m_port, SIGNAL(readyRead()), SLOT(readyData()) ); // Настраиваем таймер connect( m_timer, SIGNAL(timeout()), SLOT(timeout()) ); m_timer->setSingleShot( true ); m_timer->setInterval( 250 );} void MCU::addRequest( int val ){ // Добавляем запрос в очередь m_requests.append( val ); nextRequest();} void MCU::nextRequest(){ if( m_requests.isEmpty() ) return; // Получаем запрос но оставляем его в очереди int request = m_requests.first(); QByteArray data; m_port->write( data ); // Отправили запрос m_timer->start(); // Запустили таймер ожидания ответа // Теперь сработает один из сигналов: пришли данные (readyRead) // или сработал таймер (timeout)} void MCU::readyData(){ // Пришли данные от устройства // Останавливем таймер m_timer->stop(); // Читаем ответ из порта QByteArray result = m_port->readAll(); // В очереди есть запрос if( m_requests.isEmpty() ) { // Получаем запрос на который пришел ответ и удаляем его из очереди int request = m_requests.takeFirst(); // Обрабатываем ответ // ... // Переходим к следующему запросу nextRequest(); }} void MCU::timeout(){ // Ответ не пришел во время // В очереди есть запрос if( m_requests.isEmpty() ) { // Получаем запрос на который пришел ответ и удаляем его из очереди int request = m_requests.takeFirst(); // Обрабатываем ошибку по таймауту // ... // Переходим к следующему запросу nextRequest(); }}
C++ (Qt) class Foo : public QObject{public: Foo() { // конфигурим сторожа watchdog->setSingleShot(true); watchdog->setInterval(100); connect(watchdog, &QTimer::timeout, [this]() { if (serial->bytesAvailable() == 0) { // это ошибка по таймауту, у-во вообще ничо не ответило } else { // извлекаем весь ответ, т.к. он будет полным const QByteArray response = serial->readAll(); // что-то делаем с ответом, парсим его и пр. } sendNextRequest(); // шлем следующий запрос из очереди }); // шлем запросы по таймеру connect(timer, &QTimer::timeout, [this]() { const QByteArray request1 = ....; appendRequest(request1); }); // шлем запросы по кнопке 1 connect(button1, &QPushButton::clicked, [this]() { const QByteArray request2 = ....; appendRequest(request2); }); // шлем запросы по кнопке N connect(buttonN, &QPushButton::clicked, [this]() { const QByteArray requestN = ....; appendRequest(request3); }); // перезапускаем сторожа чтобы он не срабатывал, т.к. когда он сработает это будет // означать или таймаут или весь пакет принят connect(serial, &QSerialPort::readyRead, [this]() { watchdog->start(); } private: void appendRequest(const QByteArray &request) { pendingRequests << request; sendNextRequest(); } void sendNextRequest() { if (watchdog->isActive() || pendingRequests.isEmpty()) return; const QByteArray request = pendingRequests.takeFirst(); serial->write(request); watchdog->start(); } QList<QByteArray> pendingRequests; QSerialPort *serial; QTimer *watchdog;}