2012-02-03 3 views
0

Я пытаюсь использовать последовательный порт для взаимодействия с камерой. Теперь у камеры есть собственный собственный протокол, который довольно прост и использует 6-байтные команды и подтверждения.C# SerialPort - Странное поведение

Теперь я использую C# для написания программы, которая взаимодействует с камерой, поскольку это позволяет мне использовать WPF, и мне все равно нравится C#.

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

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

Может быть, потому что я (лениво, да) получил эту функцию в потоке пользовательского интерфейса?

Вот код:

private void retreivePhoto() 
    { 
     progressBar1.Visibility = Visibility.Visible; 
     photo = new FileStream(Environment.CurrentDirectory + @"/photos/" + (photoNum++) + ".jpg", FileMode.OpenOrCreate); 
     port.Open(); 
     progressBar1.Value = 0.5; 
     setup.theMessage = setup.JPEG(); 
     port.Write(setup.theMessage, 0, setup.theMessage.Length); 
     while (port.BytesToRead < 0) ; 
     port.Read(received.theMessage, 0, received.theMessage.Length); 
     setup.theMessage = setup.Package(); 
     port.Write(setup.theMessage, 0, setup.theMessage.Length); 
     while (port.BytesToRead < 0) ; 
     port.Read(received.theMessage, 0, received.theMessage.Length); 
     setup.theMessage = (byte[])Message.SNAPSHOT.Clone(); 
     port.Write(setup.theMessage, 0, setup.theMessage.Length); 
     while (port.BytesToRead < 0) ; 
     port.Read(received.theMessage, 0, received.theMessage.Length); 
     setup.theMessage = (byte[])Message.BLANK.Clone(); 
     setup.theMessage[1] = (byte)Message.MessageTypes.GETPICTURE; 
     setup.theMessage[2] = (byte)Message.PictureType.SNAPSHOT; 
     port.Write(setup.theMessage, 0, setup.theMessage.Length); 
     while (port.BytesToRead < 0) ; 
     port.Read(received.theMessage, 0, received.theMessage.Length); 
     while (port.BytesToRead < 0) ; 
     port.Read(received.theMessage, 0, received.theMessage.Length); 
     int length = (received.theMessage[5] << 16) + (received.theMessage[4] << 8) + received.theMessage[3]; 
     length /= data.theMessage.Length-6; 
     byte[] temp = {0xaa, 0x0e, 0x00, 0x00, 0x00, 0x00}; 
     port.DiscardInBuffer(); 
     port.Write(temp, 0, temp.Length); 

     int next = 0; 
     int bytes; 

     for (int i = 0; i < length; i++) 
     { 
      if ((bytes = port.BytesToRead) > 0) 
      { 
       port.Read(data.theMessage, 0, data.theMessage.Length); 
       if (bytes < data.theMessage.Length) 
       { 
        photo.Write(data.theMessage, 4, bytes - 6); 
       } 
       else 
       { 
        photo.Write(data.theMessage, 4, data.theMessage.Length - 6); 
       } 
       photo.Flush(); 
      } 


      next = ((data.theMessage[1] << 8) + data.theMessage[0]) + 1; 

      byte[] nextBytes = System.BitConverter.GetBytes(next); 

      if (length - i == 1) 
      { 
       temp[4] = temp[5] = 0xf0; 
      } 
      else 
      { 
       temp[4] = nextBytes[0]; 
       temp[5] = nextBytes[1]; 
      } 

      port.Write(temp, 0, temp.Length); 
     } 

     progressBar1.Value = 1.0; 
     photo.Flush(); 
     photo.Close(); 
     port.Close(); 
     progressBar1.Visibility = Visibility.Hidden; 

    } 

Вот техническое описание камеры, которая описывает протокол. http://www.4dsystems.com.au/downloads/micro-CAM/Docs/uCAM-DS-rev7.pdf

+1

aaarg мои глаза - попробуйте выложить код, чтобы он выглядел немного более привлекательным для потенциального ответчика. – AnthonyBlake

+1

Возможно, лучше использовать события, а не 'while (port.BytesToRead <0)' – sll

+1

Take посмотрите на событие 'serliaPort.ErrorReceived' и' serialPort.DataReceived' – sll

ответ

1
while (port.BytesToRead < 0) ; 
port.Read(received.theMessage, 0, received.theMessage.Length); 

Это не значит, что вы будете читать received.theMessage.Length байт. это может быть что угодно между 1 & received.theMessage.Length. Вы должны проверить возвращаемое значение

+0

Теперь я вижу, что это проблема. Есть ли какая-то особая причина в этом? Почему бы не просто заполнить мой буфер как можно больше данных? – Luke

+0

Ваше устройство (и последовательная связь) работает медленнее вашего компьютера. Вы начинаете читать сразу, когда доступен байт. Возможно, устройство еще не отправило второй байт. –

+0

Я вижу. Ну, я изменил свой код, чтобы убедиться, что он читает так много байтов за раз. Я посмотрю, работает ли это. – Luke

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