crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Чтение из порта при помощи QSerialPort
borune
  опции профиля:
сообщение 20.11.2015, 16:04
Сообщение #1


Участник
**

Группа: Участник
Сообщений: 152
Регистрация: 1.1.2011
Пользователь №: 2314

Спасибо сказали: 0 раз(а)




Репутация:   0  


День добрый, господа.

Вопрос такой. Есть порт с перемычкой между TxD и RxD. Пишу в порт данные и читаю их же. Использую QtSerialPort в полной аналогии с примером (terminal example). Проблема заключается в чтении данных. Есть слот, приконнекченный к сигналу readyRead() объекта. Когда в порте появляются данные, этот слот вызывается всякий раз, когда размер этих данных равен 8 Байтам. Например, если размер считываемых данных составляет 14 Байт, слот вызывается 2 раза, если 27 Байт - 4 раза, 248 Байт - 31 раз. Т.е. порт ведет себя так, как будто бы размер буфера равен 8. Суть проблемы в том, что из-за вышеперечисленного невозможно отследить момент, когда все доступные данные считаны из порта:
Раскрывающийся текст
MainWindow::MainWindow(QWidget *parent) :    QMainWindow(parent)
{
       ...
       serial = new QSerialPort(this);
       serial->setReadBufferSize(0);
       connect(serial, SIGNAL(readyRead()), SLOT(readData()));
       ...
}
void MainWindow::readData()
{    
    port_data.append(serial->readAll());
    if(serial->bytesAvailable()==0){
      // здесь должна быть обработка всех полученных данных      
    }
}
При каждом вызове слота readData() условие if(serial->bytesAvailable()==0) по непонятной для меня причине оказывается верно. Так же, как и верно условие if(serial->atEnd()). Как победить это? В идеале хотелось бы, чтоб все данные считывались сразу, за один заход в слот readData(). Ну, на крайний случай, пускай заходит в него сколько угодно раз, но чтоб можно было б как-то отследить момент, когда все данные считаны.

UPD
Если добавить небольшой лок перед чтением, т.е.
Раскрывающийся текст
void MainWindow::readData()
{    
    QThread::msleep(400);
    port_data.append(serial->readAll());
    ...
}
то чтение происходит за 2 захода в метод readData() - в первый раз считывается 8 Байт, затем все остальное.

Я ничего не понимаю.

Сообщение отредактировал borune - 20.11.2015, 16:42
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 20.11.2015, 18:28
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(borune @ 20.11.2015, 18:04) *
условие if(serial->bytesAvailable()==0) по непонятной для меня причине оказывается верно
Всё верно, ты их строкой выше все вычитал (а остальное ещё не пришло, если вообще должно было).
т.е. метод QtSerialPort ::bytesAvailable() обязан вернуть столько же сколько вернёт QtSerialPort ::readAll().size()

Обычно используют либо таймаут по приёму, либо управление потоком (неважно каким, например, передавая сигнальные/флаговые байты в начале и конце посылки)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
borune
  опции профиля:
сообщение 21.11.2015, 23:52
Сообщение #3


Участник
**

Группа: Участник
Сообщений: 152
Регистрация: 1.1.2011
Пользователь №: 2314

Спасибо сказали: 0 раз(а)




Репутация:   0  


Ну все равно непонятно. Я же данные посылаю за раз. Логично предположить, что и приходить они должны разом, а не кусками. Насчёт условия да, вы правы, но вопросы все равно остаются. Главный из них это как заставить порт читать не кусками по 8 байт, а сразу все? WaitForReadyRead() не помогает..

Сообщение отредактировал borune - 21.11.2015, 23:54
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 22.11.2015, 10:43
Сообщение #4


Профессионал
*****

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


8 байт - FIFO буффер COM порта. когда он заполняется, вызывается аппаратное прерывание, которое получает система и система уже дёргает юзерские коллбэки.
в принципе, размер буффера бывает 1,4,8 или 14 байт. видимо, в данном случае их 8. это совершенно нормально. в железе данные всегда режутся на куски и потом на другой стороне склеиваются.
определение конца пакета - это уже более верхний уровень, о котором COM-порт ничего не знает. он передаёт байты.
накручивай хэдер и длину пакета (можно ещё CRC для контроля целостности) в свои пакеты и разгребай поток с порта.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 28.3.2024, 17:41