Я пытаюсь подключить микроконтроллер к настольному ПК через USB-кабель.
Операционная система моего настольного ПК — Windows 8.1, а USB-последовательный кабель — TTL-232R-3V3. (FTDI)
(Версия Qt: 5.2.0 beta1, Версия QtCreator: 3.0, Компилятор: MSVC2012)
Сейчас я пытаюсь выполнить тестирование с обратной связью для чтения / записи, и поэтому контакты RX / TX USB-последовательного кабеля соединены друг с другом.
Вот мой код
#include <QtCore/QCoreApplication>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QtCore/QDebug>
#define PORT_NAME "COM3"#define BAUDRATE 19600
#define TIMEOUT_MS 1000
QT_USE_NAMESPACE
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QSerialPort pSerial(PORT_NAME);
const char strMsg[] = "#1:Send data line \n #2:Send data line\n #3:Send data line end\n";
char strBuf[256];
qint64 nByte;if(pSerial.open(QIODevice::ReadWrite)){
pSerial.setBaudRate(BAUDRATE);
qDebug() << "OPEN PASS";
pSerial.write(strMsg);
pSerial.flush();
if(pSerial.waitForBytesWritten(TIMEOUT_MS)){
qDebug() << "WRITE PASS";
}pSerial.waitForReadyRead(TIMEOUT_MS);
while(true){
if( pSerial.canReadLine()){
qDebug() << "CAN READ LINE";
nByte = pSerial.readLine(strBuf,sizeof(strBuf));
qDebug() << "Length: " << nByte;
qDebug() << "Read data: " << strBuf;
}
}
pSerial.close();
} else {
qDebug() << "OPEN FAIL\n";
}
return a.exec();
}
Когда программа начинает работать, результат отличается от того, что я ожидал.
Может быть получена только первая строка отправленных данных. Итак, «Чтение данных: # 1 Отправить строку данных» печатается
на консоли. Но остальные отправленные данные никогда не будут получены. Кто-нибудь знает почему?
Любая помощь будет оценена.
Заранее спасибо.
РЕДАКТИРОВАТЬ: Я пересмотрел свой код в соответствии с комментарием Паппа. Затем он работает, как я ожидал.
Все отправленные сообщения были получены.
Означает ли это, что я неправильно понимаю использование readLine () или canReadLine ()?
// while(true){
// if( pSerial.canReadLine()){
// qDebug() << "CAN READ LINE";
// nByte = pSerial.readLine(strBuf,sizeof(strBuf));
// qDebug() << "Length: " << nByte;
// qDebug() << "Read data: " << strBuf;
// }
// }
pSerial.waitForReadyRead(TIMEOUT_MS);
QByteArray readData = pSerial.readAll();
while (pSerial.waitForReadyRead(TIMEOUT_MS)) {
readData.append(pSerial.readAll());
}
qDebug() << "Read data: " << readData;
РЕДАКТИРОВАТЬ 2-й раз : Следующий код также работает для меня.
while(true){
if( pSerial.waitForReadyRead(TIMEOUT_MS) && pSerial.canReadLine()){ // I revised this line
qDebug() << "CAN READ LINE";
nByte = pSerial.readLine(strBuf,sizeof(strBuf));
qDebug() << "Length: " << nByte;
qDebug() << "Read data: " << strBuf;
qDebug() << "Error Message: " << pSerial.errorString();
}
}
Это потому, что вам нужно читать в цикле, как это:
QByteArray readData = serialPort.readAll();
while (serialPort.waitForReadyRead(5000))
readData.append(serialPort.readAll());
Пожалуйста, смотрите creadersync
пример для деталей, что я добавил в 5.2. Вы также можете проверить creaderasync
пример для неблокирующей операции.
Честно говоря, мы не так много тестировали readLine, но он работает для меня в Unix, так же как и в Windows для кого-то другого.
Вы допустили ошибку, ожидая получить все отправленные данные, когда waitForReadyRead
возвращается. когда waitForReadyRead
все, что вам гарантировано некоторые данные быть доступным для чтения. Это может быть всего один символ, не обязательно целая строка.
Цикл из вашей последней модификации — это почти правильный способ сделать это. Вы должны вкладывать чтение строк в отдельный цикл. Следующий код, как это должно быть сделано, и согласуется с семантикой QIODevice
:
while (pSerial.waitForReadyRead(TIMEOUT_MS)) {
while (pSerial.canReadLine()) {
qDebug() << "NEW LINE";
QByteArray line = pSerial.readLine();
qDebug() << "Length: " << line.size();
qDebug() << "Read data: " << line;
qDebug() << "Error Message: " << pSerial.errorString();
}
}
qDebug << "TIMED OUT";
Обратите внимание, что ни один из этого кода не должен даже выполняться в потоке GUI. В идеале вы должны переместить его в объект QObject, использовать сигналы, излучаемые QIODevice
(и поэтому QSerialPort
) и переместить этот объект в отдельный поток.
Поток GUI может иногда блокироваться на длительные периоды времени, обычно нежелательно, чтобы он нарушал своевременность связи вашего устройства. Точно так же вы не хотите, чтобы таймауты устройства блокировали поток GUI. Оба одинаково плохи и являются очень распространенным источником плохой пользовательский опыт. Qt делает многопоточность очень простой — используйте ее ради своего пользователя и делайте это правильно.