Developpez.com - Visual Basic 6
X

Choisissez d'abord la catégorieensuite la rubrique :


Programmer le port série en VB avec le contrôle MSComm

27/11/2003

Par Alexandre "grafikm_fr" Lokchine

A l’heure de l’Internet haut débit, le port série, avec son débit maximum de quelques dizaines de kilo-octets par seconde, peut sembler inintéressant. Pourtant, il a encore de nombreuses applications : le pilotage de machines industrielles et de mécanismes automatiques se fait encore largement au moyen du port série. Enfin, n’oublions pas que même les routeurs ont un connecteur série qui permet de se connecter à la machine pour la piloter.

Ce tutoriel a donc pour objet de montrer comment communiquer via le port série en Visual Basic.

Le Microsoft Comm Control 6.0

Pour gérer le port série, la meilleure façon est d’utiliser le Microsoft Comm Control distribué avec n’importe quelle édition de Visual Basic. Il suffit simplement de le rajouter dans la liste des contrôles de la barre d’outils.

Une fois le contrôle rajouté, son icône apparaît dans la barre des contrôles. Il suffit d’en placer une instance sur la feuille pour pouvoir l’utiliser. Par défaut, ce contrôle s’appellera MSComm1, et on retiendra ce nom pour la suite de l’application :

Les propriétés de base du Microsoft Comm Control

Une fois le contrôle de communication rajouté, il nous faut le paramétrer. Cela se fait avec les propriétés suivantes :

–   CommPort : Cette méthode fixe ou retourne le port COM utilisé par le contrôle. La plupart des ordinateurs n’ayant qu’un ou deux ports COM, cette propriété vaudra donc le plus souvent 1 (port COM1: ) ou 2 (port COM2: ).

MsComm1.CommPort=1 ‘on utilise le port COM1:

–   Settings : Cette méthode fixe les caractéristiques de la connexion, à savoir la vitesse de communication, l’utilisation ou non du bit de parité, le nombre de bits de données et le nombre de bits d’arrêt. Cette information est le plus souvent fournie par le constructeur de l’équipement avec lequel vous souhaitez communiquer. Elle est construite de la manière suivante : "vitesse, parité(Y ou N), bits de données, bits de stop"

MSComm1.Settings = "9600,N,8,1"

Cela signifie que la vitesse de connexion est de 9600 bauds/s, pas de contrôle de parité (Non), il y a 8 bits de données par octet de données (rappelez-vous que les Américains n’en utilisent souvent que 7, parce qu’ils n’ont pas les caractères accentués à gérer), et 1 bit de stop.

–   PortOpen : cette méthode permet d’ouvrir le port si on la positionne à True et le fermer si on le positionne à False :

MSComm1.PortOpen=True 'j’ouvre le port série
MSComm1.PortOpen=False 'je ferme le port série

Il est important de ne pas oublier de fermer le port série ! Pour être sûr, rajoutez le code suivant dans votre formulaire :

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)         
Comm1.PortOpen=False 'fermeture du port
End Sub

–   OutPut : cette méthode permet d’envoyer des données au port. Bien entendu, il faut au préalable configurer et ouvrir le port. La chaîne envoyée doit être terminée par un retour chariot ( Chr$(13)) ou par un retour chariot + retour ligne (vbCrLf) en fonction de la connexion. Souvent, le seul moyen de savoir lequel choisir consiste à essayer les deux à prendre celui qui marche.

MSComm1.OutPut="ATDT 0123456789"

On dit ici au modem de composer le numéro 0123456789.

–   Input : cette méthode permet de recevoir des données sur le port COM. Ici, une explication s’impose : le port série stocke les données arrivant au système dans une mémoire tampon interne qui vaut par défaut 1024 octets. Si la mémoire tampon est saturée et que de nouvelles données arrivent, celles-ci sont perdues. Il est donc impératif de recopier les données dans une chaîne de caractères, par exemple :

Dim tampon$
Tampon$ = Tampon$ & MSComm1.Input

Bien sûr, cela doit être fait de façon répétitive tant que des données arrivent sur le port. En général, les données se terminent par un caractère de terminaison (si-si!), qui nous fera savoir que la transmission est terminée.

Par exemple, on attend ici des données terminées par "OK" suivi de retour à la ligne :

Do
  DoEvents 'indispensable sinon ça marche pas!!!
  Tampon$ = Tampon$ & MSComm1.Input
Loop Until InStr(Tampon$, "OK" & vbCrLf)

–   InBufferSize : cette méthode fixe ou retourne la taille de la mémoire tampon entrée (donc celle qui contient les données arrivant sur le système), elle vaut par défaut 1024 octets :

MSComm1.InBufferSize=2048

Taille_du_tampon=MSComm1.InBufferSize

–   OutBufferSize : cette méthode fixe ou retourne la taille de la mémoire tampon sortie (donc contenant les données envoyées par le système), elle vaut par défaut 512 octets:

MSComm1.OutBufferSize=1024

Taille_du_tampon_entree=MSComm1.OutBufferSize

–   HandShaking : Cette propriété permet de fixer le mode de « poignée de mains », c’est-à-dire la façon dont la communication est établie au niveau matériel. Elle peut prendre les valeurs suivantes :

Numéro Constante chaîne Utilisation
0 comNone Pas de handshaking matériel. Parfois utilisé, mais globalement rare.
1 comXOnXOff Handshaking par contrôle de flux. Sert surtout dans les terminaux
2 comRTS Utilisé le plus souvent sur le réseau téléphonique.
3 comRTSXonXoff Combinaison des deux précédentes

La plupart du temps, la nature du hand-shaking est imposée par le matériel, il faut donc fouiller le manuel de l’équipement ou faire des tests, il n’y a pas de règle universelle…

La communication par événements

Le contrôle de communication serait bien rudimentaire et compliqué d’utilisation s’il n’incluait pas une propriété fondamentale, à savoir la communication événementielle.

Le contrôle Comm dispose en effet d’un événement appelé OnComm, qui se déclenche lorsque des données arrivent sur le port série. Donc, plutôt que de se prendre la tête avec le "Do…Loop" comme tout à l’heure, on place notre code dans l’événement OnComm et on laisse faire le système.

L’événement OnComm sert en fait à plusieurs choses :

  –   A recevoir les données
  –   A repérer les erreurs
  –   A gérer les événements de signalisation arrivant sur la ligne
  –   A repérer la fin de la transmission

La programmation typique d’un événement OnComm se passe donc de la manière suivante :

Private Sub MSComm1_OnComm()

Dim tampon as String

Select Case MSComm1.CommEvent

    'liste des erreurs possibles

    Case comEventBreak      ' On a reçu un signal d’interruption (Break)
    Case comEventCDTO       ' Timeout de la porteuse
    Case comEventCTSTO      ' Timeout du signal CTS (Clear To Send)
    Case comEventDSRTO      ' Timeout du signal de réception
    Case comEventFrame      ' Erreur de trame
    Case comEventOverrun    ' Des données ont été perdues
    Case comEventRxOver     ' Tampon de réception saturé
    Case comEventRxParity   ' Erreur de parité
    Case comEventTxFull     ' Tampon d’envoi saturé
    Case comEventDCB        ' Erreur de réception DCB (jamais vu)

    ' liste des événements possibles qui sont, eux, normaux

    Case comEvCD            ' Changement dans la broche CD (porteuse)
    Case comEvCTS           ' Changement dans broche CTS
    Case comEvDSR           ' Changement dans broche DSR (réception)
    Case comEvRing          ' Changement dans broche RING (sonnerie)

    Case comEvReceive       ' Si on reçoit des données
        tampon=MSComm1.Input
        Call Traitement(tampon) ' Routine de traitement

    Case comEvSend          ' Il y a des caractères à envoyer
    Case comEvEOF           ' On a reçu le caractère EOF

End Select

End Sub

' Cette procedure sert à traiter l’information reçue dans le tampon

Sub Traitement(tampon As String)

' Ici, on affiche le résultat dans un champ de texte
Text1.Text=Text1.text & tampon

End Sub

Oui, ça fait beaucoup de cas d’événements à traiter, et la plupart ne servent quasiment jamais, mais peuvent servir un jour…

Exemple de code (communiquer avec un autre PC via le port COM)

Pour exécuter ce code, il va vous falloir:

  –   Soit 2 PC et un câble null-modem entre les deux.

  –   Soit un PC avec 2 ports COM: (de plus en plus dur à trouver) et un câble null-modem reliant les deux ports COM:

Ensuite, il va falloir créer deux programmes, qu'on va appeler App1 et App2, la première va envoyer des données, l'autre va les recevoir.

Code de l'appli App1

–  Placez un CommControl sur le formulaire
–  Placez une zone de texte et mettez la propriété MultiLine à True.
–  Placez un bouton de commande

–  Mettez le code suivant:

Private Sub Form_Load()
Form1.Caption = "App1"
With MSCOMM1 'configuration du port
.CommPort=1 'On utilise le port COM1:
.Handshaking = 2 'RTS
.RThreshold = 1
.RTSEnable = True 'mieux pour le port COM:
.Settings = "9600,n,8,1"
.SThreshold = 1
.PortOpen = True 'ouverture du port
End With

Command1.Caption = "&Send"
Text1.Text = "Ces données ont été envoyés via le port COM"
End Sub

Private Sub Command1_Click()
MSComm1.Output = Text1.Text
End Sub

Private Sub Form_Unload(Cancel As Integer)
MSComm1.PortOpen = False 'on ferme le port à la fermeture de l'appli
End Sub

Code de l'appli App2

–  Placez un CommControl sur le formulaire.
–  Placez une zone de texte et mettez la propriété MultiLine à True.
Redimensionner-le pour qu'il soit assez grand pour afficher plusieurs lignes de texte.

–  Mettez le code suivant:

Private Sub Form_Load()
Form1.Caption = "App2"
With MSComm1
.CommPort = 2 'on utilise le port COM2: car on utilise 1 PC avec 2 ports COM:
'si vous avez 2 PC, changez en .CommPort=1 !!!

.Handshaking = 2
.RThreshold = 1
.RTSEnable = True
.Settings = "9600,n,8,1"
.SThreshold = 1
.PortOpen = True
End With
Text1.Text = ""
End Sub

Private Sub Form_Unload(Cancel As Integer)
MSComm1.PortOpen = False 'on ferme le port quand l'appli quitte
End Sub

Private Sub MSComm1_OnComm()
Dim InBuff As String

Select Case MSComm1.CommEvent
' On effectue la gestion des erreurs (cf. le modèle ci-dessus)
' Ici, on gère en fait pas grand-chose, mais c'est pour illustrer la démarche ;)


'liste des erreurs possibles
Case comEventBreak 'On a reçu un signal d’interruption (Break)
Case comEventCDTO ' Timeout de la porteuse
Case comEventCTSTO ' Timeout du signal CTS (Clear To Send)
Case comEventDSRTO ' Timeout du signal de réception
Case comEventFrame ' Erreur de trame
Case comEventOverrun ' Des données ont été perdues
Case comEventRxOver ' Tampon de réception saturé
Case comEventRxParity ' Erreur de parité
Case comEventTxFull ' Tampon d’envoi saturé
Case comEventDCB ' Erreur de réception DCB (jamais vu)

'liste des événements possibles qui sont, eux, normaux
Case comEvCD 'Changement dans la broche CD (porteuse)
Case comEvCTS 'Changement dans broche CTS
Case comEvDSR 'Changement dans broche DSR (réception)
Case comEvRing 'Changement dans broche RING (sonnerie)

'Chouette! on a reçu des données :)
Case comEvReceive
      tampon=MSComm1.Input
      Call Traitement(tampon) 'traitement données

Case comEvSend ' il y a des caractères à envoyer

Case comEvEOF 'on a reçu le caractère EOF
End Select
End Sub

Sub Traitement(tampon As String)
'cette procédure sert à traiter l’information reçue dans le tampon
     Text1.SelStart = Len(Text1.Text)
     Text1.SelText = tampon 'ici, on affiche le résultat dans un champ de texte
End Sub
 

Ensuite, exécutez les deux appli (vous aurez besoin de deux instances de VB si vous les exécutez sur le même PC).
Puis, dans App1, cliquez sur Send. Vous verrez alors s'afficher le texte "Ces données ont été envoyés via le port COM" dans la boîte texte de App2. Vous pouvez aussi changer le texte dans App1, puis cliquer sur "Send" et le texte sera envoyé dans App2.

Télécharger le code source de l'exemple (5 ko, ZIP)

Quelques problèmes fréquents et solutions

–   Si vous pilotez un modem, vérifiez que le problème ne part pas en mettant la propriété RTSEnable à True.

–   La plupart du temps, il faut laisser la propriété InputLen à 0 (valeur par défaut)

–   La plupart du temps, il faut laisser la propriété RThreshold à 1 (valeur par défaut)

Voilà, vous savez maintenant tout pour programmer une petite application exploitant le port série. Bon développement…

grafikm_fr

 
Contacter le responsable de la rubrique Visual Basic 6