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

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

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



§ 2.1. Настройка направлений линий ввода/вывода

Дмитрий Иванов, 22 марта 2008

Файлы к статье скачать
Имя: KA002_01.zip (ZIP архив)
Размер: 130 КБ

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


Для установки направления ввода/вывода линии необходимо использовать KE-команду $KE,IO,SET. В качестве параметров необходимо указать номер линии, направление линии (0 – выход, 1 - вход) и необязательный флаг (S) – сохранение настройки. Если флаг задан, то произведенная настройка линии будет сохранена в энергонезависимой памяти модуля, т.е. при следующем подключении модуля линия будет автоматически сконфигурирована в соответствии с сохраненным направле- нием. Например, чтобы настроить линию под номером 18 на вход и сохранить эту настройку в памяти модуля, необходимо подать следующую команду:

$KE,IO,SET,18,1,S


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

Для того чтобы узнать в какое направление сейчас установлена та или иная линия служит команда $KE,IO,GET. Команда имеет две модификации. Одна из них позволяет за одно обращение к модулю получить информацию по всем линиям, другая предназначена для одной конкретной линии (подробнее см. команды управления модулем). Мы будем использовать в нашей программе именно последнюю. Еще необходимо сказать, что в синтаксисе команды необходимо указать откуда собственно необходимо прочесть информацию о направлении линии. Для этого в команде используется специальное поле Location. Информация будет соответствовать текущему состоянию, если поле Location равно ‘CUR’ или будет взята из энергонезависимой памяти (‘MEM’), т.к. в общем случае значения могут отличаться (если подавалась команда $KE,IO,SET без указания сохранять в энергонезависимой памяти).


Приступим к программному обеспечению. Готовый проект вы можете найти в файлах к этой статье. Пример написан на С++ с использованием MFC в среде Microsoft Visual Studio C++ 6.0. Окно программы имеет вот такой вид:

Программа изменения направления передачи данных

Рисунок 1. Пример программы настройки направления линий ввода-вывода модуля Ke-USB24A

Начнем рассмотрение кода. Сначала идет процедура открытия порта - нам она не интересна, так она была уже рассмотрена несколько раз (если интересна - прошу к рассмотрению функцию void CSetupDirectionDlg::OnOpen()).

Мы же сейчас поговорим о функции установки направления линии, отрабатывающей по нажатию кнопки "SET". Сначала идет группа проверок адекватности введенных данных. Если все Ok то формируем куманду установки линии в заданное направление и проверяем был ли взведен флажок сохранения настройки в память. Если да, то к строке команды в конец подписываем ,S. Далее сформированный буфер отправляем в порт.

//******************************************************************************
void CSetupDirectionDlg::OnSet() 
{
  // TODO: Add your control notification handler code here
  UpdateData(true);
  
  if(this->m_hFile == NULL)
  {
    MessageBox("You should open\nport first", "Info", MB_ICONINFORMATION);
    return;
  }
 
  int direction = this->m_SetDir;
  if(direction < 0)
  {
    MessageBox("Please, select\ndirection", "Info", MB_ICONINFORMATION);
    return;
  }
 
  if(this->m_LineSet <= 0 || this->m_LineSet > 24)
  {
    MessageBox("Please, select\ncorrect line number", "Info", MB_ICONINFORMATION);
    return;
  }  
 
  DWORD lpdwBytesWritten;
  char buf[32];
 
  int len = 0;
  if(this->m_save.GetCheck() == BST_CHECKED)
    len = sprintf(buf, "$KE,IO,SET,%d,%d,S\r\n", this->m_LineSet, direction);
  else
    len = sprintf(buf, "$KE,IO,SET,%d,%d\r\n", this->m_LineSet, direction);
 
  WriteFile(m_hFile, buf, len, &lpdwBytesWritten, NULL);  	
 
  MessageBox("Data has been\nsenе to module", "Info", MB_ICONINFORMATION);
}

А вот болле интересный участок кода - обработчик нажатия кнопки "GET", по которой мы должны получить информацию о том, в какое направление сейчас настроена заданная нами линия. Сначала следует последовательность проверок на корректность данных. Далее, с учетом заданных параметров формируется команда на чтение линии. Затем буфер со строкой команды отправляется в порт. Теперь нам необходимо как-то получить ответ от модуля. Для этого можно поступить так как сделано здесь: непосредственно в обработчике нажатия кнопки сделать небольшую задержку, например на 100 мс. За это время модуль гарантированно отработает отправленную ему команду и выдаст обратно в порт ответ (другой вариант, более правильный так сказать - использовать дополнительный поток, который будет постоянно читать данные из порта и разбирать ответы). Затем пытаемся прочесть данные из порта. Если данные есть - начинаем их разбирать. Зная, в каком формате мы должны получить ответ нехитрыми операциями проверяем его на валидность и "вытаскиваем" значение направления запрошенной линии. Из полученной информации формируем ответ в виде сообщения.

//*********************************************************************************
void CSetupDirectionDlg::OnGet() 
{
  // TODO: Add your control notification handler code here
  UpdateData(true);
  
  if(this->m_hFile == NULL)
  {
    MessageBox("You should open\nport first", "Info", MB_ICONINFORMATION);
    return;
  }
 
  int source = this->m_GetSource;
  if(source < 0)
  {
    MessageBox("Please, select\nsource", "Info", MB_ICONINFORMATION);
    return;
  }
 
  if(this->m_LineGet <= 0 || this->m_LineGet > 24)
  {
    MessageBox("Please, select\ncorrect line number", "Info", MB_ICONINFORMATION);
    return;
  }  
 
  DWORD lpdwBytesWritten;
  char buf[32];
 
  int len = 0;
  if(source == 0) // CUR
    len = sprintf(buf, "$KE,IO,GET,CUR,%d\r\n", this->m_LineGet);
  else            // MEM
    len = sprintf(buf, "$KE,IO,GET,MEM,%d\r\n", this->m_LineGet);
 
  WriteFile(m_hFile, buf, len, &lpdwBytesWritten, NULL);  
 
 
  // Make littele pause for wait module anser
  Sleep(100); // Wait 100 ms
    
  DWORD dwBytesRead;
  unsigned char pBuff[128];
 
  ReadFile(m_hFile, &pBuff, sizeof(pBuff), &dwBytesRead, NULL);
 
  if(dwBytesRead > 0)
  {
    // We must get anser like this: #IO,<value>
 
    if( memcmp(pBuff, "#IO,", 4) == 0)
    {
      int direction = atoi( (char*)(&pBuff[4]) );
      if(direction < 0 || direction > 1)
      {
        MessageBox("Get Line fail1", "Info", MB_ICONERROR);
        return;
      }
 
      CString s1;
      s1.Format("Direction Info:\nLine: %d\nSource: ", this->m_LineGet);
 
      if(source == 0) // CUR
        s1 += "CUR\n";
      else            // MEM
        s1 += "MEM\n";
 
      if(direction == 0)
        s1 += "Direction: OUT";
      else
        s1 += "Direction: IN";
      
      MessageBox(s1, "Info", MB_ICONINFORMATION);
    }
    else
    {
      MessageBox("Get Line fail2", "Info", MB_ICONERROR);
    }    
  }
  else
  {
    MessageBox("Get Line fail3", "Info", MB_ICONERROR);
  }
}

Если софт вам показался сложным и заумным - всегда можно просто набрать команду в виде текста и отправляеть ее в каком-либо терминале, например HyperTerminal или KeTerm:

Программа KeTerm для модуля Ke-USB24A

Рисунок 2. Настройка направления линий ввода-вывода с помощью терминала

Ну а мы переходим к следуюущей статье, в которой мы будем считывать информацию с внешних датчиков через модуль Ke-USB24A в нашей собственной программе.



© Дмитрий Иванов
22 марта 2008 года
http://www.kernelchip.ru



© KERNELCHIP 2006 - 2023