2017-03-23 1 views
1

J'essaie d'établir une communication série entre mon microprocesseur et l'application de formulaire C#.Port d'écoute C# SerialPort

Le problème est, les données qui viennent du microprocesseur peuvent venir en 2 secondes ou 5 secondes ou 10 secondes. Je veux dire qu'il n'y a pas de temps spécifique et je voudrais écouter le port et obtenir des données s'il est arrivé en 2 secondes si ce n'est pas, attendez les données jusqu'à ce qu'il arrive.

J'ai essayé à ceci avec serialport.readline(); mais le formulaire se bloque alors que le readline bloque, donc j'ai essayé de faire avec les backgroundworkers quand je fais cela, je ne peux pas fermer le formulaire pendant que backgroundworker est occupé parce que la commande readline bloque le programme entier. Tout ce que je dis est, s'il vous plaît donnez-moi quelques indices sur l'écoute du port tout en venant le temps de données n'est pas spécifique.

Merci pour votre temps (désolé pour l'anglais, il est pas bien)

+0

Avez-vous un échantillon de code que vous pouvez nous montrer? –

+0

en essayant d'ajouter du nouveau à stackoverflow – oakar

+0

A l'intérieur de votre événement de fermeture de formulaire, vous pourriez peut-être essayer d'appeler 'Close()' sur le port série. Cela devrait débloquer l'appel en lecture si vous utilisez un BackgroundWorker, non? – nicholas

Répondre

1

Vous pouvez utiliser le SerialPort.DataReceived Event pour obtenir le async de données. Après avoir créé une instance de la classe SerialPort, vous pouvez ajouter des gestionnaires d'événements au SerialPort. Ces gestionnaires d'événements sont appelés si des données ont été reçues. À l'intérieur du gestionnaire, vous pouvez lire les données du tampon d'entrée et faire ce que vous voulez.

private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
{ 
    SerialPort sp = (SerialPort)sender; 
    string indata = sp.ReadExisting(); 
    //Do what ever you want with the data 
} 

C'est une solution très commune pour obtenir des données dans les étapes de temps unregular qui exécute votre application sans le bloquer.

+0

mais je ne reçois pas une seule donnée par exemple, quand j'écris A au port série je reçois 400 données avec un espace entre les données et les données commence par "!" et se termine par "\ n" donc j'utilise des tableaux et si j'écris comme vous l'avez dit, les tableaux ne sont pas relaible. – oakar

+0

Pouvez-vous poster un exemple? – Fruchtzwerg

+0

@oakar diviser la chaîne par un espace et vous obtenez une chaîne [] de 400 éléments –

1

Vous pouvez utiliser l'événement DataReceived. Il sera déclenché chaque fois que de nouvelles données arrivent sur votre port. Vous devez vous inscrire pour comme ceci:

SerialPort port = new SerialPort(/*your specification*/); 
port.DataReceived += Port_DataReceived; 

Dans le gestionnaire d'événements alors vous lire les données entrantes

private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    SerialPort port = sender as SerialPort; 

    if (port != null) 
    { 
     var incoming_message = port.ReadExisting(); 
    } 
} 

Maintenant, il vous suffit d'ouvrir le port et écouterez automatiquement. REMARQUE! les données entrantes arrivent sur un thread différent du thread principal. Donc, si vous voulez utiliser les contrôles de votre formulaire pour l'affichage, vous devez utiliser BeginInvoke

Si vos données est marqué à la fin avec \n vous pouvez essayer d'utiliser la méthode ReadLine:

var incoming_message = port.ReadLine(); 

Ou vous pouvez essayer ReadTo

var incoming_message = port.ReadTo("\n"); 

EDIT:

Si c'est si longtemps, que vous devriez le lire en lots. Vous pouvez aussi essayer de le gérer en boucle.

private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    SerialPort port = sender as SerialPort; 

    string message = ""; 
    if (port != null) 
    { 

     while(port.BytesToRead > 0) 
     { 
      message += port.ReadExisting(); 
      System.Threading.Thread.Sleep(500); // give the device time to send data 
     } 
    } 
} 

EDIT 2:

Si vous souhaitez stocker les données déclarent un List<string> en dehors du gestionnaire d'événements et ajoutez la chaîne lorsqu'elle est entièrement lu.

List<string> dataStorage = new List<string>(); 


private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    SerialPort port = sender as SerialPort; 

    string message = ""; 
    if (port != null) 
    { 

     while(port.BytesToRead > 0) 
     { 
      message += port.ReadExisting(); 
      System.Threading.Thread.Sleep(500); // give the device time to send data 
     } 
     // add now the entire read string to the list 
     dataStorage(message); 
    } 
} 

Depuis le gestionnaire d'événements ne sais pas si vous avez ou envoyer AB Accumulez l'ensemble des messages reçus dans une liste. Vous connaissez l'ordre dans lequel vous envoyez vos commandes, plus tard, vous pouvez prendre le message correspondant et utiliser Split pour obtenir les 400 entrées dans un tableau:

string [] A_array_data = dataStorage[0].Split(" "); 
+0

Je l'ai utilisé mais Read.existing() n'attend pas de données entières par exemple quand j'écris A sur le port série je reçois 400 données avec un espace entre les données et les données commençant par "!" et se termine par "\ n" donc j'utilise des tableaux et si j'écris comme vous avez dit les tableaux ne sont pas relaible (j'utilise split) – oakar

+0

@oakar combien de temps faut-il pour que le périphérique transmette les 400 octets? est-ce des octets? ou 400 caractères? –

+0

Avez-vous essayé 'ReadLine()'? –