Делаю имитатор прожектора. Есть следующие вещи: задается количество циклических перемещений прожектора (из крайне правого положения в крайне левое и обратно).
Алгоритм следующий:
виджет-вкладка в котором рисуются все нужные кнопки переопределен
вот так:
/// Класс отображения параметров внешних устройств управления в автоматическом режиме
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;
}
Сможете помочь решить проблему? Я уже не знаю как заставить отрабатывать так, чтобы при запуске без отладчика и точек останова, алгоритм срабатывал без зацикливания.