2016-03-01 4 views
0

Я создаю программу для работы с некоторым оборудованием с использованием последовательного порта. У меня есть документация, где есть сведения о том, как отправить команду через порт. Он работает очень хорошо, но я должен получить некоторую информацию о состоянии оборудования. Я пробовал все, но я не уверен в этом развитии. Может быть, я что-то пропустил.SerialPort отправить команду и получить ответ

Из документации:

Есть полностью 21 команды, 20 команд открытия, 1 команда чтения состояния

Открыть команду:

Адрес команды фиксированное значение (0x55) блокировка номер

Адрес 0XF2 0x55 0x01

Адресная s 0XF2 0x55 0X02

Адрес 0XF2 0x55 0x03

......

Над выполнение команд

Успех возвращается: Адрес + 0x59 + 0x59

неудачи возвращает: Адрес + 0X5E + 0X5E

/// <summary> 
    /// Send open lokcer door command 
    /// </summary> 
    /// <param name="boardAddress">0 means open left slave cabinet,1 means open right slave cabinet</param> 
    /// <param name="command"></param> 
    /// <returns></returns> 
    public byte[] OpenBox(byte boardAddress, byte command) 
    { 
     var openCommand = new byte[5]; 
     openCommand[0] = (byte)(255 - boardAddress); 
     openCommand[0] = 0xF2; 
     openCommand[1] = 0x55; 
     openCommand[2] = command; 

     openCommand[3] = 0X00; 
     openCommand[4] = 0X00; 
     try 
     { 
      if (!serialPort.IsOpen) 
      { 
       //serialPort.WriteBufferSize = 5; 
       serialPort.Open(); 
      } 
      serialPort.DiscardInBuffer(); 
      serialPort.Write(openCommand, 0, 3); 
      return openCommand; 
     } 
     catch (ArgumentException ex) 
     { 
      throw new InvalidOperationException("Locker cell can not be opened.", ex); 
     } 
    } 

Он работает очень хорошо, но последние 2 байта ничего не возвращают. Они всегда 0X00. Также я использую SerialPortDataReceived, но я всегда получаю там 0.

public void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     DBException.WriteLog(""); 
     DBException.WriteLog("Serial port data received"); 
     var sp = (SerialPort)sender; 
     DBException.WriteLog("Read existing = " + sp.ReadExisting()); 
     try 
     { 
      DBException.WriteLog("Length = " + sp.BytesToRead); 
      if (serialPort.BytesToRead == 4) 
      { 
       var readBuffer = new byte[4]; 
       sp.Read(readBuffer, 0, serialPort.BytesToRead); 

       DBException.WriteLog("Read serial port :" + readBuffer.ByteArrayToString()); 

       //     RaiseLockerStatusEvent(readBuffer.ByteArrayToString()); 
      } 
     } 
     catch (Exception ex) 
     { 
      DBException.WriteLog(ex); 
     } 
    } 

ВОПРОС 1 Как получить успех или неудача возвращается? Я думаю, что они должны быть в последних двух байтах.

ВОПРОС 2 Как получить все состояния? В настоящее время я ничего не получаю.

Документация:

Команда чтения состояние блокировки: Адрес + Data1 + Data2 + Data3 Адрес: 0XF10X55 Data1 Data2 Data3 0000 lock20 ... lock17 lock16 ... lock9 lock8 ... Lock1 Первые 4 цифры фиксировано номер 0000 Образец: 0000 0000 0000 0001 0000 0001 означает, что замок1 и замок9 открыты, другие закрыты Примечание: для какого-либо электронного замка «1» означает «закрыть», «0» означает «открыто».

Мой сниппет

/// <summary> 
    /// Send check machine(cabinet) status command 
    /// </summary> 
    /// <param name="address">0 means check left cabinet, 1 means check right cabinet </param> 
    /// <returns></returns> 
    public byte[] SendCheckLockControlStatueCommand(byte address) 
    { 
     lock (this) 
     { 
      var checkCommand = new byte[6]; 
      checkCommand[0] = Convert.ToByte(255 - address); 
      checkCommand[1] = 0xF1; 
      checkCommand[2] = 0x55; 

      checkCommand[3] = 0x00; 
      checkCommand[4] = 0x00; 
      checkCommand[5] = 0x00; 
      try 
      { 
       if (!serialPort.IsOpen) 
       { 
        //     serialPort.WriteBufferSize = 5; 
        serialPort.Open(); 
       } 

       //Send inquiry command 
       serialPort.DiscardInBuffer(); 
       //     serialPort.DiscardOutBuffer(); 
       serialPort.Write(checkCommand, 0, 6); 

       return checkCommand; 
      } 
      catch (ArgumentException ex) 
      { 
       throw new InvalidOperationException("Locker cell can not be opened.", ex); 
      } 
     } 
    } 

ответ

0

Никогда не использовать асинхронный DataReceived событие так, как вы делаете! Вам нужно решить: либо вы хотите общаться синхронно или асинхронно. Если вы хотите последнего, никогда не звоните или даже не ждите в DataReceived.

Вместо этого поместите полученный материал в буфер и обработайте его, как только сообщение будет завершено.

Кроме того, звонок ReadExisting уже считывает все данные из последовательного порта, который находится там, так что Read, вероятно, заблокирован!

Это должно скорее выглядеть примерно так:

List<byte> receivedBinaryData = new List<byte>(); 

public void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    var sp = (SerialPort)sender; 
    string availableData = sp.ReadExisting(); 
    byte[] inputAsASCII = Encoding.ASCII.GetBytes(availableData); 

    DBException.WriteLog(""); 
    DBException.WriteLog("Serial port data received"); 
    DBException.WriteLog("Read existing = " + availableData); 
    try 
    { 
     // Add the bytes to the receivedBinaryData List 
     receivedBinaryData.AddRange(inputAsASCII); 

     // If the message length is reached or exceeded, do something 
     if (receivedBinaryData.Length >= 4) 
      .... 
    } 
    catch (Exception ex) 
    { 
     DBException.WriteLog(ex); 
    } 
} 
+0

Большое спасибо. Наверное, я вникаю в это. Но на самом деле я предпочитаю общаться синхронно. И я думаю, что мне нужно подождать некоторое время в методе SendingCommand и затем прочитать данные. Не могли бы вы объяснить это, пожалуйста? Я буду признателен. –

+0

Я думаю, что нашел правильный ответ для чтения данных из последовательного порта. Он будет использовать AutoResetEvent, все детали здесь. http://stackoverflow.com/questions/11782053/serialport-wait-for-response Еще раз спасибо. –

+0

Если вы хотите синхронно общаться, вы можете позвонить 'Read' после того, как вы напишете, пока не получите свой ответ. Обратите внимание, что это может заблокировать ваше приложение навсегда, если ответа нет. Использование WaitHandle с таймаутом действительно может быть лучшим решением. –

Смежные вопросы