Интернет-магазин

Просмотр корзины
В корзине:

товаров - 0 шт.



§ 14. Ethernet модуль Jerome. Скоростные характеристики командного интерфейса

Дмитрий Иванов, 3 Июня 2011

Команды управления

Один из первых же вопросов, который может возникнуть при работе с командны интерфейсом модуля является вопрос о предельной частоте команд, которыую может обеспечить Jerome.


В прошлой статье мы рассмотрели пример реализации программы на языке С++ для взаимодействия с модулем Jerome по командному интерфейсу. Тот пример был довольно важным, но он не охватывает один важный аспект - а с какой частотой можно отправлять команды модулю? Напрмер, что произойдет если мы выполним вот такой вот код:

for( int i = 0; i < 1000; i++ )
{ 
  len = sprintf(buf, "$KE,ADC,ALL\r\n");  
  KeTcp.Send( buf, len ); 
}

К сожалению, ни чего хорошего не произойдет. Модуль просто "захлебнется" от такого потока запросов и скорее всего не выполнит ни одного из них. К счастью, это никак не повлияет на его дальнейшую работу - "зависаний" и тому подобных явлений не будет, модуль останется полностью работоспособным.

Как же обойти эту проблему? Очевидным решением является подача команд с некоторой задержкой между ними. Напрмер, код показанный ниже прекрасно отработает и модуль выполнит все из отправленных ему команд. На прктике достаточно задежки между "очередью" команд примерно в 10 мс.

for( int i = 0; i < 1000; i++ )
{ 
  len = sprintf(buf, "$KE,ADC,ALL\r\n");  
  KeTcp.Send( buf, len ); 
  Sleep(10);
}

Сделав задержку в 10 мс мы автоматически ограничиваем частоту следования команд числом 100 Гц. Представленный подход очень прост в реализации, но иногда бывают ситуации когда необходимо "выжать" максимум из модуля. В этом случае можно использовать более сложный подход. Суть его в следующем: отправлять новую команду будем только тогда, когда получим ответ на предыдущую, т.е. по факту готовности модуля принять новую команду. Практический пример реализации этого подхода показан ниже (основан на коде из предыдущей статьи).

// Глобальная переменная
unsigned char bNext = true;

int main()
{
  ........
  for( int i = 0; i < 1000; i++ )
  {        
    // Не отправляем новую команду, пока не получим ответ по предыдущей
    while( bNext == false );   
    len = sprintf(buf, "$KE,RID,ALL\r\n");    
    KeTcp.Send( buf, len ); 
    // Сбрасываем флаг. Ждем готовности ответа
    bNext = false;    
  }
  ...
}

void ParseData( char* pBuf )
{
  if( !pBuf || *pBuf != '#' ) return;  
  pBuf++;
  // Взводим флаг. Ответ на предыдущую команду получен - можно посылать новую
  bNext = true;
  ....
}

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


Команда Максимальная частота обработки, Гц
$KE450
$KE,ADC,ALL200
$KE,IMPL,1330
$KE,RD,ALL380
$KE,RID,ALL350

Как видно из таблицы "гибкий" подход позволяет повысить скоростные характеристики командного интерфейса модуля в несколько раз по сравнению с ранее полученной цифрой в 100 Гц при использовании фиксированной задержки между командами.

Следует обратить внимание на то, что представленная реализация "гибкого" подхода сделана несколько "грубовато" с точки зрения программной безопастности. Разумеется, следует разграничить доступ к общей переменой из нескольких потоков с помощью, напрмер, критических секций. Также следует предусмотреть выход по тайм-ауту из функции ожидания готовности ответа (потенциально возможна ситуация когда модуль вообще не ответит на команду). Упрощенный код представлен исключительно с целью облегчения понимания сути предлагаемого метода.


© Дмитрий Иванов
3 Июня 2011
http://www.kernelchip.ru


© KERNELCHIP 2006 - 2017