Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Общие вопросы по программированию, компьютерный форум
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.05.2017, 20:40   #1
Krounis
 
Регистрация: 13.05.2017
Сообщений: 3
Печаль Циклическое чтение информации через RS232 с использованием goto - Qt&C++, COM PORT

Всем доброго времени суток!
Перейду сразу к делу, есть два фотоприемника (ФП), которые считывают данные при засветки их лазером. Оба ФП подключены к блоку управления, тот в свою очередь подключается к ПК по Com порту. Задача импульсно в течении определенного времени считывать данные с ФП и передавать через Com порт и записывать в массив данных.

Сам процесс считывания уже реализован, но по всей видимости неверно. Есть так же уже реализованное ПО для той же самой задачи но на Cи, нужно переписать функцию для С++ либо написать свою.
Я попробовал написать свою и столкнулся с проблемой использования так называемых "меток" и оператора goto. Зачем, собственно, использовать те самые метки. Отвечаю - обмен данными через ком порт идет следующим образом: с ПК отсылается байт из 9 битов, в ответ приходит такой же байт но с измененными (если это нужно) данными. А оператор goto нужен для того чтобы постоянно отправлять байты, до тех пор пока блок не откликнется прислав в ответном байте измененный бит (8 бит), это даст нам понять что он готов передать данные, потом отправляем ему пустой байт по определенному адресу (0xdb) и в ответ прилетает такой же байт, но с нужными данными, затем работа устройства повторяется указанное пользователем время и количество замера данных.

Основная проблема в том, что я, как новичек, не совсем понимаю как работать с goto, а обычный цикл здесь не воспринимается устройством (мы зависим от его быстродействия), ну и в уже работающей программе на Си как раз используются эти "метки".

Прошу помощи в выявлении ошибок в коде, на основании логов (во вложенных файлах - логи обмена данными по RS232 во время проведения эксперимента) Write и Read логов записанных в порт и считанных с него соответственно.
А так же прилагаю код правильной и рабочей реализации этой задачи на Си и неправильно работающий код на С++.

Рабочий код на Си(вложением потому что не хватило символов):
Код функции эксперимента на С.txt

Не рабочий код на плюсах с указанием до какого момента работает, а с какой строки уже нет(см. комментарий):
Код:
void TabWindow::on_expButton_clicked() //функция эксперимента
{
    //открытие и установка параметром Com порта
    com1->open(QIODevice::ReadWrite);
    com1->setFlowControl(QSerialPort::NoFlowControl);
    com1->setBaudRate(QSerialPort::Baud115200);
    com1->setStopBits(QSerialPort::OneStop);
    com1->setDataBits(QSerialPort::Data8);
    com1->setDataTerminalReady(false);
    com1->clear();

    //Experiment writepack 2
    expWrite2.resize(9);
    expWrite2[0] = 0x55;
    expWrite2[1] = 0x81;
    expWrite2[2] = 0;
    expWrite2[3] = 0xc2;
    expWrite2[4] = 0;
    expWrite2[5] = 0;
    expWrite2[6] = 0;
    expWrite2[7] = 0;
    expWrite2[8] = expWrite2[1];
    for (int i=2; i<8; i++)
        expWrite2[8]=expWrite2[8]+expWrite2[i];

    //Experiment readpack 1
    expRead1.resize(9);
    expRead1[0] = 0x55;
    expRead1[1] = 0x81;
    expRead1[2] = 0;
    expRead1[3] = 0xD6;
    expRead1[4] = 0;
    expRead1[5] = 0;
    expRead1[6] = 0;
    expRead1[7] = 1;
    expRead1[8] = expRead1[1];
    for (int i=2; i<8; i++)
        expRead1[8]=expRead1[8]+expRead1[i];

    //Experiment readpack 2
    expRead2.resize(9);
    expRead2[0] = 0x55;
    expRead2[1] = 0xE1;
    expRead2[2] = 0;
    expRead2[3] = 0xDB;
    expRead2[4] = 0;
    expRead2[5] = 0;
    expRead2[6] = 0;
    expRead2[7] = 0;
    expRead2[8] = expRead2[1];
    for (int i=2; i<8; i++)
        expRead2[8]=expRead2[8]+expRead2[i];


    ARef = 4000;
    BRef = 0;
    ASig = 4000;
    BSig = 0;
    QFile adcFile("ADC data.csv");


    expResult.resize(9);
    expResultP.resize(9);
    
    //запись байтов по адресу 0xC2 для начала стадии считывания данных
    com1->write(expWrite1);
    com1->waitForBytesWritten(50);
    com1->waitForReadyRead(50);
    expResult = com1->readAll();

    //с данной строки логи отправляемые и получаемые в ответ 
    //программой на С++ не совпадают с логами на Си 
    //Ошибка в том что с данной строки цикл должен повторятся и привязываться к тому что условие выполнения цикла 
    //это то что в ответном байте от блока по адресу 0хd6 8 бит с каждым шагом цикла увеличивается на 1цу в 16 системе 
    int count=0;
    expSignal[0]=count;
    while ((int)expSignal[0]<14)
    {
    com1->write(expWrite2);
    com1->waitForBytesWritten(50);
    com1->waitForReadyRead(50);
    expResult = com1->readAll();
    //expSignal[0]=count+1;

    //отправление байта для проверки можно ли проводить считывание по адресу 0хd6
    flag1:
    com1->write(expRead1);
    com1->waitForBytesWritten(100);
    com1->waitForReadyRead(100);
    expResultP = com1->readAll();
    expSignal[0] = expResultP[7];
    if ((int)expSignal[0]!=(int)expSignal[0]+1) goto flag1;
    else goto flag2;

    //если прошлый байт изменился в 8 бите на 1, считываем данные
    flag2:
    com1->write(expRead2);
    com1->waitForBytesWritten(100);
    com1->waitForReadyRead(100);
    expResult = com1->readAll();

    //операции преобразования полученных данных
    //Reading massive of data

        expRes1 = 0;
        expRes1 = expResult[4];
        expRes1 = expRes1 & 0xf;
        expRes1 = expRes1 << 8;
        expRes1 = expRes1 + expResult[5];
        expRes1 = (((double)expRes1 - BRef) / (ARef - BRef) * 4000);

        expRes2 = 0;
        expRes2 = expResult[6];
        expRes2 = expRes2 & 0xf;
        expRes2 = expRes2 << 8;
        expRes2 = expRes2 + expResult[7];
        expRes2 = (((double)expRes2 - BSig) / (ASig - BSig) * 4000);

        ADC1.resize(count+1);
        ADC2.resize(count+1);
        ADC1[count]=expRes1;
        ADC2[count]=expRes2;
        count++;
}

         com1->clear();
         com1->close();
}
Полный код на с++:
Функция на C++.txt


Логи:
Логи write C++ и С.docx

Логи read C++ и С.docx

Последний раз редактировалось Krounis; 13.05.2017 в 20:48.
Krounis вне форума Ответить с цитированием
Старый 13.05.2017, 21:07   #2
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,707
По умолчанию

Все ваши издевательства с метками заменяются на цикл do{} while() с выкидыванием меток и гоуту.
p51x вне форума Ответить с цитированием
Старый 13.05.2017, 21:17   #3
Krounis
 
Регистрация: 13.05.2017
Сообщений: 3
По умолчанию

можно слегка подробнее? где именно применять этот цикл?
Забыл прикрепить протокол обмена:http://hdd.tomsk.ru/file/llnfpzoz
Krounis вне форума Ответить с цитированием
Старый 14.05.2017, 05:41   #4
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,707
По умолчанию

Вот этот код:
Код:
    flag1:
    com1->write(expRead1);
    com1->waitForBytesWritten(100);
    com1->waitForReadyRead(100);
    expResultP = com1->readAll();
    expSignal[0] = expResultP[7];
    if ((int)expSignal[0]!=(int)expSignal[0]+1) goto flag1;
    else goto flag2;
будет до команды аналогичен циклу, но читаться будет легче и понятнее.
p51x вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Com port (rs232) асинхронные чтение. Использование таймаута во время ожидания события прихода данных из порта Mefil Win Api 0 20.02.2017 08:41
Нужно написать программу на циклическое открытие внешней программы и завершение через некоторое время Megawolk Помощь студентам 7 30.04.2015 17:48
Com port (RS232) Pavlov_yu C++ Builder 14 18.06.2014 19:12
c# + банальное чтение com port alexandrusankov C# (си шарп) 28 05.12.2013 08:47
com port чтение запись delphi SonicBob Помощь студентам 5 15.11.2011 10:20