СОПРЯЖЕНИЕ КОМПЬЮТЕРОВ С ВНЕШНИМИ УСТРОЙСТВАМИ

Яндекс цитирования

Друзья ресурса:

www.roboforum.ru




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

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

Файлы к статье (размер: 117 КБ)

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

Для установки направления ввода/вывода линии необходимо использовать команду $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. Внешнее окно программы имеет вот такой вид:

Модуль 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\nsended 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

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

© Дмитрий Иванов
22 марта 2008 года
www.pcports.ru



Контакты | Гостевая книга

© 2005-2010 сопряжение компьютеров с внешними устройствами PCPORTS.RU © Иванов Д.В.