crossplatform.ru

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


  Ответ в Чтение параметра
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
Теги
Выровнять по центру
Ссылка на тему
Ссылка на сообщение
Скрытый текст
Сокращение
Код с подсветкой
Offtopic
 
Удалить форматирование
Спец. элементы
Шрифт
Размер
 
Цвет шрифта
 
Отменить ввод
Вернуть ввод
Полужирный
Курсив
Подчеркнутый
 
 
Смайлики
Вставить изображение
Вставить адрес электронной почты
Цитата
Код
Раскрывающийся текст
 
Увеличить отступ
По левому краю
По центру
По правому краю
Вставить список
Вставить список

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
AD Дата 4.6.2009, 9:14
 
Цитата(BRE @ 3.6.2009, 21:58) *
Сильно в алгоритм не вникал, вот что бросилось сразу в глаза:
Отдельно эта функция проверялась, она работает?

Проверялась. Работает! На самом деле ее я все-таки и переписал. Теперь все нормально работает!
Litkevich Yuriy Дата 3.6.2009, 21:18
 
Цитата(AD @ 3.6.2009, 17:27) *
Если делать все под отладчиком, то при поставке точек останова, алгоритм срабатывает.
скорее всего, ты где-то не учитываешь, что данные должны накопится. Т.е. существует медленный асинхронный процесс (например тот же коммуникационный порт). И при отладке по шагам данные успевают накопиться, т.к. программа выполняется очень медленно. А в нормальном режиме она выполняется быстрее чем этот самый асинхронный процесс.
BRE Дата 3.6.2009, 20:58
  Сильно в алгоритм не вникал, вот что бросилось сразу в глаза:

/// Циклическое чтение из COM-порта, пока не соберем пакет данных
INFO_FROM_EXTERN_DEVICE* ImitatorTSL::readCyclic()
{
    BYTE buffer[128] = {0};
    INFO_FROM_EXTERN_DEVICE* pack; // !!! Указатель необходимо устанавливать в 0!!!
    unsigned long len_result;
    ::ReadFile(COMPort::instanceCOM() -> comHandle(), buffer, sizeof(buffer), &len_result, 0);

        // !!! Для чего ты вставил проверку buffer != 0 ??? Может ты хотел сделать *buffer != 0 или buffer[0] != 0?
    if(len_result > 0 && buffer != 0)
    {
        unsigned int new_len = 0;
        BYTE* _buffer = findHead(buffer, len_result, INFO_FROM_EXTERN_DEVICE().header, new_len);
        if(_buffer == 0 || new_len == 0) return 0;
        memmove(buffer, _buffer, new_len);

                // !!! Здесь не сообразил, для чего рекурсия и что хотел этим сделать?
        pack = packetFromPage(buffer, new_len);
        if(!pack) readCyclic();

        delete[] _buffer;    _buffer = 0;
    }
    return pack;
}


Отдельно эта функция проверялась, она работает?

Есть классная штука для отладки это ЛОГИ. Если поставить много qDebug в нужных местах с выводом необходимых параметров, то разобраться можно в разы быстрее. ;)
AD Дата 3.6.2009, 13:27
  Делаю имитатор прожектора. Есть следующие вещи: задается количество циклических перемещений прожектора (из крайне правого положения в крайне левое и обратно).
Алгоритм следующий:
виджет-вкладка в котором рисуются все нужные кнопки переопределен
вот так:
/// Класс отображения параметров внешних устройств управления в автоматическом режиме
class AutoControl: public QWidget, public AutoControlClass
{
    Q_OBJECT

private:
// какие-то данные
}

внутри класса есть следующие переменные:

private:
    INFO_FROM_EXTERN_DEVICE inf_from_ed_packet;    ///< пакет данных от внешнего устройства в режиме авто управления
    const int MAXBYTES;                            ///< константа максимального количества байт
    ImitatorTSL* imitTsl;                        ///< указатель на класс главного окна


Слоты запуска циклических перемещений по каждой оси и функции чтения:
private:
    void readAzimuth(int& geted_azimuth, double limit);
    void readAngleElevation(int& geted_angle_elev, double limit);

private slots:
    void startHorizontalCycles();
    void startVerticalCycles();


Далее реализация. Вот так соединяется слот с сигналом и реализация слота:
connect(btnStartHorizontal, SIGNAL(clicked()), this, SLOT(startHorizontalCycles()));

В слоте происходит следующее:
1) проверяется текущее положение прожектора
2) если он не в крайне правом положении, переводим его в это положение
3) далее запускается цикл перехода из крайне правого в крайне левое и обратно
4) счетчик соответственно уменьшается

/// Получение азимута
void AutoControl::readAzimuth(int& geted_azimuth, double limit)
{
    if(!imitTsl) return;
    while(geted_azimuth < ((limit - 1.5) * 10) || geted_azimuth > ((limit + 1.5) * 10))
    {
        imitTsl -> readFromCtrlPage();
        geted_azimuth = VALFROMBYTES(inf_from_ed_packet.high_azim, inf_from_ed_packet.low_azim);
    }
}

/// Запуск циклического перемещения по горизонтальной плоскости
void AutoControl::startHorizontalCycles()
{
    int geted_azimuth = VALFROMBYTES(inf_from_ed_packet.high_azim, inf_from_ed_packet.low_azim);
    int azimuth = 172 * 10;                                ///< правый предел прожектора
    if(geted_azimuth < ((172. - 1.5) * 10) || geted_azimuth > ((172. + 1.5) * 10))
    {
        inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
        inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);        ///< перевод в этот предел прожектора
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
    }
    readAzimuth(geted_azimuth, 172.);

    /// внешний цикл по количеству перемещений
    const int number_cycles = spinHorizCycles -> value();
    for(register int i=0; i<number_cycles; ++i)
    {
        azimuth = -172 * 10;
        inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
        inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
        readAzimuth(geted_azimuth, -172.);

        azimuth = 172 * 10;
        inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
        inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
        readAzimuth(geted_azimuth, 172.);

        spinHorizCycles -> setValue(number_cycles - (i + 1));
        spinHorizCycles -> update();
    }
}

Проблема в том, что при заходе в функцию readAzimuth, там он зацикливается. Если делать все под отладчиком, то при поставке точек останова, алгоритм срабатывает.


Вот функции главного окна, которые считывают и записывают в порт:
// Получение пакета данных из поступившего куска байт со страницы управления с внешнего устройства
INFO_FROM_EXTERN_DEVICE* ImitatorTSL::packetFromPage(BYTE* buffer, unsigned int len)
{
    if(!buffer) return 0;
    if(len < INFO_FROM_EXTERN_DEVICE().length)
        return 0;
    BYTE sum = 0;
    BYTE* packet = new BYTE[INFO_FROM_EXTERN_DEVICE().length];
    for(register int i=0; i<INFO_FROM_EXTERN_DEVICE().length; ++i)
        sum += buffer[i];
    if(!sum)
        for(register int i=0; i<INFO_FROM_EXTERN_DEVICE().length; ++i)
            packet[i] = buffer[i];
    else return 0;

    return (INFO_FROM_EXTERN_DEVICE*)packet;
}

/// Циклическое чтение из COM-порта, пока не соберем пакет данных
INFO_FROM_EXTERN_DEVICE* ImitatorTSL::readCyclic()
{
    BYTE buffer[128] = {0};
    INFO_FROM_EXTERN_DEVICE* pack;
    unsigned long len_result;
    ::ReadFile(COMPort::instanceCOM() -> comHandle(), buffer, sizeof(buffer), &len_result, 0);
    if(len_result > 0 && buffer != 0)
    {
        unsigned int new_len = 0;
        BYTE* _buffer = findHead(buffer, len_result, INFO_FROM_EXTERN_DEVICE().header, new_len);
        if(_buffer == 0 || new_len == 0) return 0;
        memmove(buffer, _buffer, new_len);
        pack = packetFromPage(buffer, new_len);
        if(!pack) readCyclic();
        delete[] _buffer;    _buffer = 0;
    }
    return pack;
}

/// Чтение данных из порта для страницы контроля с внешнего управления
void ImitatorTSL::readFromCtrlPage()
{
    INFO_FROM_EXTERN_DEVICE* pack = readCyclic();
    if(!pack) return;

    if(_timerCtrlManual.isActive())
    {
        tabManualControl -> fromExternalDevice(*pack);
        tabManualControl -> checkPacket();
    }
    else if(_timerCtrlAuto.isActive())
    {
        tabAutoControl -> fromExternalDevice(*pack);
        tabAutoControl -> checkPacket();
    }
}

/** Запись в COM-порт данных со страницы управления прожектором с внешнего устройства и прием данных из порта
    Автоматический режим работы. */
void ImitatorTSL::writeFromCtrlAutoPage()
{
    readFromCtrlPage();
    unsigned long length_result;
    INFO_TO_EXTERN_DEVICE inf_ed_packet = tabAutoControl -> autoControl();
    ::WriteFile(COMPort::instanceCOM() -> comHandle(), &inf_ed_packet, sizeof(inf_ed_packet), &length_result, 0);
}


/// Установка пакета данных от внешнего управления в автоматической режиме работы
void AutoControl::fromExternalDevice(INFO_FROM_EXTERN_DEVICE& mp)
{
    BYTE sum = 0;
    BYTE* ptr = (BYTE*) (&mp);
    for(register int i=0; i<(sizeof(mp) - 1); ++i) sum += ptr[i];
    if((MAXBYTES - sum) == mp.checksum)
        inf_from_ed_packet = mp;
}


Сможете помочь решить проблему? Я уже не знаю как заставить отрабатывать так, чтобы при запуске без отладчика и точек останова, алгоритм срабатывал без зацикливания.
Просмотр темы полностью (откроется в новом окне)
RSS Рейтинг@Mail.ru Текстовая версия Сейчас: 10.7.2025, 14:31