crossplatform.ru

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

 
Ответить в данную темуНачать новую тему
> QSerialPort, Обработка пакетов
leonneon_89
  опции профиля:
сообщение 2.7.2015, 13:10
Сообщение #1


Студент
*

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

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




Репутация:   0  


Всем привет! Возникла небольшая сложность в получении данных по RS-485. Использую библиотеку QtSerialPort.
Есть протокол в котором взаимодействуют компьютер с неким устройством по сети RS-485. Размер запросных сообщений от устройства 16 байт. Первые два байта описывают тип сообщения.
Размер ответных сообщений от компьютера различный, как и в запросном сообщении первые два байта описывают тип сообщения.

Вот примерный класс для обработки полученных сообщений.

#include "opuConnectionRS485.h"
#include <QDebug>
#include "opuRequestMessage.h"
#include <unistd.h>

ConnectionRS485::ConnectionRS485(QString com_portName, int com_baudrate, QObject *parent) :
    QObject(parent), portName_(com_portName), baudrate_(com_baudrate)
{
    initSettings();

    port_->setReadBufferSize(messageLength);
    int portState = port_->open(QIODevice::ReadWrite);
    if(portState)
    {
        qDebug()<< "[ConnectionRS485]. Good open port:" << portName_ << "baudrate:" << baudrate_;
        connect(port_, SIGNAL(readyRead()), SLOT(getMessage()));

    }else{
        qDebug()<< "[ConnectionRS485]. Error open port:" << portName_ << "baudrate:" << baudrate_;
    }
}

void ConnectionRS485::initSettings()
{
    port_ = new QSerialPort;
    port_->setPortName(portName_);
    port_->setBaudRate(baudrate_);
    port_->setDataBits(QSerialPort::Data8);
    port_->setParity(QSerialPort::NoParity);
    port_->setStopBits(QSerialPort::OneStop);
    port_->setFlowControl(QSerialPort::NoFlowControl);
}

void ConnectionRS485::getMessage()
{    
    QByteArray message;
    if(port_->bytesAvailable() >= messageLength)
    {
        message = port_->read(messageLength);
        emit sendMessage(message);
    }
}

void ConnectionRS485::changePortSettings(QString port, int baud)
{
    qDebug() << "[ConnectionRS485]. Change port setting port:" << port << " baudrate:" << baud;

    port_->setPortName(port);
    port_->setBaudRate(baud);
    port_->setDataBits(QSerialPort::Data8);
    port_->setParity(QSerialPort::NoParity);
    port_->setStopBits(QSerialPort::OneStop);
    port_->setFlowControl(QSerialPort::NoFlowControl);
}

void ConnectionRS485::writeMessage(QByteArray message)
{
    port_->write(message);
    port_->flush();
}


Когда я напрямую передаю сообщения (тестовое соединение в компьютере из одного порта в другой) все вроде нормально работает. А когда работаю с реальным устройством т.е. компьютер
принимает запросные сообщения от устройства(messageLength == 16 байтов) и посылает на этот запрос ответные сообщения запрашиваемому устройству, тогда порой возникают ошибки. В этой сети иногда
проскальзывают ненужные байты, и тогда принятое сообщение в 16 байт уже имеет другие данные, в следствие чего не могу нормально обработать поступивший запрос и отослать ответное сообщение. Вопрос, как мне
правильно считывать поступающие данные, если в сети иногда возникают другие байты данных. Заранее спасибо.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
leonneon_89
  опции профиля:
сообщение 6.7.2015, 16:56
Сообщение #2


Студент
*

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

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




Репутация:   0  


А может кто-нибудь знает как вытаскивать из "потока" нужное сообщение? Например есть сеть rs-485 в виде общей шины, в которой гуляют различные сообщения с различной длинной.
Есть так же определенные(необходимые нам) запросные сообщения с заданной длинной, в которых первые два байта обозначают тип сообщения. Как я могу из всех входящих сообщений,
вытащить нужное мне сообщение? Спасибо за ответ=).
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 6.7.2015, 18:27
Сообщение #3


Старейший участник
****

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

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




Репутация:   8  


На такой шине, где гуляют сообщения с разной длинной должен быть контролер, который инициирует передачу и следит чтобы в каждый момент передавалось только одно сообщение.
Почитайте например про MODBUS
http://www.csimn.com/CSI_pages/Modbus101.html
Для него есть готовая библиотека
http://libmodbus.org
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 7.7.2015, 10:10
Сообщение #4


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

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

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




Репутация:   12  


чем длиннее провод - тем ниже должна быть скорость передачи.
и на проводе должны быть терминаторы. если их нет, то скорее всего в сигнале будут отражённые паразитные данные.
да, если в непосредственной близости присутствуют двигатели, трансформаторы или любые девайсы с мощными токами в обмотках, то возможны помехи на линии и данные также могут искажаться.
в целом от подобных вещей спасает только вычисление CRC на каждый пакет и нумерация пакетов плюс система перезапроса пакета, в случае его потери или испорченных данных.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
leonneon_89
  опции профиля:
сообщение 7.7.2015, 13:52
Сообщение #5


Студент
*

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

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




Репутация:   0  


Цитата(lanz @ 6.7.2015, 18:27) *
На такой шине, где гуляют сообщения с разной длинной должен быть контролер, который инициирует передачу и следит чтобы в каждый момент передавалось только одно сообщение.
Почитайте например про MODBUS
http://www.csimn.com/CSI_pages/Modbus101.html
Для него есть готовая библиотека
http://libmodbus.org

Спасибо за ответ, я посмотрю его. В общем контроллер разрабатывает другой программист, и сделан он на плате плис. Как я понял у него будет это реализовано по типу протокола modbus.
А вот еще один вопрос, что если мне приходящие куски пакетов анализировать и искать в них два байта, которые отвечают за тип сообщения, если два байта найдены, считывать оставшуюся часть пакета,
иначе отбрасывать прочитанный кусок и анализировать приходящие сообщения, пока нужный пакет с байтами не будет найден. Как вам такой подход? В реализации modbus, как я понимаю признак конца сообщения, это какая то пауза. Я просто пока плохо понимаю как применить это к протоколу.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 7.7.2015, 16:33
Сообщение #6


Старейший участник
****

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

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




Репутация:   8  


Цитата
А вот еще один вопрос, что если мне приходящие куски пакетов анализировать и искать в них два байта, которые отвечают за тип сообщения, если два байта найдены, считывать оставшуюся часть пакета,

В принципе нормальный подход, главное не перепутать эти два байта с двумя байтами данных, которые выглядят так же.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

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


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




RSS Текстовая версия Сейчас: 4.12.2024, 11:54