Просмотр сообщений
|
Страниц: [1]
|
2
|
Qt / Вопросы новичков / Re: QSerial приём данных
|
: Ноябрь 08, 2020, 21:18
|
не должна функция делать и запись и чтение, разделяй и переписывай код и никаких sleep и waitForReadyRead - не нужно
Поскольку это мой дебют в QT - можно по подробнее: в чем проблема если даю запрос потом пауза и чтение (про GUI не надо рассказывать) Нет. Догадываюсь, в чём у вас проблема. waitForReadyRead вам нужен тут только для того, чтобы хоть как то отдать время центральному процессору. Тут надо либо по-другому строить архитектуру (чтобы нормально использовать сигналы-слоты) либо в цикле (при ожидании) периодически вызывать QCoreApplication::processEvents. Ну и, при полном приёме данных (после заполнения буфера полезными данными), лучше взвести какой-нибудь флаг. Либо выпустить сигнал. Хотя тут "на вкус и цвет все фломастеры разные" Может я заблуждаюсь - поправьте, когда данные приходят в COM порт они складываются сначала в буфер винды и выполнение этого процесса никоим образом не касается выполнения QTшного кода, а когда дело у QT доходит до забора данных с буфера COM порта - QT фактически забирает эти данные с памяти (с буфера винды) а не непосредственно с COM порта. Как бы тема для новичков, но некоторые ответы просто "убивают"
|
|
|
3
|
Qt / Вопросы новичков / Re: QSerial приём данных
|
: Ноябрь 08, 2020, 17:10
|
Заголовочный файл нужен ? mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include "sendcom.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this);
QString PORT="COM4"; sendCom.setPORT(PORT);// Устанавливаем номер порта if(!sendCom.InitPort())qDebug<<"Что то не получилось с "<<PORT;
qDebug()<<"Получилось подключится к "<<PORT;
}
sendcom.cpp #include "sendcom.h" #include <QDebug>
SendCom::SendCom(QObject *parent) : QObject(parent)//,
{
//qDebug("Potok SendCom telo"); //qDebug()<<"Telo Thread:"<<QString::number((int)QThread::currentThreadId()); }
bool SendCom::InitPort() { if(!InitSerial())return false;
if(!SendAndRead()) { serial->close(); return false; } qDebug()<<PORT<<" Read:"<<QString(m_arrCom.toHex().toUpper());
serial->close(); return true; }
bool SendCom::InitSerial() { qDebug()<<"Init START "<<PORT; serial=new QSerialPort(this); serial->setPortName(PORT); serial->setBaudRate(QSerialPort::Baud38400); serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl);
if(!serial->open(QSerialPort::ReadWrite)) { qDebug()<<"ERROR !!! Не могу открыть порт "<<PORT; return false; }
connect(serial, SIGNAL(readyRead()), this, SLOT(read())); connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(errorSerial(QSerialPort::SerialPortError))); return true; }
bool SendCom::SendAndRead() { serial->clear(); w_arrCom.clear();//Очищаем массив перед подготовкой пакета
w_arrCom = QByteArray::fromHex("010404020001913A");
quint8 lenRead=........;//Вычисление длины ответа от устройства
for (quint8 i=0;i<2;i++)//Две попытки отправки запроса и получения ответа { qDebug()<<"Попытка №"<<QString::number(i+1); serial->write(w_arrCom);// Запись в последовательный порт
this->thread()->msleep(qCeil(150));// Засыпаем, ожидая, пока микроконтроллер обработает данные и ответит. m_arrCom.clear();//Очищаем буфер перед приёмом данных
serial->waitForReadyRead(300);//Без этой команды данные не приходят в буфер от слова СОВСЕМ)))
if (m_arrCom.size()==lenRead) break; else{ qDebug<<"Ответ не подходит по длине Bytes read: "<<QString::number(m_arrCom.size()) <<" lenRead:"<<QString::number(lenRead);
} serial->clear(); } if (m_arrCom.size()!=lenRead) return false;
return true; }
void SendCom::read() {
//qDebug()<< "Доступно: "<<serial->bytesAvailable(); m_arrCom += serial->readAll(); }
void SendCom::errorSerial(QSerialPort::SerialPortError err) { qDebug()<<"SendCom Error: "+serial->errorString();//QString::number(err); }
void SendCom::setPORT(QString m_PORT) { if (PORT == m_PORT) return;
PORT = m_PORT; }
|
|
|
4
|
Qt / Вопросы новичков / Re: QSerial приём данных
|
: Ноябрь 08, 2020, 15:09
|
Трудно гадать без исходников, но по симптомам - отсутствует цикл обработки событий. Код в первом посте http://www.prog.org.ru/index.php?topic=32856.msg243311#msg243311 изменение времени задержки проблему появления ошибки таймаута не решают. Код обработки ошибок: connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(errorSerial(QSerialPort::SerialPortError)));
void SendCom::errorSerial(QSerialPort::SerialPortError err) { qDebug()<<"SendCom Error: "+serial->errorString();//QString::number(err); }
|
|
|
5
|
Qt / Вопросы новичков / Re: QSerial приём данных
|
: Ноябрь 08, 2020, 13:24
|
Спасибо всем кто отписался.... Свистков у меня 2 - мой на FTDI, и клиентский на PL2303 - поведение одинаковое. Самый стабильный приём получился при приёме данных по сигналу readReady(). Один из моментов которые я не могу понять это почему этот сигнал появляется только после пользования waitForReadyRead(), но больше всего БЕСИТ !!!!!!!!!!! появление ошибки таймаут после пользования waitForReadyRead(), причём независимо от длительности задержки. Версия QT 5.15.1. Программа проверялась и на 10ке и на 7ке. Железо на 10ке значительно сильнее, но при этом по сигналу readReady() на 10ке всегда принимается исключительно по 1му байту, в то время как на 7ке при приёме пакета 7 байт за один раз залетало и 4 байта(размер буфера и задавал и не задавал) - этот момент также непонятен.... Может комуто мои изыскания будут полезны.......... P.S. Весь гемморой начался после того как рабочая программа с использованием QModbusRtuSerialMaster на I5 не захотела работать на более слабом железе и пришлось связь по MODBUS реализовывать через QSerialPort
|
|
|
6
|
Qt / Вопросы новичков / Re: QSerial приём данных
|
: Ноябрь 06, 2020, 22:34
|
Считывал данные не юзая сигнал readyRead()? Или вообще не юзая QSerialport?
Перенёс проект на Win10 - поведение точь точь как и на семёрке....... Версия QT везде 5.15. Как то странно чтобы такие "детские" баги до сих пор имели место.......... Может ктото из гуру всё таки подскажет куда копать ?
|
|
|
8
|
Qt / Вопросы новичков / QSerial приём данных
|
: Ноябрь 06, 2020, 19:32
|
Если не затруднит когото кто досконально знает работу QSerial объясните пожалуйста как правильно принимать данные. Пересмотрел, перегуглил, перепробовал разные варианты, но так и не понял как это правильно делать . Можно ли принимать данные не используя сигнала - у меня не получилось. . Сигнал у меня испускается только после выполнения serial->waitForReadyRead(100); Число принимаемых данных небольшое 10-50 байт. Данные принимаются после отправки запроса (с этим проблем нет). Самое неприятное (что собственно и подвигло к написанию данного поста) это возникновение ошибки "TimeoutError" после выполнения команды waitForReadyRead. Значение задержки на появление ошибки не влияет. Данные принимаются полностью и с ошибкой "TimeoutError" следующим кодом: connect(serial, SIGNAL(readyRead()), this, SLOT(read())); . //Подготовка запроса для COM порта . . lenRead=.....//Расчёт длины пакета от микроконтроллера serial->write(m_arrCom);// Запись запроса в последовательный порт this->thread()->msleep(100);// Засыпаем, ожидая, пока микроконтроллер обработает данные и ответит. m_arrCom.clear();//Очищаем буфер перед приёмом данных serial->waitForReadyRead(300); if (m_arrCom.size()!=lenRead) outLog("Ответ не подходит по длине Bytes read: "+QString::number(m_arrCom.size()) +" tim:"+QString::number(tim_read.elapsed())+" lenRead:"+QString::number(lenRead));
void SendCom::read() { m_arrCom += serial->readAll(); }
|
|
|
9
|
Qt / Вопросы новичков / Re: QT 5.15 не хочет принять код стандартного примера
|
: Сентябрь 02, 2020, 12:40
|
Смотрел я документацию... Если бы всё понял и был бы не новичком, не задавал бы глупых вопросов уважаемым и занятым людям......... Строка на которую указали - это уже были истерические )) попытки исправить ситуацию (просто вставил две строки из похожего кода чтобы убедится что проблема не в компиляторе). Эта строка и предыдущая к данному коду не относятся....
|
|
|
10
|
Qt / Вопросы новичков / QT 5.15 не хочет принять код стандартного примера
|
: Сентябрь 02, 2020, 11:23
|
С помощью примера из просторов сети хочу разобраться с TCP соединением двух машин. Пример клиента скомпилился нормально, а пример сервера уже при написании ругается.... void MyServer::slotNewConnection() { QTcpSocket* pClientSocket = m_ptcpServer->nextPendingConnection(); connect(pClientSocket, SIGNAL(disconnected()), pClientSocket, SLOT(deleteLater()) ); connect(pClientSocket, SIGNAL(readyRead()), this, SLOT(slotReadClient()) );
sendToClient(pClientSocket, "Server Response: Connected!"); } void MyServer::slotReadClient() { QTcpSocket* pClientSocket = (QTcpSocket*)sender(); QTcpSocket *tcpSocket = (QTcpSocket*)sender(); QDataStream clientReadStream(&tcpSocket); QDataStream in(pClientSocket); in.setVersion(QDataStream::Qt_5_7); for (;;) { if (!m_nNextBlockSize) { if (pClientSocket->bytesAvailable() < sizeof(quint16)) { break; } in >> m_nNextBlockSize; }
if (pClientSocket->bytesAvailable() < m_nNextBlockSize) { break; } QTime time; QString str; in >> time >> str;
QString strMessage = time.toString() + " " + "Client has sended - " + str; m_ptxt->append(strMessage);
m_nNextBlockSize = 0;
sendToClient(pClientSocket, "Server Response: Received \"" + str + "\"" ); } } uploads
|
|
|
|
|