Le composant TComPort, description25/11/2003
Par
Vincent PETIT (home page) niveau : facile durée : 15 minutes Cet article a pour but de montrer comment accèder au port série du PC avec C++ Builder Avant-Propos 1. Généralité sur le port série 1.1. Le brochage vue de face 1.2. Format des données 2. Le composant TComPort 2.1. Ouverture du port 2.2. Fermeture du port 2.3. Changement de niveau sur les sorties RTS et DTR 2.3. État d'une broche d'entrée, CTS, DSR, RLSD 2.4. Ecrire une chaîne de caractères sur TxD 2.5. Ecrire une valeur sur TxD 2.6. Lecture d'une chaîne de caractères sur RxD 2.7. Lecture d'une valeur sur RxD 2.8. Vérifier les erreurs sur le port série 2.9. Nombre d'octet présent dans le buffer d'entrée 2.10. Vider les buffers d'entrée et de sortie 2.11. Attendre un événement pour exécuter une action 2.12. Changer les paramètres du port 2.13. Stocker les paramètres du port dans un fichier .ini 2.14. Lire les paramètres du port depuis un fichier .ini 2.15. Gestion des exceptions Conclusion Avant-Propos
Dans les applications industrielles et domotiques, nous avons souvent besoin d'allier un système
électronique à une application logicielle via un port d'entrée/sortie de l'ordinateur. Ce peut être
le port parallèle, le port série ou même l'USB. Par exemple un modem externe, sur le port série ou
une imprimante avec le port parallèle. Ceci dans un but d'allégement des montages électroniques et
de commodité pour tout ce qui est calcul. Bien que ce ne soit pas toujours possible, par exemple
pour des systèmes embarqués, ou là l'emploi d'un micro contrôleur est inévitable. Ce tutoriel à pour but de voir, quelques méthodes de ce composant, pour l'écriture, la lecture, les mises à 1 des niveaux sur certaine broche, voir l'état des entrées etc... sur le port série. 1. Généralité sur le port série 1.1. Le brochage vue de face
Affectation:
Description des signaux:
D'un point de vue électronique, les signaux TX et RX en sortie des prises répondent
aux normes RS232, c'est à dire: 1 logique compris entre -3 et -25V et 0 logique
compris entre +3 et +25V. Bien sur, nous pouvons utiliser les broches comme bon nous semble, c'est à dire par exemple, se servir de CTS autrement que pour signaler à l'ordinateur que le périphérique est prêt à recevoir, mais il vaut quand même mieux respecter la norme. 1.2. Format des données
La communication série nécessite trois fils au minimum: une masse pour référencer les signaux,
un fil émetteur et un fil récepteur. Notre liaison série est en effet full-duplex, c'est à dire
que l'on peut émettre et recevoir en même temps (comme le téléphone par exemple).
La différence principale entre le port parallèle et le port série est que les informations ne
sont pas transmises simultanément sur des fils séparés (D0 à D7) mais les unes après les autres
sur un même fil. Cela amène une économie de câble (un fil au lieu de 8) mais un montage décodeur
devient nécessaire pour retransformer les données sérialisées. Il est bon de rappeler que le port série, lors d'une écriture par exemple, envoi le bit de poids faible (LSB) en premier. La liaison série est totalement asynchrone. Aucune horloge n'est transmise. Il faut donc se mettre d'accord sur la vitesse de transfert des bits et rajouter des bits de synchronisation. Voici un petit résumé des différents paramètres rentrant en jeu lors d'une communication série:
2. Le composant TComPort 2.1. Ouverture du port
On définit préalablement, le port COM1, 2, 3 ou 4 dans l'inspecteur d'objets, (propriété Port).
//------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ComPort1->Connected=true; //Ouverture du port (prêt à communiquer) } //-------------------------------------------------------
Le port et maintenant ouvert et prêt à communiquer avec un périphérique externe.
2.2. Fermeture du port //------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { ComPort1->Connected=false; //Fermeture du port (arrêt des communications) } //-------------------------------------------------------
Le port série est fermé, toutes tentatives de lecture, d'écriture ou autre, déclenchera une erreur.
2.3. Changement de niveau sur les sorties RTS et DTR
Il peut être nécessaire d'envoyer un signal au montage relié au port du PC par une sortie. Admettons
que celui ci ai besoin d'une impulsion pour diverses raisons. Nous pouvons faire ceci via RTS.
//------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ComPort1->SetRTS(true); //Mise à +15V de RTS ComPort1->SetRTS(false); //Mise à -15V de RTS } //-------------------------------------------------------
ou par DTR comme cela.
//------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ComPort1->SetDTR(true); //Mise à +15V de DTR ComPort1->SetDTR(false); //Mise à -15V de DTR } //------------------------------------------------------- 2.3. État d'une broche d'entrée, CTS, DSR, RLSD
Il peut être utile de savoir quelle est le niveau sur une broche d'entrée. Il faut pour cela, agir dans les événements, des ces broches. Prenons un exemple avec CTS. //------------------------------------------------------- void __fastcall TForm1::ComPort1CTSChange(TObject *Sender, bool OnOff) { if (OnOff == true) Button1->Caption = "État haut sur CTS"; //État haut = +15V else Button1->Caption = "État bas sur CTS"; //Etats bas = -15V } //-------------------------------------------------------
Si le Caption du TButton indique "Etats haut sur CTS", c'est que le niveau sur celle ci est +15V. Nous pouvons procéder de même pour les autres événements, DSR et RLSD (DCD). 2.4. Ecrire une chaîne de caractères sur TxD
Vous serez peut être amené à envoyer des caractères ASCII vers le correspondant. Voilà un petit exemple de la manière à procéder pour faire cela. //------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { AnsiString Phrase; Phrase = Edit1->Text; ComPort1->WriteStr(Phrase); //Écrit toute la chaîne "Phrase" sur le port série } //------------------------------------------------------- 2.5. Ecrire une valeur sur TxD //------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { unsigned char tableau[7] = {'V', 'i', 'n', 'c', 'e', 'n', 't'}; ComPort1->Write(tableau, 7); //Ecrit 7 octets de "tableau" sur le port série } //------------------------------------------------------- 2.6. Lecture d'une chaîne de caractères sur RxD
Après avoir envoyé une chaîne de caractères sur la ligne TxD, il serait bien de savoir comment la recevoir. Écrivons dans l'événement OnRxChar:
//------------------------------------------------------- void __fastcall TForm1::ComPort1RxChar(TObject *Sender, int Count) { AnsiString Phrase2; ComPort1->ReadStr(Phrase2, Count); //Lit les "Count" octet(s) présent(s) dans le buffer d'entrée et le(s) place dans Phrase2 } //-------------------------------------------------------
La phrase reçut est stockée dans le buffer d'entrée du port, qui cela dit en passant est paramètrable en taille dans l'inspecteur d'objets, propriété Buffer / Input et OutputSize. Dans cette exemple, nous remarquons bien que la lecture se fait caractère par caractère, ReadStr vient effacer le caractère dans le buffer, puis il passe au suivant et refait de même. Une lecture peut se faire, aussi, en dehors de l'événement OnRxChar. 2.7. Lecture d'une valeur sur RxD
Toujours dans l'événement OnRxChar :
//------------------------------------------------------- void __fastcall TForm1::ComPort1RxChar(TObject *Sender, int Count) { unsigned char *Buf = new unsigned char [Count]; ComPort1->Read(Buf, Count); //Lit "Count" octet(s) présent(s) dans le buffer d'entrée et le(s) place dans "Buf" delete [] Buf; Buf = NULL; } //-------------------------------------------------------
Une lecture peut aussi se faire hors de cette événement.
2.8. Vérifier les erreurs sur le port série
Il est possible, via l'événement OnError, de savoir si une erreur a eu lieu sur le port série. //------------------------------------------------------- void __fastcall TForm1::ComPort1Error(TObject *Sender, TComErrors Errors) { if (Errors.Contains(ceFrame)) { // Une erreur de frame a eu lieu, mauvaise vitesse de communication !? } if (Errors.Contains(ceOverrun)) { // Une erreur d'overrun a eu lieu, la donnée suivante est erronée !? } // voir l'aide de TComPort sur "LastErrors" pour continuer la gestion des erreurs } //------------------------------------------------------- 2.9. Nombre d'octet présent dans le buffer d'entrée //------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { int NbrBits; NbrBits = ComPort1->InputCount(); } //-------------------------------------------------------
Chaque fonction de lecture Read, ReadStr etc... décrémente InputCount.
2.10. Vider les buffers d'entrée et de sortie
Nous pouvons effacer les Buffers, si une donnée est jugée inexploitable pour quelques raisons que se soit.
//------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ComPort1->ClearBuffer(true, false); // buffer d'entrée vidé, celui de sortie intacte } //------------------------------------------------------- 2.11. Attendre un événement pour exécuter une action
Lors d'un dialogue, il est parfois nécessaire d'attendre une réponse du correspondant avant de lui envoyer une commande.
//------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ComPort1->Events = TComEvents(); // Effacer tous les évenements ComPort1->Connected = true; TComEvents Ev; Ev << evRxChar; ComPort1->WaitForEvent (Ev, 0, 5000); // Attend un événement OnRxChar ou 5 secondes avant de continuer if (Ev.Contains(evRxChar)) { // Executer une action, une donnée est arrivée } else { // Executer autre action, les 5 secondes se sont écoulées } } //-------------------------------------------------------
L'utilisation de WaitForEvent se fait de la manière suivante :
2.12. Changer les paramètres du port
La première posibilité est d'appeler la méthode ShowSetupDialog
//--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ComPort1->ShowSetupDialog (); } //---------------------------------------------------------------------------
La seconde est de placer par exemple un TComRadioGroup et d'affecter ses propriétés:
La même technique peut être employé pour un TComComboBox.
2.13. Stocker les paramètres du port dans un fichier .ini
Lors de la fermeture de l'application nous pouvons écrire.
//--------------------------------------------------------------------------- void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) { ComPort1->StoreSettings (stIniFile, GetCurrentDir() + "\\mon_fichier.ini"); ComPort2->StoreSettings (stIniFile, GetCurrentDir() + "\\mon_fichier.ini"); } //---------------------------------------------------------------------------
Attention à prendre les précautions nécessaire en cas d'échec d'écriture !
2.14. Lire les paramètres du port depuis un fichier .ini
Lors de la création de l'application nous pouvons écrire.
//--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { ComPort1->LoadSettings (stIniFile, GetCurrentDir() + "\\mon_fichier.ini"); ComPort2->LoadSettings (stIniFile, GetCurrentDir() + "\\mon_fichier.ini"); ComRadioGroup1->UpdateSettings (); // si vous avez placé un TComRadioGroup // avec la méthode expliquée en 2.12 } //---------------------------------------------------------------------------
On peut procéder de la même manière pour un TComComboBox.
2.15. Gestion des exceptions
Il est possibles de gérer les exceptions provoquées par le composant TComPort.
//--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { AnsiString msg = ""; try { ComPort1->Connected = true; } catch (EComPort &e) { switch (e.Code) { case CError_OpenFailed : msg = "Votre port série est déjà ouvert" ; break ; case CError_WriteFailed : msg = "Erreur d'écriture sur le port série" ; break ; // voir l'aide de TComPort sur "Error codes" pour continuer la gestion des erreurs } ShowMessage(msg); } } //--------------------------------------------------------------------------- Conclusion
Attention le composant TComPort se révèle être inactif sans l'emploi des TComLed, il vous suffit de placer 3
TComLed et d'attribuer leurs propriétés:
Malheureusement le port série tend à disparaître sur les ordinateurs actuels pour laisser place aux ports USB. Referez vous aux liens ci
dessous pour savoir où et comment installer le composant TComPort.
Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur.
La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur. |