|
|
  |
FTDI 232, Уменьшить время отклика |
|
|
|
Jul 5 2011, 09:08
|

Twilight Zone
  
Группа: Свой
Сообщений: 454
Регистрация: 17-02-09
Из: Челябинск
Пользователь №: 44 990

|
Приветствую коллеги по цеху! Такая задача у меня: Имеется некий софт для ПК, который принимает данные от «железки», последняя отправляет данные в ПК через FTDI(FT232). Между ПК и железкой есть свой простой протокол обмена. Вопрос в том, что после посылки сообщения железка ждет подтверждения от ПК, которое приходит с задержкой 5-25 ms, что сильно напрягает и делает пропускную способность канала 25% при скорости 115200 (сообщения короткие 24-50 байт). Предполагаю что это связанно с задержками самого драйвера FTDI. Для работы с FTDI со стороны ПК пользовался D2XX Programmer's Guide. кликДанные с FTDI вычитываю каждую 1 ms с использованием мультимедийного таймера (разрешение - 1ms точно). Передаю также с разрешением 1ms, но увы, идут задержки. Прошу совета как выйти из положения. Писать свой драйвер под Windows могу но нет желания. Отказаться от FTDI нет возможности. Прилагаю листинг инициализации FTDI. Заголовок для класса FTDI Код #ifndef __FTDI_H #define __FTDI_H
#include "ftd2xx.h" #include <Mmsystem.h>
class My_FTDI { public: My_FTDI(void); public: ~My_FTDI(void);
int Multimedia_Timer_Init(void); static int Get_number_D2XX_devices(void); static int Write_FTDI(BYTE *sours, WORD len); static int Read_FTDI(BYTE *RxBuffer); static int Find_FTDI_Connect(void); void static __stdcall TimeProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
FT_HANDLE ftHandle; DWORD NumDevs; DWORD Monitor_Timer; int Timer_Resolution;
};
extern My_FTDI My_FTDI_Dev;
#endif Вырезка из метода поиска/инициализации/подключения к FTDI Код Метод инициализации FTDI int My_FTDI::Find_FTDI_Connect(void) // Пробую подлючиться к железке { FT_STATUS ftStatus; BYTE sours[2] = {0x01, 0x03}; // START, STOP static BYTE Rx_Buff[1024] = {0}; WORD BytesWritten = 0;
cout << " Connect to FTDI " << endl;
for ( int i = 0; i < (int)My_FTDI_Dev.NumDevs; i++ ) {
ftStatus = FT_Open (i, &My_FTDI_Dev.ftHandle ); if (ftStatus != FT_OK) FT_Close(My_FTDI_Dev.ftHandle); // Закрыть в случае ошибки;
ftStatus = FT_SetTimeouts( My_FTDI_Dev.ftHandle, 1, 1 ); // Timeout if (ftStatus != FT_OK) { cout << " Fail timeout " << i << endl; FT_Close(My_FTDI_Dev.ftHandle); // Закрыть в случае ошибки }
ftStatus = FT_SetBaudRate(My_FTDI_Dev.ftHandle, 115200); // Set baud rate to 115200 if (ftStatus != FT_OK) FT_Close(My_FTDI_Dev.ftHandle); // Закрыть в случае ошибки
// Set 8 data bits, 1 stop bit and no parity ftStatus = FT_SetDataCharacteristics(My_FTDI_Dev.ftHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); if (ftStatus != FT_OK) FT_Close(My_FTDI_Dev.ftHandle); // Закрыть в случае ошибки
} // for ( int i = 0; i < (int)My_FTDI_Dev.NumDevs; i++ )
return 0;
} Спасибо!
--------------------
Magic Friend
|
|
|
|
|
Jul 5 2011, 11:47
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(Danis @ Jul 5 2011, 12:08)  сообщения короткие 24-50 байт Т.е. меньше размера пакета обмена для FTDI. И не отправлются из микросхемы в комп до тех пор, пока не отработает Latency Timer, по умолчанию 16 мс (собственно, для длинных пакетов та же беда с остатком в конце пакета). Надо или крутить в свойствах данного ком-порта, или (на мой взгляд, лучше) устанавливать через FT_SetLatencyTimer(). Ещё лучше в пакетах иметь флаговый байт конца пакета (типа того, как в SLIP сделно) и назначить его для ком-порта как EventChar (вероятно, через FT_SetChars(), я этим делом пользовался и с обычным ком-портом через поле в DCB). Это для любого ком-порта полезно, чтобы в Win через WaitObject не за каждым символом из ком-порта дёргаться, а только по приходу всего пакета. А в случае FTDI это ещё и приводит к немедленной отправке неполного буфера по приходу данного символа. Даже минимальный LatencyTimer не отсчитывается, его настройка не влияет вообще.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jul 5 2011, 13:12
|

Twilight Zone
  
Группа: Свой
Сообщений: 454
Регистрация: 17-02-09
Из: Челябинск
Пользователь №: 44 990

|
Цитата(ReAl @ Jul 5 2011, 15:47)  (на мой взгляд, лучше) устанавливать через FT_SetLatencyTimer(). Да, помогло. Установил минимальное значение LatencyTimer – 2 ms, повесил на RX и TX осциллограф, замерил, действительно 2-2,5 ms. Работает! Этого мне достаточно. Большое спасибо  . Цитата(zltigo @ Jul 5 2011, 16:53)  В данном случае правильный выход только один - протокол должен стать сложнее и не требовать немедленного подтверждения каждого фрейма. Посмотрите как подобное делается в классических протоколах, например, LAPB. TCP тоже годится для ознакомления с принципами. Согласен, дело в том, что это не мой софт, он написан давно и «устаканен», человек который его написал не «железячник», менять кардинально ничего нельзя, вот перед ним встала проблема, я ее помог решить. На счет сканирования, я завел его в отдельный паток Windows в котором идет обработка мультимедийного таймера, загрузка процессора от него не более 0,7% при max трафике, сам проверял, так что для ПК это сойдет. Вот подготовил класс С++ пусть вставляет и живет счастливо. Отозвавшимся спасибо, тему можно закрывать. Цитата(zltigo @ Jul 5 2011, 16:53)  Сканирование это моветон  Программирование микроконтроллеров меня конечно воспитало но не на столько.
--------------------
Magic Friend
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|