COMx: Ouvrir et gérer un port série
publication: 8 décembre 2024 / mis à jour 12 décembre 2024
Introduction
La carte Z79Forth est une carte qui se gère via un port USB-série. Cette carte héberge une version 79-Standard du langage Forth. La gestion de cette carte est réalisée au travers d'un terminal virtuel (Tera Term 5). Ici, on va voir comment gérer le port série depuis l'API Windows pour communiquer entre eForth Windows et les appareils connectés à ce port série.
Pour savoir si un port série est actif, cliquer sur le champ de recherche Windows et tapez Gestionnaire de périphériques.
Ouvrez le gestionnaire de périphériques et recherchez Ports (COM):
Ici, le port série COM5 est disponible.
ATTENTION: s'il n'y a aucun appareil connecté en liaison série, le gestionnaire de périphériques n'indiquera aucun port série disponible.
Pour la suite, on suppose le programme eForth paramétré pour accéder à notre port série COM5. A charge pour vous d'adapter le programme en fonction du port série disponible quand vous connectez un appareil.
Le port série
Le port série est apparu sur les premiers ordinateurs comme le premier interface simple pour communiquer avec des accessoires, dont des imprimantes, modems, etc...
Le câblage était souvent un cauchemard, entre fiches DB9, DB25, fils croisés, signaux de handshake pris en compte ou ignorés. Avec l'apparition des ports USB, ces soucis ont disparu.
Aujourd'hui, de petites cartes d'interface convertissent les signaux USB en signaux compatibles RS322. De son coté, Windows permet de paramétrer la communication. C'est ce paramétrage que nous allons aborder.
Ouverture du port série
Le mot CreateFileA
permet d'ouvrir un port série. Même si dans l'énoncé de ce mot on retrouve File,
Windows considère les ports série comme ressources au même titre que les vrais fichiers les accès réseau, etc...
Le mot CreateFile
est déjà défini dans le vocabulaire windows
. Utilisation:
only forth also windows also structures $10000000 constant GENERIC_ALL \ All possible access rights $20000000 constant GENERIC_EXECUTE \ Execute access $40000000 constant GENERIC_WRITE \ Write access $80000000 constant GENERIC_READ \ Read access \ parameters used by CreateFileA z" COM5" value CF_lpFileName GENERIC_READ GENERIC_WRITE or value CF_dwDesiredAccess 0 value CF_dwShareMode NULL value CF_lpSecurityAttributes OPEN_EXISTING value CF_dwCreationDisposition 0 value CF_dwFlagsAndAttributes NULL value CF_hTemplateFile : .error ( -- ) getLastError dup ." Error: " . space case 2 of ." port indisponible " endof 5 of ." acces refuse " endof endcase ; -1 constant INVALID_HANDLE_VALUE 0 value hSerial \ create handle for serial port : create-serial ( -- hSerial ) CF_lpFileName CF_dwDesiredAccess CF_dwShareMode CF_lpSecurityAttributes CF_dwCreationDisposition CF_dwFlagsAndAttributes CF_hTemplateFile CreateFileA dup INVALID_HANDLE_VALUE = if .error then ;
Chaque paramètre utilisé par CreateFileA
est défini dans une valeur, exemple:
z" COM5" value CF_lpFileName
Si vous voulez gérer un autre port série, il suffit d'ajuster ce paramètre.
Toute la création du port série est définie dans le mot create-serial
. L'exécution de ce
mot empile un handle qui est stocké dans la valeur hSerial
.
Ce handle hSerial
devient notre seul point d'accès à tous les autres mots de gestion du port série.
Récupération des paramètres du port série
Pour gérer tous les paramètres du port série, il est nécessaire de définir une structure DCB
:
struct DCB i32 field ->DCBlength i32 field ->BaudRate i32 field ->fBinary i32 field ->fParity i32 field ->fOutxCtsFlow i32 field ->fOutxDsrFlow i32 field ->fDtrControl i32 field ->fDsrSensitivity i32 field ->fTXContinueOnXoff i32 field ->fOutX i32 field ->fInX i32 field ->fErrorChar i32 field ->fNull i32 field ->fRtsControl i32 field ->fAbortOnError i32 field ->fDummy2 i16 field ->wReserved i16 field ->XonLim i16 field ->XoffLim i8 field ->ByteSize i8 field ->Parity i8 field ->StopBits i8 field ->XonChar i8 field ->XoffChar i8 field ->ErrorChar i8 field ->EofChar i8 field ->EvtChar i16 field ->wReserved1
Création du mot dcbSerialParams
utilisant cette structure:
\ Sets the control parameter for a serial communication device \ struct DCB \ transfered in Kernel32-definitions.fs \ DCB structure for COM port create dcbSerialParams DCB allot
Le fichier Kernel32-definitions.fs est disponible ici:
eForth-Windows/extensions/
Pour remplir dcbSerialParams
, on définit le mot get-serial-params
:
\ store serial parameters in DCB structure : get-serial-params ( hSerial -- ) dcbSerialParams GetCommState 0 = if abort" Error: GetCommState" then ;
Ce mot utilise GetCommState
, dont voici la définition:
\ Retrieves the current control settings for a specified communications device z" GetCommState" 2 Kernel32 GetCommState ( hSerial lpDCB -- fl )
Paramètres:
- hSerial handle du port série ouvert
- lpDCB structure à remplir
GetCommState
remplit la structure dcbSerialParams
avec les paramètres du port
série ouvert précédemment par create-serial
.
Modification des paramètres du port série
Pour valider les nouveaux paramètres du port série, on utilise le mot SetCommState
dont voici la définition:
\ configures a communications device according to the specifications in a DCB z" SetCommState" 2 Kernel32 SetCommState ( hSerial lpDCB -- fl )
Voici comment le mot SetCommState
est utilisé dans set-serial-params
:
2 constant EVENPARITY 3 constant MARKPARITY 0 constant NOPARITY 1 constant ODDPARITY 3 constant SPACEPARITY 0 constant ONESTOPBIT \ 1 stop bit 1 constant ONE5STOPBITS \ 1.5 stop bits 2 constant TWOSTOPBITS \ 2 stop bits \ set speedn byte size, parity and stop bit : set-speed-8N1 ( dcbStruct -- ) >r 115200 r@ !field ->BaudRate 8 r@ !field ->ByteSize NOPARITY r@ !field ->Parity ONESTOPBIT r> !field ->StopBits ; \ set serial port with DCB structure : set-serial-params ( hSerial -- ) dcbSerialParams SetCommState 0 = if abort" Error: SetCommState" then ;
Initialisation du port série
L'initialisation du port série se déroule en plusieurs étapes:
- récupération du handle rattaché au port COM, ici le port COM5
- récupération des paramètres courants du port ouvert
- modification des paramètres de vitesse, parité...
- affectation des paramètres modifiés au pour série ouvert
\ initialise serial port : init-serial create-serial to hSerial hSerial get-serial-params dcbSerialParams set-speed-8N1 hSerial set-serial-params ; \ close serial port : close-serial ( -- ) hSerial CloseHandle 0 = if abort" Error: CloseHandle" then ;
Le code FORTH complet en lien avec cet article est disponible ici:
GITHUB: eForth-Windows /serial/
Transmission et réception via le port série
La transmission via le port série utilise le mot WriteFile
:
variable BytesWritten : to-serial { addr len -- } hSerial addr len BytesWritten NULL WriteFile 0= if ." Error : WriteFile " .error then ;
Après exécution de to-serial
, le nombre d'octets transmis est stocké dans la variable
BytesWritten
. Pour transmettre une chaîne de commande, il faut compléter la chaîne de caracères
qui correspond à l'équivalent de CR:
create CRLF $0D c, $0A c, : CRLF-to-serial ( -- ) CRLF 1 to-serial ; : str-to-serial ( addr len -- ) to-serial CRLF-to-serial ;
Dans CRLF-to-serial
, on ne transmet que le code $0D. Si c'est nécessaire, on peut
ajuster la définition:
CRLF 1+ 1 to-serial
pour ne transmettre que $0ACRLF 2 to-serial
pour ne transmettre que $0D $0A
Pour recevoir des données depuis le port série, on utilise le mot ReadFile
:
variable BytesRead
256 constant bufferSize
create BUFFER
bufferSize allot
: from-serial ( -- )
BUFFER bufferSize erase
hSerial BUFFER bufferSize BytesRead NULL ReadFile 0= if
." Error : ReadFile " .error
then
;
Le tampon de réception a été limité à 256 octets avec la constante bufferSize
. Si
nécessaire, on peut facilement augmenter la taille du tampon.
L'exécution du mot from-serial
lit les données récupérées par le port série et les enregistre dans
BUFFER
. La variable BytesRead
enregistre le nombre de caractères reçus. Pour afficher
la chaîne de caractères reçus, voici le mot .buffer
:
: .buffer ( -- )
buffer BytesRead @ type
;
Le test de transmission est effectué entre un PC et une carte Z79Forth. La carte Z79Forth est connectée sur un port USB et reconnue par le PC sur le port COM5.
Voici le test du port série entre le PC et la carte Z79Forth:
init-serial
s" hex 3f 2f + . " str-to-serial
from-serial
.buffer \ display: hex 3f 2f + . 6E ok
Le code Forth hex 3f 2f + .
a été transmis à la carte Z79Forth. La chaîne
affichée par .buffer
correspond au code Forth exécuté par la carte Z79Forth.
En conclusion, le code Forth gérant cette transmission série peut certainement être amélioré. En l'état, il permet déjà l'utilisation d'accessoires, comme un transmetteur LoRa.
Legal: site web personnel sans commerce / personal site without seling