Le composant TComPort, description25/11/2003
Par
Vincent PETIT (home page) Patrick 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:
Nom | C++ Builder | Broche | Sens | DCD | RLSD | Broche n°1 | Entrée | RxD | Rx | Broche n°2 | Entrée | TxD | Tx | Broche n°3 | Sortie | DTR | DTR | Broche n°4 | Sortie | Masse | -- | Broche n°5 | -- | DSR | DSR | Broche n°6 | Entrée | RTS | RTS | Broche n°7 | Sortie | CTS | CTS | Broche n°8 | Entrée | RI | RING | Broche n°9 | Entrée |
Description des signaux:
- Broche 1 : DCD ou RLSD (Data Carrier Detect) ou
(Receive Line Signal Detect) cette ligne est une entrée active à
l'état haut. Elle signale à l'ordinateur qu'une liaison a été
établie avec un correspondant.
- Broche 2 : RxD (Receive Data) cette ligne est une
entrée. C'est ici que transitent les informations du correspondant
vers l'ordinateur.
- Broche 3 : TxD (Transmit Data) cette ligne est une
sortie. Les données de l'ordinateur vers le correspondant sont
véhiculées par son intermédiaire.
- Broche 4 : DTR (Data Terminal Ready) cette ligne est
une sortie active à l'état haut. Elle permet à l'ordinateur de signaler
au correspondant que le port série a été libéré et qu'il peut être
utilisé s'il le souhaite.
- Broche 5 : GND (Ground) c'est la masse.
- Broche 6 : DSR (Data Set Ready) cette ligne est une entrée
active à l'état haut. Elle permet au correspondant de signaler qu'une
donnée est prête.
- Broche 7 : RTS (Request To Send) cette ligne est une
sortie, qui quand elle est active est à l'état haut. Elle indique au
correspondant que l'ordinateur veut lui transmettre des données.
- Broche 8 : CTS (Clear To Send) cette ligne est une entrée
active à l'état haut. Elle indique à l'ordinateur que le correspondant est
prêt à recevoir des données.
- Broche 9 : RI ou RING (Ring Indicator) cette ligne est une
entrée active à l'état haut. Elle permet à l'ordinateur de savoir qu'un
correspondant veut initier une communication avec lui.
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:
- Longueur de mot : sur le PC, le BIOS ne permet une longueur de mot que de 7 ou 8 bits.
- Parité : le mot transmis peut être suivi d'un bit de parité qui sert à détecter
les erreurs éventuelles de transmission. Il existe deux parités: la parité paire et la parité
impaire. Dans le cas de la parité paire, et pour le mot 10110101 contenant 5 états à 1, le bit
de parité sera 1 amenant ainsi le nombre total de 1 à un nombre pair (6). Dans le cas de la parité
impaire, le bit de parité aurait été 0 car le nombre total de 1 est déjà impair. L'intérêt de ce
rajout est le suivant: si jamais lors de la transmission un état 1 est transformé en état 0
(perturbation du canal par des parasites par exemple) le nombre total de 1 change et donc le bit de
parité recalculé par le récepteur ne correspond plus à celui reçu. L'erreur est donc détectée.
Évidemment, si deux états à 1 passent à 0, l'erreur ne sera pas détectée mais la probabilité pour que
cela arrive est très faible.
- Bit de start : lorsque rien ne circule sur la ligne, celle-ci est à l'état haut.
Pour indiquer qu'un mot va être transmis, la ligne passe à bas avant de commencer le transfert.
Cette précaution permet de resynchroniser le récepteur.
- Bits de stop : ces bits signalent la fin de la transmission. Selon le protocole utilisé,
il peut y avoir 1, 1.5, ou 2 bits de stop (ces bits sont toujours à 1).
- Vitesse de transmission : la plupart des cartes série permettent de choisir une vitesse
entre 300 et 9600 bauds (par exemple à 300 bauds, un bit est transmis tout les un trois-centième de seconde).
Les cartes récentes proposent des vitesses jusqu'à 115200 bauds. Ces vitesses ne vous paraissent peut-être
pas énormes mais il faut garder à l'esprit que la liaison série est avant tout pensée pour les liaisons
téléphoniques par modems, dont la bande passante est très limitée.
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;
}
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;
}
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);
ComPort1->SetRTS(false);
}
ou par DTR comme cela.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ComPort1->SetDTR(true);
ComPort1->SetDTR(false);
}
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"; else
Button1->Caption = "État bas sur CTS";
}
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);
}
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);
}
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);
}
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); 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))
{
} if (Errors.Contains(ceOverrun))
{
}
}
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);
}
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();
ComPort1->Connected = true;
TComEvents Ev;
Ev << evRxChar;
ComPort1->WaitForEvent (Ev, 0, 5000); if (Ev.Contains(evRxChar))
{
} else
{
}
}
L'utilisation de WaitForEvent se fait de la manière suivante :
- On efface tous les événements de la propriété Events de TComPort. Ce qui implique qu'aucun thread n'est créé.
- On ouvre le port série.
- On déclare les événements déclencheurs de l'application.
- On appel la méthode WaitForEvent avec comme paramètre, les événements déclancheurs, 0 puis le timeout en ms. Il est possible de remplacer le timeout par "WaitInfinite"
- On test le(s) événement(s) qui ont déclenché(s).
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:
- "AutoApply" à true
- "ComPort" sur le port voulu, ComPort1, ComPort2 etc...
- "ComProperty" sur le paramètre à regler, cpPort pour le port, cpBaudRate pour la vitesse etc...
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 ();
}
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 ;
}
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:
- "ComPort" sur le port voulu, ComPort1 ou ComPort2 etc...
- "LedSignal" une sur IsConn pour l'ouverture du port, l'autre sur IsRx pour la ligne RxD et enfin une sur IsTx pour TxD.
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.
|