2012-02-03 6 views
0

J'essaie d'utiliser un port série pour interfacer avec une caméra. Maintenant, la caméra a son propre protocole propriétaire, qui est assez simple et utilise des commandes de 6 octets et reconnaît. Maintenant, j'utilise C# pour écrire le programme qui s'interface avec la caméra, puisque cela me permet d'utiliser WPF, et je suis à l'aise avec C# de toute façon.C# SerialPort - Comportement étrange

Mon problème se pose lorsque j'essaie de configurer l'appareil photo pour qu'il récupère une image. L'objet Serial Port fonctionne très bien pour ce faire, lorsque je parcours le programme. Cependant, dès que je l'exécute à pleine vitesse, pour une raison quelconque, je me retrouve avec les messages au port étant très mal lu et même manqué. J'arrive à la fin du processus d'installation, juste avant que je commence à récupérer les données réelles, et il y a encore des commandes et des choses qui sont encore dans le tampon du port. Maintenant, cette solution est, certes, juste une tentative très hacky d'apprendre le protocole et de faire fonctionner le truc en ce moment, et j'ai l'intention de l'améliorer plus tard, mais je n'arrive pas à comprendre pourquoi. La caméra n'est pas supposée envoyer le paquet suivant jusqu'à ce que j'ai reconnu le dernier, donc je peux seulement supposer que l'objet du port série est problématique, pas la caméra ou ma gestion du protocole.

Serait-ce parce que j'ai (paresseusement, oui) obtenu cette fonction sur le fil de l'interface utilisateur?

Voici le code:

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; 

    } 

Voici la fiche technique de l'appareil photo qui décrit le protocole. http://www.4dsystems.com.au/downloads/micro-CAM/Docs/uCAM-DS-rev7.pdf

+1

aaarg mes yeux - essayez de jeter votre code de sorte qu'il semble un peu plus attrayant pour un répondeur potentiel – AnthonyBlake

+1

Peut-être préférable d'utiliser des événements plutôt que 'while (port.BytesToRead <0)' – sll

+1

un coup d'oeil à l'événement 'serliaPort.ErrorReceived' et' serialPort.DataReceived' – sll

Répondre

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

ne signifie pas que vous allez lire received.theMessage.Length octets. il peut être n'importe quoi entre 1 & received.theMessage.Length. Vous devriez vérifier la valeur retournée

+0

Je vois maintenant que c'est le problème. Y a-t-il une raison particulière à cela? Pourquoi ne remplirait-il pas mon tampon avec autant de données que possible? – Luke

+0

Votre appareil (et sa communication série) est plus lent que votre ordinateur. Vous commencez à lire immédiatement quand un octet est disponible. Peut-être que le périphérique n'a pas encore envoyé le second octet. –

+0

Je vois. Eh bien, j'ai changé mon code pour m'assurer qu'il lit tant d'octets à la fois. Je verrai si cela fonctionne. – Luke