Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Кому-нибудь приходилось писать в Builder C++ программу для работы с FTDI?
Форум разработчиков электроники ELECTRONIX.ru > Интерфейсы > Форумы по интерфейсам > RS232/LPT/USB/PCMCIA/FireWire
zheka
Кому-нибудь приходилось писать в Builder C++ программу для работы с FTDI?

Господа, я застрял...
По нажатию кнопки я должен дождаться прихода символа и ответить на него в течение не более 70 мсек.
Стандартная конструкция типа терминала не подходит.

Я отправляю символ и пытаюсь читать ответ:
Код
USBStat=FT_Write(hUSB,TxBuffer,dwBytesToWrite,&dwBytesWritten);

if (!USBStat==FT_OK)
{
USBErr(USBStat);
return;
};

        USBStat=FT_GetStatus(hUSB,&RxBytes,&TxBytes,&EventDWord);



Естественно, читаю ноль байт, так как комп переходит к чтению мгновенно, а ответ не успевает прийти.

Если же ставлю
Код
while(RxBytes==0)
{
Application->ProcessMessages();
USBStat=FT_GetStatus(hUSB,&RxBytes,&TxBytes,&EventDWord);
}

ShowMessage(RxBytes);


То получаю гигантское число. ПРочие манипуляции приводят к зависанию программы.

Как подружить контроллер, FT232RL и этот долбаный Builder C++ ?
Xenia
А если while оставить, а ProcessMessages() из него убрать?
zheka
Хех, так зависнет же. Вы знаете, что такое ProcessMessages?
follow_me
Не хорошо как то , грубо по отношению к даме которая хочет вам помочь

ProcessMessages - функция диспетчера сообщений приложения на отработку очереди
система повиснет пока не получит обратно управление т.к. процесс блокирован ожиданием ввода

тут возникает вопрос - почему вы выполняете эту функцию в том же потоке что и основное приложение - выполните в отдельном потоке, это решит вопрос с потерей отзывчивости
и как сказала Xenia - держать вот так в цикле ожидания ввода это совсем неправильно
YAM
Последний пост - путь к успеху.
Выполняю поллинг по чтению данных от FTDI в обработчике по таймеру с интервалом 10 mSec. И все гуть...
sparcmaster
Цитата(follow_me @ Feb 7 2012, 23:19) *
почему вы выполняете эту функцию в том же потоке что и основное приложение - выполните в отдельном потоке

Абсолютно верно, подобные вещи реализуются в отдельном потоке.
zheka
Цитата
Не хорошо как то , грубо по отношению к даме которая хочет вам помочь


Упаси меня бог грубить женщине?
Просто ее вариант я уже пробовал, а ProcessMessages мне как раз и посоветовали, чтобы избавиться от зависания. Не помогло.

Цитата
Последний пост - путь к успеху.


Дык пацан уже пришел к успеху:

Код
recieve_ok=0;

    while(recieve_ok==0) // В который раз убеждаюсь - флажок это наше все.
    {
      //Application->ProcessMessages();
      USBStat=FT_GetStatus(hUSB,&RxBytes,&TxBytes,&EventDWord);// спокойно проверяем посылку
        if (RxBytes > 0)
         {
           USBStat=FT_Read(hUSB,RxBuffer,RxBytes,&dwBytesReceived);
             if (!USBStat == FT_OK)
                 {
                  USBErr(USBStat);
                  return;
                  };
        RxBuffer[RxBytes]=0;
       RichEdit1->Lines->Add("Получено: "+AnsiString(RxBytes)+":"+ AnsiString((const char*)RxBuffer));
       recieve_ok=1; // ставим флажок
      }
    }


Осталось рассчитать разумный таймаут и добавить его контроль.

А потоки вещь хорошая, но я к сожалению ни бум-бум в них, а разбираться для решения конкретной текущей задачи времени нет.
Тем более, что тормоза этот код будет вносить лишь при отсутствии ответа от FTDI.
YAM
Ну, а если от FTDI ничего не прийдет - так и умрете в этом цикле wink.gif
zheka
Цитата(YAM @ Feb 8 2012, 16:40) *
Ну, а если от FTDI ничего не прийдет - так и умрете в этом цикле wink.gif


Даже с учетом этого:

Цитата
Осталось рассчитать разумный таймаут и добавить его контроль.


???
Силаев
Делать такое надо строго в отдельном потоке. В билдере это два нажатия мышкой и немного кода:

File->New->Other->Thread Object
Далее задать имя класса потока (Class Name)

В функции Execute потока

Код
void __fastcall fx2thread::Execute()
{//---- Place thread code here ----
while (Form_Main->Start_reg)
  { UCHAR buf[512];
     long bufsize = 512;//функция XferData меняет значение, она возвращает в эту переменную число принятых байт
     Form_Main->FX2Device->EndPoints[2]->XferData(buf, bufsize, NULL);
       for (int x=0; x<bufsize; x=x++)
        {    //разбор данных буфера buf
         }
  }//while
}


Start_reg - пересменная типа bool управляемая из основной программы
В потоке это все

В основной программе:
TForm_Main *Form_Main;
fx2thread *fx2thr = new fx2thread(true); //указатель на поток

Чтобы запустить поток по кнопке:
Код
void __fastcall TForm_Main::Button_StartClick(TObject *Sender)
{//Пуск
  if (Start_reg == false)
   {Start_reg = true; //переключил триггер
      if (fx2thr->Suspended == true)  fx2thr->Resume(); //запустил поток
   }
}


Чтобы остановить поток по кнопке:
Код
void __fastcall TForm_Main::Button_StopClick(TObject *Sender)
{//Стоп
if (Start_reg == true)
{  Start_reg = false; //переключил триггер остановил чтение в цикле потока
     if (fx2thr->Suspended == false)  fx2thr->Suspend(); //остановил поток
  }
}


В примере функции от Cypress, но думаю понятно.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.