Поиск:

Ответ в темуСоздание новой темы Создание опроса
> инкапсуляция данных в пакет Xmodem 
:(
    Опции темы
daemonaz
Дата 8.1.2012, 13:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 160
Регистрация: 4.5.2008

Репутация: нет
Всего: нет



Я новичок в Qt, у меня цель написать код, который бы отправлял прошивку флеш микроконтроллера, подключенный к COM-порту,  по протоколу Xmodem, я создал отдельный класс Xmodem, но не знаю как правильно было бы реализовать инкапсуляцию данных из файла в пакет xmodem, есть ли у кого нибудь готовая реализация? Буду благодарен если кто-нибудь посоветует куда посмотреть.. Вопрос вот в чем, я использую в качестве пакета QByteArray, куда инкапсулирую данные прочитанные из файла, но получилось у меня довольно громоздко из трех массивов:   один -для данных, которые я извлек из файла, второй - для служебной информации пакета (SOH, num, ~num), затем слиянием двух массивов делаю третий и отправляю в COM-порт. Как сделать более компактно и быстро? Есть вариант с использованием сериализации DataStream, но не знаю как его использовать в данном случае
PM MAIL   Вверх
borisbn
Дата 8.1.2012, 17:48 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 48
Всего: 135



Цитата(daemonaz @  8.1.2012,  13:44 Найти цитируемый пост)
Как сделать более компактно и быстро?

Нормальное у тебя решение. Зачем тебе быстрее ? Передача по COM-порту всё равно на порядки медленнее, чем конкатинация двух массивов в третий.
Цитата(daemonaz @  8.1.2012,  13:44 Найти цитируемый пост)
Есть вариант с использованием сериализации DataStream, но не знаю как его использовать в данном случае

А вот это не советую, т.к. QDataStream добавлет в поток свои данные. Вот, почитай эту тему


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
daemonaz
Дата 8.1.2012, 23:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 160
Регистрация: 4.5.2008

Репутация: нет
Всего: нет



borisbn,  спасибо! 
Вот что получилось
Код


while (1)
{

// xbuff - буфер пакета, ybuff -  пакет данных с CRC
// затем конкатенацией их объединяем в один буфер xbuff

       xbuff.clear();

        xbuff.append(SOH);// стартовый байт
        xbuff.append(packetno);// номер пакета
        xbuff.append(~packetno);

        ybuff.clear();
        ybuff.append(src.left(128));// пишем блок из 128 байт данных
        src.remove(0, 128);

        ybuff.append(QByteArray().fill(CTRLZ, 128-ybuff.length()));
        ushort ccrc = crc16_ccitt(ybuff);
        ybuff.append((ccrc>>8) & 0xFF);
        ybuff.append(ccrc & 0xFF);

        xbuff.append(ybuff);

        qDebug("len %d\n\r", xbuff.length());

//////////////////////////////////////
        QString out;

        QTextStream str(&out);

        for (int i=0;i<xbuff.length();i++)
            str << QString().sprintf("%02X", xbuff.at(i));

        qDebug() << "Packet: " << out;

        /////////////////////////////////////////

//..................... отправка в COM-порт и ожидание подтверждения

        ++packetno;
        if (src.isEmpty())
            break;
}


Покритикуйте плиз код, это мой первый скажем так проект в QT, и заодно вопрос, хочу вывести на экран содержимое буфера побайтово, а выводится почему то в 32-хразрядном виде 0xffffffA5, как сделать чтобы массив выводился именно побайтово в виде 0xA5?
Спасибо

PM MAIL   Вверх
bsa
Дата 9.1.2012, 11:52 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 24
Всего: 196



мне только непонятно, а почему ты не отправляешь заголовок напрямую модему, а пихаешь во временный буфер? Так, думаю, было бы значительно более эффективно. Аналогично и с данными, т.е. ты читаешь их непосредственно перед отправкой. В этом случае будет значительно проще выполнить повтор передачи при возникновении ошибки (достаточно будет в очередь пакетов добавить номер повторяемого).

Цитата(daemonaz @  9.1.2012,  00:26 Найти цитируемый пост)
Покритикуйте плиз код, это мой первый скажем так проект в QT

QT = QuickTime. Не путай с Qt.
По возможности не используй sprintf, а используй arg().
Цитата(daemonaz @  9.1.2012,  00:26 Найти цитируемый пост)
выводится почему то в 32-хразрядном виде 0xffffffA5, как сделать чтобы массив выводился именно побайтово в виде 0xA5?
все аргументы передаются в объеме кратном int. Таким образом, когда ты передаешь char, то она автоматически конвертируется в int. А это приводит к тому, что все числа большие 0x7f будут отрицательными. Поэтому, тебе необходимо вручную преобразовать к беззнаковому целому, а уже потом передавать.
В твоем случае код подготовки к выводу можно переписать так:
Код
qDebug() << "Packet:" << QString::fromLatin1(xbuff.toHex());



Это сообщение отредактировал(а) bsa - 9.1.2012, 11:56
PM   Вверх
daemonaz
  Дата 11.1.2012, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 160
Регистрация: 4.5.2008

Репутация: нет
Всего: нет



bsa, спасибо! smile 
PM MAIL   Вверх
daemonaz
Дата 12.1.2012, 20:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 160
Регистрация: 4.5.2008

Репутация: нет
Всего: нет



Мне нужно отправить через COM-порт заготовленный пакет, но с ожиданием подтверждения, по протоколу xmodem, и чтобы не висеть в бесконечном цикле ожидания подтверждения по таймауту я хотел бы реализовать это через поток, но не знаю как это можно сделать, буду благодарен если будет примерчик такого способа реализации.. Планируется использовать при передаче файла QProgressDialog, где-то читал что можно реализовать через поток. Буду благодарен за любую помошь.
PM MAIL   Вверх
kuzulis
Дата 12.1.2012, 23:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 154
Регистрация: 5.9.2007

Репутация: нет
Всего: 1



Цитата

Мне нужно отправить через COM-порт заготовленный пакет, но с ожиданием подтверждения, по протоколу xmodem, и чтобы не висеть в бесконечном цикле ожидания подтверждения по таймауту я хотел бы реализовать это через поток, но не знаю как это можно сделать, буду благодарен если будет примерчик такого способа реализации.. 


Да не нужен тебе поток в этом случае, тем более, если не еще знаешь что это такое и как им пользоваться.
Используй сигналы/слоты для этого + QTimer для ожидания ответа.

Также рекомендуется использовать готовые библиотеки для I/O через Serial порты, т.к. не понятно как ты там реализуешь у себя I/O и т.п.

--

Также вместо crc16_ccitt() можно использовать Qt-шные функции (они вроде тоже могут считать CRC по разным там полиномам).



Это сообщение отредактировал(а) kuzulis - 12.1.2012, 23:11
PM MAIL   Вверх
daemonaz
Дата 13.1.2012, 08:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 160
Регистрация: 4.5.2008

Репутация: нет
Всего: нет



Цитата(kuzulis @  12.1.2012,  23:08 Найти цитируемый пост)
Используй сигналы/слоты для этого + QTimer для ожидания ответа.Также рекомендуется использовать готовые библиотеки для I/O через Serial порты, т.к. не понятно как ты там реализуешь у себя I/O и т.п.


Я использую библиотеку QextSerialPort, я обратил внимание на сигнал void QIODevice::readyRead () , он реализован в waitForReadyRead(), не это имели ввиду? Только хотелось бы понять механизм работы этой функции, или там сидим пока не придет сигнал, или же можем выполнять другую работу пока сигнал приема не придет? 

под Qt-шной функцией имеете ввиду qChecksum()? А где инициализируется полином?

Это сообщение отредактировал(а) daemonaz - 13.1.2012, 09:27
PM MAIL   Вверх
bsa
Дата 13.1.2012, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 24
Всего: 196



Цитата(daemonaz @  13.1.2012,  09:52 Найти цитируемый пост)
Только хотелось бы понять механизм работы этой функции, или там сидим пока не придет сигнал, или же можем выполнять другую работу пока сигнал приема не придет
это не функция, это сигнал. соединяешь со своим слотом и он вызывается, когда придут данные. Так же делаешь таймер и соединяешь его сигнал с другим своим слотом. Если он вызовется, значит время ожидания ответа истекло. Естественно, когда данные приходят таймер необходимо перезапускать.
Цитата(daemonaz @  13.1.2012,  09:52 Найти цитируемый пост)
А где инициализируется полином?
мне тоже интересно...
PM   Вверх
daemonaz
Дата 13.1.2012, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 160
Регистрация: 4.5.2008

Репутация: нет
Всего: нет



Цитата(bsa @  13.1.2012,  10:03 Найти цитируемый пост)
это не функция, это сигнал. соединяешь со своим слотом и он вызывается, когда придут данные. Так же делаешь таймер и соединяешь его сигнал с другим своим слотом. Если он вызовется, значит время ожидания ответа истекло. Естественно, когда данные приходят таймер необходимо перезапускать.


Я так понимаю это имеет смысль если реализованы отправка пакета и ожидание приема по отдельности, а если они в одной функции

Код


void mySerial::xmodemSend(const QString &fileName)
{
....

while (1)
{
     // подготовка пакета к отправке


     send(packet);

    // как раз вот здесь мне не хотелось бы сидеть и ждать, есть другие задачи, которые нужно выполнять

    bool flag = wait_(&s, TIMEOUT);
    if (flag){
         // принято подтверждение
    }// иначе таймаут, значит повторим или отмена

}

.......

}



А вообще сушествует ли готовый класс для работы с протоколом X-modem, Ymodem?

PM MAIL   Вверх
kuzulis
Дата 13.1.2012, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 154
Регистрация: 5.9.2007

Репутация: нет
Всего: 1



Цитата(daemonaz)

Я использую библиотеку QextSerialPort

Лучше эту https://gitorious.org/qserialdevice/qserial...ive-tarball/2.0

Цитата(daemonaz)

Я так понимаю это имеет смысль если реализованы отправка пакета и ожидание приема по отдельности, а если они в одной функции

Нене, так делать не нужно, т.к. твой цикл while(1), затормозит/приостановит Qt-шный Event loop и у тебя будут тормоза GUI
во время твоей транзакции.

Цитата(daemonaz)

А вообще сушествует ли готовый класс для работы с протоколом X-modem, Ymodem?

В Qt их точно нету. Да и что ты подразумеваешь под готовым классом? Что он должен делать? ;)

Цитата(bsa)

мне тоже интересно... 


Упс... Я думал что это запилили, судя по "утвердительным" высказываниям  на форумах:

http://developer.qt.nokia.com/forums/viewthread/13128
http://developer.qt.nokia.com/doc/note_rev...ns/136/229/view

Значит я ошибся :(

Это плохо, если нет такой возможности. 
Нужно запилить!!!  smile 

Это сообщение отредактировал(а) kuzulis - 13.1.2012, 12:53
PM MAIL   Вверх
daemonaz
Дата 13.1.2012, 16:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 160
Регистрация: 4.5.2008

Репутация: нет
Всего: нет



Цитата(kuzulis @  13.1.2012,  12:39 Найти цитируемый пост)
Цитата(daemonaz)Я так понимаю это имеет смысль если реализованы отправка пакета и ожидание приема по отдельности, а если они в одной функцииНене, так делать не нужно, т.к. твой цикл while(1), затормозит/приостановит Qt-шный Event loop и у тебя будут тормоза GUIво время твоей транзакции.


я как раз пытаю Вашу библиотеку, если Вы действительно его автор, а как надо правильно подкиньте идею.. 

PM MAIL   Вверх
bsa
Дата 13.1.2012, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 24
Всего: 196



daemonaz, открываешь порт (объект serial типа SerialPort). Открываешь файл (объект file типа QFile). Подключаешь сигнал readyRead к слоту readData (или как ты его назвал) твоего класса. Этот слот читает данные из порта при вызове. Теперь тебе необходимо отправить признак начала передачи и проинициализировать переменную - номер текущего блока.
Внутри readData ты читаешь данные из порта, на их основании принимаешь решение о дальнейших действиях. Если все нормально, ты посылаешь текущий блок, предварительно считав его в буфер. Или еще что-нибудь. Все. функция завершилась. Но когда придут очередные данные она снова будет вызвана.
PM   Вверх
kuzulis
Дата 13.1.2012, 17:24 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 154
Регистрация: 5.9.2007

Репутация: нет
Всего: 1



Цитата(daemonaz)

я как раз пытаю Вашу библиотеку, если Вы действительно его автор, а как надо правильно подкиньте идею.. 


вот идея:
Цитата(bsa)

это не функция, это сигнал. соединяешь со своим слотом и он вызывается, когда придут данные. Так же делаешь таймер и соединяешь его сигнал с другим своим слотом. Если он вызовется, значит время ожидания ответа истекло. Естественно, когда данные приходят таймер необходимо перезапускать.


т.е как то так:
Код


class Xmodem : public QObject
{
    Q_OBJECT
signals:
    void oneBlockTransactionComplete();

public:

    Xmodem() : m_currentSendBlockNumber(0) {
        m_port = new SerialPort(this);
        connect(m_port, SIGNAL(readyRead(), this, SLOT(checkAvailable()));
        ...
        // открываем порт, настраиваем
        ...
        
        m_timer = new QTimer(this);
        connect(m_timer, SIGNAL(timeout()), this, SLOT(processResponse()));
        m_timer->setInterval(100); // это максимальный интервал ожидания ответа от устройства, в мсек.
        ...

        connect(this, SIGNAL(oneBlockTransactionComplete(), this, SLOT(sendRequest()));
    }

public slots:

    void sendRequest(const QByteArray &request) {

        if (m_currentSendBlockNumber < maxSendBlockNumber) { // еще не все отправили
            m_timer->start();
            m_port->write(request);
        } else {
            // всё уже отправили
        }
    }

private slots:

    void checkAvailable() {
        if (m_port->dataAvailable() < expectedResponseSize) {
           // если пришло в буфер кол-во байт меньше чем ожидалось, то ничего не делаем
        } else {
            processResponse();       
        }

    void processResponse() {
        m_timer->stop();
        
        QByteArray response = m_port->read(expectedResponseSize);

        // тут проверяем CRC, разные поля и т.п.

        // если все ОК, то инкремент номера блока
        // чтобы послать следующий блок
        if (ok) { 
            ++m_currentSendBlockNumber;
        }

        emit oneBlockTransactionComplete();
    }

private:

    SerialPort *m_port;
    QTimer *m_timer;

    int m_currentSendBlockNumber;



Идея думаю ясна smile

А вообще, такого рода задачи необходимо делать через State Machine, оно тогда будет нагляднее и меньше ошибок сделаешь, ИМХО

Это сообщение отредактировал(а) kuzulis - 13.1.2012, 17:37
PM MAIL   Вверх
daemonaz
Дата 13.1.2012, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 160
Регистрация: 4.5.2008

Репутация: нет
Всего: нет



Спасибо, kuzulis, супер! smile 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.0899 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.