Russian Qt Forum
Сентябрь 30, 2024, 14:40 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QSerialPort принимает пакет два раза  (Прочитано 3313 раз)
vorotislav
Гость
« : Февраль 05, 2015, 09:23 »

Доброго времени суток.
Есть класс, в котором объект класса QSerialPort. Его сигнал readyRead(), связан с моим слотом.
Слот сначала говорит, что минимальный размер пакета должен быть 15 байт, затем делает первичный разбор пакета на наличие синхробайта. (Если синхробайт первый в пакете - все отлично. Но проверяем каждый последующий байт. Если опять синхробайт - значит уже другой пакет.)
Ниже сам код.
Код:
void SPort::slotReadPort()
{
    QByteArray arrayFromPort, arrayRecieve;
    arrayFromPort.clear();
    arrayRecieve.clear();
    quint64 buf = _port.bytesAvailable();
    quint64 minBuf = 15;
    QString packet;

    if (buf < minBuf)
        return;
    else {
        arrayFromPort = _port.read(buf);
        packet = arrayFromPort.toHex();

        for (int i = 0; i < arrayFromPort.size(); i++) {
            switch (arrayFromPort.at(i)) {
            case 00: { // синхробайт
                if (i == 0) {
                    arrayRecieve.append(arrayFromPort.at(i));
                    break;
                } else {
                    if (i < (minBuf - 1)) {
                        for (int z = 2; z < packet.size(); z += 3)
                            packet.insert(z, ' '); // для ведения лога удобнее читать по байтам, вот и делю
                        emit signalMessageOutPort("<< " + _port.portName() + " -- пришел битый пакет: " + packet); //не большой лог в главном окне программы
                        emit signalMessageToLog("<< " + _port.portName() + " -- пришел битый пакет: " + packet); // основной лог
                        arrayRecieve.clear();
                        arrayFromPort.clear();
                        packet.clear();
                        goto stop; // выход полностью из слота
                        break;
                    } else {
                        QString msg = arrayRecieve.toHex();
                        for (int z = 2; z < msg.size(); z += 3)
                            msg.insert(z, ' ');
                        emit signalMessageToLog("<< " + _port.portName() + " -- " + msg);
                        emit signalArrayOutPort(arrayRecieve);
                        arrayFromPort.clear();
                        arrayRecieve.clear();
                        goto stop;
                        break;
                    }
                    break;
                }
            }
            default:{
                arrayRecieve.append(arrayFromPort.at(i));
                break;
            }
            }
        }
        if (arrayRecieve.size() >= minBuf) {
            QString msg = arrayRecieve.toHex();
            for (int z = 2; z < msg.size(); z += 3)
                msg.insert(z, ' ');
            emit signalMessageToLog("<< " + _port.portName() + " -- " + msg); // основной лог
            emit signalArrayOutPort(arrayRecieve); // передача пакета для дальнейшего разбора
            arrayFromPort.clear();
            arrayRecieve.clear();
            _port.clear(QSerialPort::Input);
            return;
        }
    }
    stop:
    arrayFromPort.clear();
    arrayRecieve.clear();
    _port.clear(QSerialPort::Input);
}

Беда в том, что иногда пакеты приходят дважды. Помогите решить проблему. Отправляются точно по одному пакету (смотрю через qDebug()). Заранее благодарен
Записан
vorotislav
Гость
« Ответ #1 : Февраль 05, 2015, 09:29 »

В основном логе вот такая картина:

05.02.2015 11:26:29 | << COM7 -- 00 22 11 f0 bb dd f0 f0 f0 11 f0 44 ee 0f f0
05.02.2015 11:26:29 | << COM3 -- 00 22 11 f0 f0 ee f0 f0 f0 11 f0 c3 22 11 0f
05.02.2015 11:26:29 | << COM5 -- 00 22 77 f0 77 dd f0 f0 f0 11 f0 88 ee c3 f0 // вот эти две строки
05.02.2015 11:26:29 | << COM5 -- 00 22 77 f0 77 dd f0 f0 f0 11 f0 88 ee c3 f0
05.02.2015 11:26:29 | << COM7 -- 00 22 f0 f0 77 dd f0 f0 f0 11 f0 3c bb 77 3c

Возможно ли такое, что сигнал readyRead испускается дважды, если да, то как "обнулить" сигнал?
Записан
Bepec
Гость
« Ответ #2 : Февраль 05, 2015, 10:53 »

Ответ - врядли. Сериалпорт работает стабильно и без таких выкидонов. Значит ищите ответ в своём коде.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #3 : Февраль 05, 2015, 13:49 »

Для проверки достаточно запихнуть qDebug() в слот:

Код
C++ (Qt)
Foo::slotReadyRead()
{
   QByteArray data = port->readAll();
   qDebug() << data; // тут нужно преобразовать в toHex
}
 
Записан

ArchLinux x86_64 / Win10 64 bit
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.092 секунд. Запросов: 23.