Le premier site francophone dédié au développement Pocket PC


Gestion du port série pour Pocket PC et Windows CE
 
   



Les ports séries sont l'un des modes de communication qui est souvent utilisé en industrie. Lors de projet, on doit implémenter une couche de communication pour les ports séries et régulièrement le document associé fournit par le constructeur de carte électronique est un exemple en C pour attaquer directement le HardWare de votre matériel. Or si vous disposez d'un OS tel que Windows CE, alors vous vous rendrez rapidement compte que ce type d'accès direct vous est interdit. Vous êtes obligés de passer par un driver.

Cet article vous expliquera l'utilisation des fonctions API qui utilisent les fonctions de vos drivers de base qui vous seront utiles pour programmer une communication via les ports série que se soit pour Pocket PC ou Windows CE en général.


Comment utiliser un port série via les API ?

Pour pouvoir effectuer une communication via un port série, il faut en premier lieu pouvoir l'atteindre par l'intermédiaire de l'OS. Pour effectuer cette manœuvre, on dispose d'API permettant d'obtenir un chemin entre votre application et le port série en passant successivement les couches de l'OS et des drivers associés à la gestion des ports série.

La fonction CreateFile va vous renvoyer une instance sur le chemin d'accès qui vous permettra d'utiliser votre port série. Il vous suffit seulement de lui passer en paramètre le nom du port que vous souhaitez utiliser. Cette fonction va par la suite récupérer dans la base de registre les informations correspondant au port de communication désigné tel que son adresse de base, etc …

Une fois que vous possédez ce chemin d'accès, vous devez passer à l'étape suivant qui est la configuration du port série. Pour ce faire, il faut configurer le registre hardware du port via les fonctions GetCommState & SetCommState.

Ces fonctions vont récupérer dans une structure les informations du registre pour ensuite les remettre modifiées selon vos désirs.

Une fois ces étapes finalisées, vous pouvez commencer à dialoguer. Pour envoyer un caractère sur le port série, vous devez utiliser la fonction WriteFile. Pour Recevoir un caractère sur le port série, vous devez utiliser la fonction ReadFile.

Pour mettre fin à la communication, il vous suffit de libérer le port série en libérant l'instance créée précédemment. Pour cette manœuvre utiliser la fonction CloseHandle.


Explication détaillée de l'utilisation de ces fonctions ci-après.

Comment avoir accès au port série ?

Pour avoir accès au port série, il vous faut créer une instance de type HANDLE qui vous permettra via les drivers d'activer l'utilisation d'un port.

Pour ce faire, vous disposez de cette fonction :

HANDLE CreateFile(
 LPCTSTR lpFileName, // pointer sur le nom du port à utiliser
 DWORD dwDesiredAccess, // mode d'accès (read-write) 
 DWORD dwShareMode, // share mode
 LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
 DWORD dwCreationDisposition, // Condition pour créer l'instance
 DWORD dwFlagsAndAttributes, // file attributes
 HANDLE hTemplateFile // handle to file with attributes to copy
);

Exemple commenté:

// Déclaration de notre instance pour accueillir l'accès au port série
HANDLE hPort; 
         
//Nom du port série auquel on veut accéder 
LPSTR lpszPortName = _T("COM1:");
         
// Les deux points ( : ) sont important ils indiquent à la
//fonction qu'il s'agit du chemin d'une ressource de communication.
//Ce chemin est connu de Windows grâce à la base de registre          de l'OS
//Il n'est donc pas nécessaire de connaître l'adresse de
//base du port série en question

//Open the serial port.
hPort = CreateFile (
 lpszPortName,                  //Pointer to the name of the port
 GENERIC_READ | GENERIC_WRITE,  //accès en lecture ou en écriture
 0,                             //Share mode
 NULL,                          //Pointer to the security attribute
 OPEN_EXISTING,                 //Cela indique que l'instance sera créée
                                //à condition que le port de 
                                //communication demandé existe 
                                //et donc est connu de l'OS
 0,                             //Port attributes
 NULL);                         //Handle to port with 
                                //attribute to copy
//vérification sur la création de l'instance
if ( hPort == INVALID_HANDLE_VALUE ) 
 {
   //insérer votre code d'erreur ici
 }


Comment configurer le port série ?

Pour qu'une communication entre deux appareils puisse exister, il faut qu'ils parlent le même langage. Pour ce faire, la configuration des ports série doit être identique des deux cotés.

Le procédé de configuration est simple et se passe en trois temps.
- Récupérer la structure de configuration du port série
- Mettre à jour cette structure selon vos critères
- Renvoyer la structure vers le port série

Au bout de cette étape les registres de vos ports série sont prêts, vous pouvez communiquer.

La structure du port série :

typedef struct _DCB {       //dcb 
 DWORD DCBlength;           //sizeof(DCB) 
 DWORD BaudRate;            //current baud rate 
 DWORD fBinary: 1;          //binary mode, no EOF check 
 DWORD fParity: 1;          //enable parity checking 
 DWORD fOutxCtsFlow:1;      //CTS output flow control 
 DWORD fOutxDsrFlow:1;      //DSR output flow control 
 DWORD fDtrControl:2;       //DTR flow control type 
 DWORD fDsrSensitivity:1;   // DSR sensitivity 
 DWORD fTXContinueOnXoff:1; // XOFF continues Tx 
 DWORD fOutX: 1;            //XON/XOFF out flow control 
 DWORD fInX: 1;             //XON/XOFF in flow control 
 DWORD fErrorChar: 1;       //enable error replacement 
 DWORD fNull: 1;            //enable null stripping 
 DWORD fRtsControl:2;       //RTS flow control 
 DWORD fAbortOnError:1;     //abort reads/writes on error 
 DWORD fDummy2:17;          //reserved 
 WORD wReserved;            //not currently used 
 WORD XonLim;               //transmit XON threshold 
 WORD XoffLim;              //transmit XOFF threshold 
 BYTE ByteSize;             //number of bits/byte, 4-8 
 BYTE Parity;               //0-4=no,odd,even,mark,space 
 BYTE StopBits;             //0,1,2 = 1, 1.5, 2 
 char XonChar;              //Tx and Rx XON character 
 char XoffChar;             //Tx and Rx XOFF character 
 char ErrorChar;            //error replacement character 
 char EofChar;              //end of input character 
 char EvtChar;              //received event character 
 WORD wReserved1;           //reserved; do not use 
} DCB; 

La fonction de récupération :

BOOL GetCommState(
 HANDLE hFile, //instance d'accès de votre port série
 LPDCB lpDCB   //Pointeur sur votre structure de configuration
);

La fonction de renvoie :

BOOL SetCommState(
 HANDLE hFile, // instance d'accès de votre port série
 LPDCB lpDCB   // Pointeur sur votre structure de configuration
);
Exemple commenté :

Vous n'êtes pas obligé de mettre à jour entièrement votre structure, car elle représente une copie du registre du port série et donc ce que vous ne remplirez pas restera à son ancienne valeur ou celle par défaut.

DCB PortDCB;
//Récupération des informations enregistées du port série dans votre structure.
GetCommState (hPort, // instance d'accès de votre port série
 &PortDCB);         // Structure de configuration
// mise à jour de la structure
PortDCB.DCBlength = sizeof (DCB); 
PortDCB.BaudRate = 9600; 
PortDCB.fBinary = TRUE; 
PortDCB.fParity = TRUE; 
PortDCB.fOutxCtsFlow = FALSE; 
PortDCB.fOutxDsrFlow = FALSE; 
PortDCB.fDtrControl = DTR_CONTROL_ENABLE; 
PortDCB.fDsrSensitivity = FALSE; 
PortDCB.fTXContinueOnXoff = TRUE; 
PortDCB.fOutX = FALSE; 
PortDCB.fInX = FALSE; 
PortDCB.fErrorChar = FALSE; 
PortDCB.fNull = FALSE; 
PortDCB.fRtsControl = RTS_CONTROL_ENABLE; 
PortDCB.fAbortOnError = FALSE; 
PortDCB.ByteSize = 8; 
PortDCB.Parity = NOPARITY; 
PortDCB.StopBits = ONESTOPBIT; 
//Renvoie des nouvelles informations dans le registre de votre port série
if (!SetCommState (hPort, &PortDCB))
 {
   //Mettre ici votre code d'erreur
 }

Comment écrire sur le port série ?

Pour ce faire, utiliser cette fonction :

BOOL WriteFile(
 HANDLE hFile,                   //Instance de votre accès au port série
 LPCVOID lpBuffer,               //Pointeur sur la donnée à écrire
 DWORD nNumberOfBytesToWrite,    //Nombre de bytes à écrire
 LPDWORD lpNumberOfBytesWritten, //pointeur to number of bytes written
 LPOVERLAPPED lpOverlapped       //Doit être NULL pour windows CE
);

 

Exemple commenté :

DWORD dwNumBytesWritten;
BYTE Byte = 'a';
if (!WriteFile (hPort, // Instance d'accès de votre port série
 &Byte,                //Pointeur sur la donnée à envoyer
 1,                    //Nombre de byte à envoyer
 &dwNumBytesWritten,   //Pointer sur la variable contenant le nombre 
                       //byte écrit dans le buffer 
 NULL))                //Doit être NULL pour Windows CE
{
  //code d'erreur
}

Comment lire sur le port série ?

Le port série peut recevoir différents types d'événements comme l'arrivée d'une donnée, buffer d'envoie vide ou différents signaux (CTS, DSR) ce qui permet une large manipulation de ceux-ci

Ici seul l'arrivée d'une donnée nous intéresse.

Exemple commenté :

BYTE Byte;
DWORD dwCommStatus, // variable de stockage pour les évènements
DWORD dwBytesTransferred;
         
//Cette fonction définit les évènements pour lesquels
//ont va réagir par rapport à notre instance
SetCommMask (hPort,
 EV_RXCHAR ); //ici EV_RXCHAR indique que l'on va détecter la réception          
              //de données (cette entrée est de type DWORD)
//Cette fonction est bloquante, elle va attendre
//des événements définit par le mask et
//Elle stockera le type d'événement qui l'aura réveillée dans une variable.
WaitCommEvent (hPort, //instance d'accès du port série
 &dwCommStatus,       //Pointeur sur la variable de stockage pour les évènements
                      //Cette entrée est de type LPDWORD
 0);                  //pointeur sur la structure d'overlapped.
                      //Ici il n'y en a pas.
                      //cette entrée est de type LPOVERLAPPED

//Cette fonction permet la lecture du buffer d'entrée du port série
ReadFile (hPort,      //Instance sur l'accès du port série
 &Byte,               //Conteneur pour récupérer le byte lu
 1,                   //Nombre de byte à lire
 &dwBytesTransferred, //Pointer sur le nombre de byte lu, sert à
                      //la gestion propre de la fonction read.
 0);                  //Doit être NULL pour Windows CE

// Permet l'affichage de votre conteneur
Printf("%c",Byte);

Comment fermer l'accès au port série ?

Pour ce faire, utilisez cette fonction :

BOOL CloseHandle(
 HANDLE hObject //Instance d'accès du port série
);
 
       
   
 
   
Copyright 2001-2004 - Tous droits réservés
 
   

iPAQ est un produit de COMPAQ.
Visual Tools est un produit de Microsoft Corporation.
Toutes les autres marques et produits présents dans ces pages sont la propriété exclusive de leurs sociétés respectives.