Com port et thread

fantasio36 Messages postés 21 Date d'inscription mercredi 30 juillet 2008 Statut Membre Dernière intervention 3 octobre 2011 - 30 sept. 2008 à 06:20
masbaby Messages postés 2 Date d'inscription vendredi 10 juillet 2009 Statut Membre Dernière intervention 22 août 2009 - 22 août 2009 à 23:41
Re-Bonjour a tous, je suis mega bloque depuis une bonne semaine........A l'aide!!
J'attends dans une routine une lecture de 1024 bytes sur le port COM que je dois lire par paquet de 64 bytes. Mon probleme est que je n'arrive pas a lire l'event de reception qui a lieu dans la routine dediee dans une autre partie du soft. Du coup je me retrouve bloque et il me faudrait sortir de cette routine de lecture pour que l'event de reception puisse etre leve, puis retour dans ma routine de lecture....bref, comment est-il possible par exemple de mettre un flag a 1 dans ma routine de reception, sachant que cette routine de reception doit pouvoir venir interrompre l'execution de ma routine d'attente de mise a 1 de ce flag? Ou bien est-il possible de faire autrement??? Si c'est pas clair, je peux  donner plus de details!!

Merci,
Florent

15 réponses

maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
30 sept. 2008 à 08:48
Salut,

En effet c'est pas clair

Tu aurais un exemple de code sous la main ?

@+

Dédé
0
leprov Messages postés 1160 Date d'inscription vendredi 23 juillet 2004 Statut Membre Dernière intervention 21 octobre 2010 17
30 sept. 2008 à 09:33
Non cest carrément pas clair. Pour lire dans un port COM, en général on a deux solutions :
1 - s'abonner a l'event datareceived de l'objet serialport et lire dans la méthode handler de l'event
2 - créer un thread, puis lire en boucle dans ce thread. A priori dans ton cas, le mieux est d'utiliser cette solution. tu lis les données en boucle jusqu'a ce que ta trame soit complète, et une fois que cest le cas, tu la traite, puis tu te remet en attente de lecture (le mieux étant de fournir cette trame à un autre thread qui s'occupera de gérer tout ca, pour ne pas interrompre la lecture au cas ou quelque chose d'autre arriverait)
0
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
30 sept. 2008 à 09:39
Sinon, tu peux aussi utiliser la propriété BaseStream de ton SerialPort, et là tu peux mettre ce que tu veux comme Stream avec. De plus, tu peux l'utiliser en asynchrone, ce qui ne nécessitera pas de gérer un autre thread (comme gérer l'arret de ce thread à l'arret du programme).
0
fantasio36 Messages postés 21 Date d'inscription mercredi 30 juillet 2008 Statut Membre Dernière intervention 3 octobre 2011
30 sept. 2008 à 09:44
OK, voici en resume/simplifie ce que j'ai:

routine pour la requete de 256 bytes:

    private void Button_Readfromdevice(object sender, EventArgs e)
        {
          .....
                COMport.Write(buffer, 0, 19);  // requete pour 64 bytes

               while (flag_received != true);
                flag_received = false;

               Read_64Bytes_from_Buffer();

              
               COMport.Write(buffer, 0, 19);  // requete pour 64 bytes supplementaires

               while (flag_received != true);

                flag_received = false;


               Read_64Bytes_from_Buffer();

               COMport.Write(buffer, 0, 19);  // requete pour 64 bytes supplementaires

               while (flag_received != true);

                flag_received = false;


               Read_64Bytes_from_Buffer();

               COMport.Write(buffer, 0, 19);  // requete pour 64 bytes supplementaires

               while (flag_received != true);

                flag_received = false;


               Read_64Bytes_from_Buffer();

               // 256 bytes recus

        }

routine de reception com port:
       
public static void comport_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
          flag_received = true;
         }

Je commence a croire qu'il me faut faire du multi threading, mais pour le moment rien ne fonctionne du tout!!
En fait sur un microcontrolleur on a une interruption de generee lorsque je recois une trame sur le COM, mais je n'arrive pas a faire qqchose de similaire sur le visual C#. Je reste desesperement  bloque sur le test du flag de reception....

Ton aide/suggestions sont grandement les bienvenus!! Et si c'est tjrs pas clair, n'hesite pas a me le faire savoir!
Merci,
Florent
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
30 sept. 2008 à 09:54
Essaie ce code :
            byte[] requette;
            //requete pour 64 bytes
            COMPort.Write(requette, 0, 19);

            List trame = new List();
            byte[] buffer = new byte[64];
            while (trame.Count < 1024)
            {
                //Réception de 64bits
                COMPort.BaseStream.Read(buffer, 0, buffer.Length);
                //stocke le buffer dans la trame
                trame.AddRange(buffer);
            }
            //Récupère le buffer complet
            buffer = trame.ToArray();
Pas besoin de gérer l'évènement "DataReveived"

Si ça ne marche pas, je t'en mettrait un autre avec de l'asynchrone...
0
fantasio36 Messages postés 21 Date d'inscription mercredi 30 juillet 2008 Statut Membre Dernière intervention 3 octobre 2011
30 sept. 2008 à 10:35
Merci pour ta reponse super rapide, je vais essayer cela de suite! Serais-t-il possible que tu me mette l'autre version aussi, asynchrone?? J'ai essaye gras de chose a ce sujet, avec des begininvoke et autres trucs tordus, ca n'a jamais marche!!!

Merci bcp pour ton aide,
Florent
0
fantasio36 Messages postés 21 Date d'inscription mercredi 30 juillet 2008 Statut Membre Dernière intervention 3 octobre 2011
30 sept. 2008 à 11:10
Re-salut,
Je viens d'essayer mais les valeurs retournees dans le buffer sont tres bizarres, je me prends pas mal de 0x1f au debut de la trame et le reste des data semblent erronées...Lors de mes precedents essais, j'avais remarque que ca marchait tjrs si j'attendais l'event data_received. Par contre lors de mes essais precedents je faisais un while (COMPort.BytesToRead <= 64); mais ca me donnait aussi au final des data erronees...Est-il possible d'implementer la methode asynchrone dont tu m'as parle?

Merci encore pour l'aide!
Florent
0
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
30 sept. 2008 à 11:16
Essaie avec celui-là :

            byte[] requette;
            //requete pour 64 bytes
            COMPort.Write(requette, 0, 19);

            List trame = new List();
            byte[] buffer = new byte[64];
            while (trame.Count < 1024)
            {
                //Réception de 64bits
                int read = COMPort.BaseStream.Read(buffer, 0, buffer.Length);
                //stocke le buffer dans la trame
                for (int i = 0; i < read; i++)
                {
                    trame.Add(buffer[i]);
                }
            }
            //Récupère le buffer complet
            buffer = trame.ToArray();

Tes données erronées en début, je ne sais pas... C'est peut-être un résidu de ce qu'il y a dans le buffer de ton port.
Avant d'envoyer ta requête, essaie d'ajouter :
            COMPort.DiscardInBuffer();

Je vois pour te faire la version asynchrone...
0
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
30 sept. 2008 à 11:28
Version asynchrone :

        private System.IO.Ports.SerialPort COMPort;
        private byte[] buffer;
        private List trame;

        private void StartRead(byte[] requette)
        {
            //requete pour 64 bytes
            COMPort.DiscardInBuffer();
            COMPort.Write(requette, 0, 19);

            trame = new List();
            buffer = new byte[64];
            COMPort.BaseStream.BeginRead(buffer, 0, buffer.Length, this.COMPort_Read, null);
        }

        private void COMPort_Read(IAsyncResult result)
        {
            //Fin de lecture
            int read = COMPort.BaseStream.EndRead(result);
            for (int i = 0; i < read; i++)
            {
                trame.Add(buffer[i]);
            }
            if (trame.Count >= 1024)
            {
                //Trame complète lue
            }
            else
            {
                //Continue à recevoir
                COMPort.BaseStream.BeginRead(buffer, 0, buffer.Length, this.COMPort_Read, null);
            }
        }

Tu appelles "StartRead" avec ta requête, et tu fais ton traitement de trame complète à l'endroit où c'est marqué "trame complète lue".

Voilàààààà

@+

Dédé
0
fantasio36 Messages postés 21 Date d'inscription mercredi 30 juillet 2008 Statut Membre Dernière intervention 3 octobre 2011
30 sept. 2008 à 11:29
MErci bcp dede!
Je m'en vais essayer tout cela.........DE SUITE!!!!!!!!

A+
Florent
0
masbaby Messages postés 2 Date d'inscription vendredi 10 juillet 2009 Statut Membre Dernière intervention 22 août 2009
30 juil. 2009 à 18:20
Bonjours à tous,

J'ai exactement le meme type de soucis avec le event handler "data_received".
Avec cette methode étant donné que j'envoi des requetes de message avec un thread toute les 80ms (pourtant avec une pause de 80 ms entre chaque envoi) ne permet pas de récupérer les messages arrivé proprement(Ils sont tronqués).
J'ai regardé attentivement vos solutions proposé pour la reception de message mais celle ci ne propose pas de traiter ça dans un autre thread paralléle à l'envoi ou y à t'il une solution plus viable et stable.

A bientot

GTA
0
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
4 août 2009 à 10:44
Bonjour,

Si tes messages sont tronqués, tu dois d'abord les mettre dans un buffer (un MemoryStream ou un tableau de byte) et ne traiter ton message que si il est complet.
0
fantasio36 Messages postés 21 Date d'inscription mercredi 30 juillet 2008 Statut Membre Dernière intervention 3 octobre 2011
5 août 2009 à 04:35
Salut,
De memoire je me rappelle ne jamais avoir trouve l'explication a mon probleme de message tronque. Je pense juste qu'il y a un truc louche du cote de l'outil microsoft plutot que du cote de mon code (qui en passant reste une simple application COM port, rien d'extraordinaire...). J'ai du rajoute des flag (volatile bool) avec une tempo de plusieurs centaines de ms qui attend que le bool passe a true dans la routine de reception du com port. Si c'est pas le cas on relance la requete. Une fois que le flag passe a true, la je verifie a l'aide d'un checksum que les data ne sont pas corrompues. Voila, c'est la seule solution qui marche pour moi, je me suis casse les dents sur ce probleme des semaines!!

A+
Florent
0
maitredede Messages postés 153 Date d'inscription vendredi 9 août 2002 Statut Membre Dernière intervention 18 septembre 2009
5 août 2009 à 09:23
Salut,

Plutôt que d'utiliser une boucle avec une tempo, essaie avec un System.Threading.ManualResetEvent
En gros, ça bloque le thread appelant tant qu'un autre n'a pas dit "T'as le droit de continuer", ou bien que tu aie atteint un timeout. C'est plus propre que les boucles à temporisation.

@+

Dédé
0
masbaby Messages postés 2 Date d'inscription vendredi 10 juillet 2009 Statut Membre Dernière intervention 22 août 2009
22 août 2009 à 23:41
Salut tout le monde,

Desolé de reagir si tardivement j'etais en vacance...
Donc il y a du nouveau quand meme!!
Je ne peux pas metre le thread d'nvoi en attente car ce thraed doit resté constament periodique de 80 ou 100ms (connection avec un peripherique exterieur sera perdu! J'ai testé).
Néanmoins j'arrive maintenant à récupéré des messages si il ne sont pas trop long... dans l'ordre de 10 ou 12 octet environ...
Si le message reçu est plus je recois soit le debut ou soit la fin et ceci peridiquement... l'affichage me l'informe!
Tanto les 8 ou 10 premiers tant les 6,8, 4 derniers et vice versa... J'utilise la dll IO.Port de Visual studio 2005

GTA
0
Rejoignez-nous