M.P.I., travaux pratiques, des astuces pour piloter avec Delphi des mesures réalisées avec les cartes Candibus (Windows 98) et Sysam PCI Fastlab (Windows 98 et XP)

Page modifiée le13 / 2 / 2006
Contenu : Librairie FastLab pour Delphi. Commande d'interfaces Candibus par une librairie ou un composant sous Delphi, commande vocale, IBM Voice type control, fonction Port en Delphi 1, Absolute, langage d'assembleur en Delphi 3 et 4, temporisation, Unit Candibus et un composant pour piloter les cartes Candibus.
Le cours de MPI commence à la page 8 de ce chapitre.

0 Sommaire

  1. Librairie FastLab pour Delphi (rangée dans le chapitre logiciels)
  2. Librairie Delphi de commande de carte d'acquisition Candibus (encore quelques temps, car un composant vient d'être créé
  3. Commande vocale
  4. Commande d'interfaces
  5. Delphi 1, fonction Port
  6. Delphi 3 et 4, langage d'Assembleur
  7. Code assembleur
  8. Temporisation en Delphi 3 et 4
  9. Composant PhyJiC, pilotant les cartes d'acquisition Candibus

1 Librairie Delphi de commande d'interface (nommée pour l'instant Candibus) compatible Windows 98, mais pas XP

Note importante : Cette librairie comporte un bogue (bug) qui empêche l'emploi du copier coller vers Excel. Ce bogue peut être contourné en plaçant un composant DDE sur votre Form, mais il vaut mieux  télé charger le composant Delphi que nous vous proposons. Rédigée il y a quelques années, elle se révèle incompatible avec Windows XP.


Nous avons rédigé une librairie Delphi proposant des fonctions additionnelles à Delphi 3 ou 4 : commande de carte d'acquisition Candibus, entrées analogiques, entrées et sorties logiques, FFT, FFT avec fenêtre de hamming, FFT inverse, transfert des mesures, ou des spectres de Fourier dans Excel, accès à un site Internet, envoi d'un Mail, lancement d'un fichier d'aide .Hlp.

Grâce à cette librairie, de bons élèves de seconde sont capables de réaliser en moins d'une demi heure un programme qui lance une acquisition paramétrable, trace sa représentation graphique, trace le spectre de Fourier, transfère les données dynamiquement dans Excel, et envoie un Mail de félicitations à l'auteur du logiciel, ou lance la consultation de son site Internet.
Une fois compilé, ce programme sur mesure devient totalement autonome, et n'a pas à rougir de la comparaison avec un logiciel professionnel. Pas mal Delphi !

Le pilotage de carte d'acquisition est programmé essentiellement en langage d'Assembleur. Si vous aviez un problème sur une de vos machines, veuillez me contacter, car le pilotage de l'horloge (Timer 2) du PC que j'ai rédigé est incompatible avec certains BIOS (datant de l'âge des cavernes, mais on ne sait jamais ! ) et pourrait donner une base de temps fausse.

Si vous souhaitez que cette Unit dédiée à Candibus soit adaptée à une autre carte d'acquisition, veuillez me faire parvenir une documentation complète sur celle ci. Si la carte n'est pas trop exotique (nous n'allons tout de même pas nous fatiguer à programmer des cartes datant de Mathusalem, ou diffusées au compte gouttes, ou nécessitant l'apprentissage d'un langage de programmation spécial ... quoique si cela en vaut la peine ...). Voici mon adresse : J-M Jussiaux, 5, rue Monge, 25300 Pontarlier. Mon Mail figure dans la "Home Page" et dans le chapitre des bonnes adresses de ce site.

Mode d'emploi de la librairie Candibus.dcu


Télé chargez cette librairie, enregistrez la sur votre disque dur et décompressez la par un double clic. Choisissez le dossier où seront rangés les deux fichiers décompressés, Candibus.dcu et Candibus.dfm. Copiez ces deux fichiers dans Delphi4 \ Lib, ou mieux Delphi4 \ Lib \ Personnel, en créant dans Lib, un sous dossier Personnel, afin de ne pas mélanger vos propres librairies et celles de Borland Inprise Corel. Vous devrez copier ces deux fichiers sur tous les ordinateurs sur lesquels tourne Delphi, ce qui prend quelques secondes. Delphi retrouve tout seul cette librairie personnelle, mais parfois, s'il était en fonctionnement avant la création de la nouvelle librairie, il faut le relancer pour qu'il la recherche.
Ceci marche aussi pour Delphi 3.
Delphi 5 ne semble pas retrouver un éventuel sous dossier Lib \ Personnel (peut être les concepteurs ont ils cherché à gagner du temps de chargement) ; rangez donc les deux fichiers directement dans Lib.
Il me semble que le comportement de Delphi est variable car il exige parfois Candibus.dfm, parfois pas. S'il vous le demande, ignorez le fichier Candibus.pas, non fourni.
Si vous avez perdu l'adresse de Delphi sur votre disque dur, faites un clic droit sur l'icône Delphi sur le bureau et dans propriétés, demandez raccourci.

L' emploi de cette librairie est ensuite d'une grande simplicité :

Dans votre Unit, ajoutez dans les clauses Uses, Candibus, de préférence après Implementation.

Chaque fois que vous voudrez employer une fonction de Candibus, il vous suffira d'entrer Candibus., d'attendre une fraction de seconde, et Delphi vous affichera la liste de tout ce qui est disponible dans la bibliothèque supplémentaire Candibus. Il vous suffira de choisir et de valider. S'il s'agit d'une fonction, ou d'une procédure, ouvrez ensuite une parenthèse, et Delphi vous demandera les valeurs des variables attendues, en vous précisant leur type. A la compilation, ces procédures seront automatiquement incluses dans votre exécutable. Merveilleux !
Nous n'avons pas rédigé pour l'instant de fichier d'aide en ligne directement associée à cette librairie, appelable par F1 ; cela nous a paru assez hermétique. C'est pourquoi, nous vous recommandons de copier le texte suivant, et de l'imprimer.

Librairie Delphi supplémentaire, Candibus, liste des variables, des fonctions et procédures disponibles :
 

Haut de cette page

Note importante :


Lorsqu'une acquisition est en cours, pour éviter une intervention incongrue du système d'exploitation, les interruptions du processeur sont invalidées. Cela signifie que l'acquisition est déclenchée de manière bien régulière par l'une des horloges de votre PC (pas de trou intempestif dans les mesures parce que WinTruc a décidé de faire tourner inutilement le disque dur ou autre fantaisie). Par contre pendant ce temps, clavier, souris ... sont neutralisés. Tant que vous êtes en mode débogage sous Delphi, vous pouvez cependant reprendre le contrôle de la machine. Mais pas lorsque l'exécutable tourne de façon indépendante, donc veillez à interdire une acquisition trop longue, par un test.

Liste des variables de l'Unit Candibus :


avertissement : String ; Si vous commettez une erreur (demande de fréquence d'acquisition trop élevée, négative ...) la librairie Candibus choisit une valeur mieux appropriée et fait la mesure. Seule la lecture de la variable avertissement vous permet de savoir que quelque chose d'anormal s'est passé. Nous avons préféré cette technique, à celle qui aurait consisté à afficher systématiquement une boîte de dialogue, interrompant par la même le déroulement du programme. Il vous revient d'afficher avertissement, dans un StatusBar par exemple. C'est une façon très primitive de transmettre les exceptions. Delphi permet dans ce domaine des choses beaucoup plus élaborées, mais plus difficiles.

frequenceVraie : Real ; Lorque vous choisissez une fréquence (raisonnable), la valeur exacte demandée n'est pas toujours possible car le timer doit faire un nombre entier de 'tours' avant de déclencher une nouvelle mesure ; la librairie Candibus choisit la valeur la plus proche possible et écrit cette valeur réellement employée dans la variable frequenceVraie, que vous pouvez consulter.

delaiMesureTensionMoyenne : Real ; Même chose lorsqu'on mesure une tension moyenne sur une certaine durée.

tensionVoie1, tensionVoie2 : Real ; Valeurs de retours des mesures de tensions moyennes sur les deux voies.

mesure1 : TListeCandibus ; liste des tensions (entiers convertis en nombres réels) mesurées sur voie 1,
mesure2 : TListeCandibus ;  réels mesurés sur voie 2,

module : TListeCandibus ; liste des modules obtenus par FFT,
partieReelle : TListeCandibus ; liste des parties réelles obtenues par FFT,
partieImaginaire : TListeCandibus ; liste des parties imaginaires obtenues par FFT.

Liste des fonctions logiques :


Procedure Configurer(valeur : Byte) : Configure les 3 ports en entrée ou sortie (voir la notice de la carte Candibus, pour les valeurs à inscrire)

Procedure EcrireDansA(valeur : Byte) : pour écrire un octet sur le port A,
Procedure EcrireDansB(valeur : Byte),
Procedure EcrireDansC(valeur : Byte),

Function LireA : Byte : pour lire un octet sur le port A,
Function LireB : Byte,
Function LireC : Byte.
 

Haut de cette page

Liste des fonctions d'acquisition par conversion analogique -> numérique :


Procedure AcquerirMoyenne(nombrePoints : Cardinal ; frequence : Real) : Effectue nombrePoints mesures, et en donne la valeur moyenne dans tensionVoie1, et tensionVoie2.

Procedure Acquerir(nombrePoints : Word ; frequence : Real) : Effectue nombrePoints mesures, et donne les résultats dans les tableaux mesure1, et mesure2.

Procedure FFT(numeroCourbeOuSigne, nombreDePoints : Integer) : Si numeroCourbeOuSigne vaut 1, effectue la FFT sur nombreDePoints du tableau mesure1 ; s'il vaut 2 c'est mesure2 qui est transformé. nombreDePoints doit être inférieur ou égal à 1024. Il ne doit pas impérativement être une puissance de 2, mais en ce cas, le calcul est plus lent. Les résultats de la FFT sont rangés dans les tableaux module, partieReelle, partieImaginaire.
Si numeroCourbeOuSigne vaut -1, c'est la FFT réciproque qui est calculée, mais ici uniquement sur un nombre de points qui est une puissance de deux. Les nombres sont pris dans les tableaux partieReelle, partieImaginaire et les résultats sont rangés comme dans le cas précédent. Nous avons choisi cette façon de faire pour ne pas perturber les élèves avec la transformée inverse.

Procedure FFTHamming(numeroCourbeOuSigne, nombreDePoints : Integer) : Calcule un spectre de Fourier, avec une fenêtre de Hamming, si numeroCourbeOuSigne vaut 1 ou 2 (mesure1 ou mesure2, correspondant aux voies 1 et 2). Si numeroCourbeOuSigne vaut -1, une FFT inverse est calculée, sans fenêtrage.

Procedure LancerEchantNumVoie1 : Pour effectuer une seule mesure à la fois, on lance l'acquisition
Procedure LancerEchantNumVoie2

Function LireVoie1 : Real : après échantillonnage et numérisation, on lit une valeur.
Function LireVoie2 : Real

Procedure Copier(nombrePoints : Word ; nomDeLaListe : String) : Copie dans le presse-papiers le nombre de points indiqué par nombrePoints. Vous devez indiquer par une chaîne (String) les points qui vous intéressent, 'mesure1', 'mesure2', 'module', 'partieReelle', 'partieImaginaire'. Exemple Copier(128, 'module') envoie 128 fréquences et 128 points du module de la FFT dans le presse-papiers.
Une fois copiés, les points peuvent être transférés dans Excel.

Liste des autres fonctions


qui n'ont rien à voir avec la carte Candibus, mais qui sont susceptibles d'améliorer grandement la présentation d'un logiciel :
Procedure LancerAideEnLigne(nomDuFichierDaide : String) : Le fichier d'aide peut être rangé au même niveau que l'exécutable (dans le même dossier), ou dans un sous dossier nommé Aide, ou Aides, ou Help. Si le fichier d'aide se nomme aideMesure.hlp, faire : LancerAideEnLigne(aideMesure) ; .

Function AdresseDuDossierPrincipal : String : Retourne l'adresse du dossier où se trouve l'exécutable.

Procedure AccederAUnSiteInternet(adresseSite : String) : A associer au menu déroulant Aide.
Procedure EcrireAuxAuteurs (adresseMail : String).

Télé charger candibus.dcu ?
 

Haut de cette page
 

2 Commande vocale


Attention ! Il ne s'agit pas d'une simple commande par un bruit suffisamment intense, mais bien d'une réelle commande vocale, avec reconnaissance des mots prononcés.

Pour cela, il vous faudra acquérir le logiciel de chez I B M, nommé Voice Type Control.
Il est disponible chez votre marchand de journaux, fourni avec la revue Presqu' offert, n° 25 de Mai / Juin 1999. Les anciens numéros peuvent être commandés sans problèmes. Il vous en coûtera 38 F par poste installé.
Installez le logiciel, comme indiqué dans la revue, et placez son icône sur le bureau. Voice Type Control connaît environ 35 000 mots de la langue française, il peut en apprendre d'autres.

S'il est lancé conjointement avec un autre programme, il est capable de lancer, à la voix, dans ce dernier toutes les actions associées aux en-têtes des menus déroulants (MainMenu) et aux Caption des Buttons (Delphi 4).
Donc, en résumé, vous rédigez un petit programme en Delphi, vous associez ses procédures à son menu déroulant, ou à des boutons.
Vous pouvez maintenant commander le déclenchement de ces procédures, en prononçant dans un microphone le nom correspondant dans l'en-tête du menu, ou la propriété Caption du composant Button.

Les menus déroulants 'Jour' et 'Noir' marchent bien. 'Nuit' est mal reconnu, sans apprentissage, dans Voice Type Control. Nous autres Francs Comtois, habitant une petite ville près de la frontière suisse, avons de plus, paraît-il, un accent particulier, qui semble indisposer Voice Type Control. Préférez des microphones pas trop sophistiqués, du genre micro casque. Un microphone de haute fidélité, placé près de la bouche, sur le côté, conduit à une mauvaise reconnaissance. Peut-être à cause de sa bonne sensibilité dans les graves, qui provoque un renforcement des plosives.

La chaîne est la suivante :

Opérateur -> Voix -> Propagation des sons dans l'air -> Transducteur (microphone) -> Tension électrique variable -> Conversion Analogique Numérique (par la carte son) -> Suite de nombres -> Reconnaissance des mots prononcés (par le logiciel Voice Type Control) -> Action (informatique) sur le Button ou le Menu correspondant -> Déclenchement de la procédure associée (dans notre logiciel personnel) -> Action sur les sorties logiques -> Allumage ou extinction des diodes électro luminescentes.

Les causes de pannes sont, c'est facile à comprendre, nombreuses.

Vérifiez :

Notez que la commande ne fonctionne que si votre logiciel est actif, bandeau supérieur bleu foncé. Pour cela cliquez sur sa fenêtre.
Pour vérifier la partie microphone, carte son, lancez le logiciel d'enregistrement fourni avec celle-ci, nommé Créative Wave Studio pour la carte Sound Blaster. Dans la barre d'outils de celui-ci, vous pouvez lancer Créative Mixer, qui permet les paramétrages et les tests. Vous pouvez aussi lancer directement Créative Mixer.

Nous avons constaté à deux reprises, que des microphones de type électret, achetés en tant que composants discrets, ou livrés dans des micro casques (bon marché), tombaient systématiquement en panne après un ou deux ans, dans notre laboratoire. Nous n'en avons pas trouvé la raison.

Créative Mixer est un peu 'piégeant'. Les options d'enregistrement (les seules employées ici) correspondent à des symboles (clavier MIDI, lecteur CD, entrée ligne, entrée microphone) repérés par des points rouges. Pour les obtenir, vous devez (si nécessaire) passer dans le mode Options d'Enregistrement.
Si vous êtes dans le mode Options de Mixage, les points sont verts, sauf un, sur le petit bouton à gauche, qui permet justement de passer dans le mode Options d'Enregistrement.
Sous le symbole du microphone, une petite case à cocher comporte un point rouge lorsque le microphone est en service.

Le bon fonctionnement peut alors être constaté par un affichage graphique. Celui-ci comporte en bas, à droite, une toute petite icône, avec un carré bleu lorsque l'affichage n'est pas en service, et deux carrés, bleu et rouge lorsqu'il fonctionne.
A gauche de cette icône, vous en voyez une autre, bleue, avec des flêches ; elle permet de cacher les potentiomètres linéaires, ou de les faire apparaître. Dans ce dernier cas, elle n'est pas visible ! Mais elle fonctionne !
Lorsque le pointeur de la souris passe sur le graphique, il prend la forme d'une main. Un simple clic permet de modifier la présentation de l'affichage.

Dans certaines versions plus récentes, le BarGraph ne fonctionne qu'à la lecture. L'enregistrement a lieu cependant. A vérifier.

De même, tout à gauche des potentiomètres linéaires, dans la colonne de boutons de la barre d'outils, l'un permet de cacher l'affichage graphique ou de le faire apparaître.

Vous pouvez accéder à différents paramètres, en effectuant un clic droit dans la barre de titres. Vous pourrez ainsi afficher la barre d'outils, rendre cette fenêtre toujours visible, augmenter le gain jusqu'à 4 fois...

Le central vocal IBM comporte un petit indicateur du niveau sonore reçu.
Un bouton de la barre d'outils permet d'accéder aux options. Nous vous conseillons :

Options vocales | Test des connexions audio, permet d'enregistrer et d'écouter le signal. Ne placez pas le microphone trop en face de votre bouche, car il récupèrera du souffle.

Conclusion :
Montage éprouvant pour le professeur, mais plaisant beaucoup aux élèves.

Difficile et au-dessus du niveau normal de M.P.I.
 

Haut de cette page

3 Commande d'interfaces


Delphi 1, disponible chez votre marchand de journaux, pour 69 F, avec la revue Presqu' offert, possède la fonction nommée Port. Elle convient à nos besoins, mais Delphi 1 est une version 16 bits, ancienne, de Delphi. Les programmes que vous réaliserez avec, posséderont le petit côté "look rétro" qui peut plaire.
Delphi 1 est livré gratuitement, avec les versions ultérieures de Delphi, car il permet de compiler des exécutables pour Windows 3.1. Les autres versions fournissent des exécutables compatibles seulement avec Windows 95 et plus.
 

Haut de cette page

4 Delphi 1, fonction Port


Pour écrire valeur à adresse, vous ferez :
Port[adresse] := valeur ;
Pour lire,
valeurLue := Port[adresse] ;
 

Haut de cette page

5 Delphi 3 et 4, Absolute ou langage d'Assembleur

Voir aussi la librairie Candibus pour Delphi, en haut de cette page


Comme nous l'avons indiqué plus haut, la fonction Port n'existe plus en Delphi 2 à 5. Les concepteurs évoquent une
incompatibilité 16, 32 bits. Que faire ? Trois solutions se présentent :

  1. Employer une dll, mais cela est lourd à gérer, car rien ne marche, si la dll n'est pas installée au bon endroit.
  2. Une deuxième méthode, utilisant le mot clé Absolute, exposée plus loin, a été trouvée dans l'aide en ligne de Delphi. Elle semble simple, mais je ne suis pas parvenu à la faire fonctionner.
  3. Il est aussi possible d'utiliser le langage d'assembleur. Mais avec des élèves, on peut avoir peur. En fait il vaut mieux réaliser des fonctions et procédures employant l'Assembleur et les ranger dans Delphi, comme la librairie Candibus proposée plus haut.

Méthode utilisant le mot clé Absolute


Ceci a été trouvé dans l'aide en ligne de Delphi 4.

Pour déclarer une variable située à une adresse mémoire spécifique, placez le mot absolute après le nom de type en le faisant suivre d'une adresse. Par exemple :

var nombreEnSortie : Byte absolute adressePortA ;

Où adressePortA a été déclarée comme constante par :

Const
adressePortA : Word = $28C

Cette technique ne s'utilise que pour la programmation au niveau du matériel, par exemple pour écrire des pilotes de périphérique.
Pour créer une nouvelle variable placée à la même adresse qu'une variable existante, placez le nom de la variable existante (au lieu d'une adresse) après le mot absolute. Par exemple :

var

  Str: string[32];
  StrLen: Byte absolute Str;

Spécifie que la variable StrLen doit commencer à la même adresse que Str. Comme le premier octet d'une chaîne courte contient la longueur de la chaîne, la valeur de StrLen est la longueur de Str.
Il n'est pas possible d'initialiser une variable dans une déclaration absolute.

Voici du code pour écrire et lire dans le port A :

Procedure EcrireDansA(valeur : Byte) ;
var nombreDansA: Byte absolute adressePortA;
begin
avertissement := '' ;
nombreDansA := valeur ;
end;

Function LireA : Byte ; Pascal ;  //Word
var nombreDansA: Byte absolute adressePortA;
Begin
avertissement := '' ;
result := nombreDansA ;
End ;
 

Haut de cette page

Méthode Utilisant l'Assembleur


puceAttention : Certaines fonctions Assembleur (in, out, cli, sti...) sont incompatibles avec Windows XP.
Si cette technique vous intéresse, il vous est conseillé d'acquérir un ouvrage sur l'Assembleur ; en voici un :
Indispensable pour Assembleur, théorie, pratique et exercices pour processeur Intel, Bernard Fabrot, Marabout est pratique.
puceSachez cependant que le code Assembleur de Delphi n'est pas tout à fait le même que celui utilisé par l'auteur du livre en question. Les lignes qui suivent devraient vous aider à assurer la "traduction".

Nous vous proposons d'écrire vous-même des fonctions et procédures en assembleur, remplaçant la fonction Port, et après test, de les ranger dans une librairie. Elles pourront être appelées, mais pas modifiées par erreur. De plus vous pourrez interdire l'accès à certaines adresses, par exemple en n'associant pas l'adresse de lecture, ou d'écriture du port à une variable accessible depuis l'extérieur de votre Unit Delphi.

Voici un exemple pour la carte Candibus ; vous saurez l'adapter à vos besoins.

  1. A l'aide de l'explorateur, créez un nouveau dossier, nommé Assembleur.
  2. Ouvrez Delphi (ceci a été testé en Delphi 4)
  3. Faites : Enregistrer le projet sous
  4. Nommez le Project : ProjAsm
  5. Nommez l'Unit : CandibusTmp
  6. Faites : Fichier | Nouveau | Unité (choisi dans la boîte de dialogue qui s'ouvre)
  7. Faites : Fichier | Enregistrer sous : Candibus.
  8. Entrez et testez le code dans CandibusTmp ; L'Unit CandibusTmp, associée à sa Form1 servira aux tests, l'Unit Candibus sans Form servira à compléter la librairie de Delphi.
  9. vous pouvez ajouter des Button et des Edit pour tous vos tests.
  10. Une fois tout au point, recopiez votre code, au bon endroit, dans l'Unit Candibus.
  11. Compilez, sauvegardez.

  12. Retournez dans l'explorateur, copiez le fichier Candibus.dcu qui se trouve dans le dossier Assembleur et collez-le dans la librairie de Delphi, par exemple C:\Borland\Delphi4\Lib, ou mieux : C:\Borland\Delphi4\Lib\personnel Il est conseillé de coller aussi Candibus.Pas ; ce fichier sera employé par Delphi 4, lors du debbugage.
  13. Le professeur devra coller Candibus.dcu dans la librairie Delphi, sur chaque ordinateur élève. Cela a été testé en Delphi 4.
  14. Pour employer la procédure EcrireDansA, les élèves devront ajouter Candibus, à la liste des Uses, puis, dans leur code entrer Candibus.EcrireDansA...
  15. Il n'est pas nécessaire de taper Candibus., mais en faisant cela, et en attendant une fraction de seconde, Delphi donne la liste de ce qui est disponible dans la librairie Candibus, avec la syntaxe et les noms de variables. De plus, si par malheur existait dans Delphi une fonction de même nom que la nôtre, cela permettrait de les différencier.

  16.  Nous avons tenté la même chose en Delphi 3.
     Plusieurs versions semblant identiques n'ont pas réagi de la même manière. L'une a réclamé en plus de copier le fichier Candibus.pas dans le dossier Delphi3 \ Imports
  17. D'autres versions ont simplement déclaré une erreur. En Delphi 3, il vaut mieux copier Candibus.dcu et Candibus.pas dans : Delphi3 \ Imports


Haut de cette page

6 Code assembleur, en Delphi 4


Voilà à quoi devrait ressembler votre Unit Candibus définitive :

unit Candibus;

interface

Procedure Configurer(valeur : Byte) ; // accessible depuis l'extérieur de Unit Candibus
Procedure EcrireDansA(valeur : Byte) ;
Function LireB : Word ; pascal ;
Function LireC : Byte ; pascal ;
Function Bit(exposant : Byte) : Byte ;

implementation

Const

adresseConfiguration : Word = $28F ; // inaccessible depuis l'extérieur de Unit Candibus
adressePortA : Word = $28C // donc non modifiable par erreur par les élèves
adressePortB : Word = $28D ;
adressePortC : Word = $28E ;

Procedure Configurer(valeur : Byte) ;
begin
Asm
mov dx, adresseConfiguration
mov al, valeur //si valeur = 155-16 -> A en sortie, B et C en entrée
out dx,al
End;
end;

Procedure EcrireDansA(valeur : Byte) ;
begin
Asm
mov dx, adressePortA
mov al, valeur
out dx,al
End;
end;

{cette fonction lit 16 bits (un Word). Le nombre lu est dans EAX}
{EAX contient 32 bits, AX contient les 16 bits de poids le plus faible de EAX,  AL contient les 8 bits de poids le plus faible de AX, ou EAX}

Function LireB : Word ; pascal ;
Begin
Asm
mov dx, adressePortB
in ax,dx
mov @Result,ax ; {on transfère AX, soit 16 bits, soit un Word à l'adresse Result, sur laquelle pointe @Result}
End ;
End ;

Function LireC : Byte ; pascal ;
Begin
Asm
mov dx, adressePortC
in ax,dx
mov @Result,al {même chose, mais on veut 8 bits, soit un octet, ou Byte ; on les prend dans AL}
End ;
End ;

{delphi n'a pas la fonction puissance}
{on obtient 2 puissance exposant ; si exposant sort de l'intervalle 0..7, le résultat est 0}
{pour mettre à 1, les bits 0,3 et 7 du port A, il suffira de faire : EcrireDansA(Bit(0) + Bit(3) + Bit(7)) ;}

Function Bit(exposant : Byte) : Byte ;
Begin
Result := 1 Shl exposant ; // attention Shl ne marche que sur un Byte (octet)
End ;
end.
 

Haut de cette page

7 Temporisation en Delphi 3 et 4


Nous avons déjà parlé de l'usage de la fonction Sleep (durée : Integer, millisecondes), ainsi que de l'usage d'un Timer. Cela ne convient qu'en très basse fréquence.
Voici du code qui permet de travailler plus vite :

7.1. Usage de GetTickCount


Cela permet d'aller un peu plus vite qu'avec un composant Timer, mais on atteint péniblement 1 000 Hz et encore !
(résultat semblant dépendre de la version de Delphi).

var
dateArret, delai : LongInt;
{on utilise une procédure Tant Que ... }
dateArret := GetTickCount + delai ;  // précision -2, +14 ms
while GetTickCount < dateArret do Begin
//Application.ProcessMessages ;
End ;

7.2. Usage d'une boucle


Les boucles en Delphi donnent parfois des résultats curieux, car le compilateur très puissant détecte les actions inutiles (et une boucle d'attente en est une) et décide parfois de passer outre. Vérifiez, après compilation la présence de points bleus dans la gouttière, à gauche de votre code.

Voici deux exemples de procédures écrites en assembleur ; le premier est 'sécurisé' par usage de tests ; il est donc un peu plus lent, mais cela semble dépendre de l'adresse où il se trouve en mémoire de l'ordinateur.

Procedure Attendre(nombreIterations : LongWord) ; //  Cardinal en Delphi 3. Nombre entier sur 4 octets.

// Réalisation : Jean-Michel Jussiaux, Lycée Xavier Marmier, Pontarlier

Label
Boucle ;

Begin
If (nombreIterations <=0) Then nombreIterations := 1 ; // si 0, on repart pour un grand tour !
If (nombreIterations > 100000000) Then nombreIterations := 100000000 ; // environ deux secondes
Asm
mov eax, nombreIterations
boucle:
dec eax
jnz boucle
End ;
End ;

Deuxième exemple :

Procedure AttendreNonSecurise(nombreIterations : LongWord) ;

// Réalisation : Jean-Michel Jussiaux, Lycée Xavier Marmier, Pontarlier
{nombreIterations doit être strictement supérieur à 0, et inférieur
à environ 100 000 000 (attente de environ 2 secondes)}

Label
Boucle ;
Asm
mov eax, nombreIterations
boucle:
dec eax
jnz boucle
End ;

// remarquez que Begin ... End ; ne sont pas nécessaires. La boucle prend deux cycles d'horloge du processeur. A 200 MHz, cela fait 100 millions de boucles par seconde. La régularité est cependant loin d'être parfaite, rançon du multi tâches.

7.3. Usage du Timer de 'précision'


Voici un exemple qui marche en Delphi 4. Il a été trouvé sur le site Borland et debuggé.

var
frequence, lu1, lu2, lu3, lu4 : TLARGEINTEGER;
dateArret, delai : LongInt;
i, nombrePoints : Integer ;

begin
QueryPerformanceFrequency(frequence) ;
delai := StrToInt(Form1.Edit2.Text) ;
If delai < 1 Then delai := 1 ;
If delai > 10000 Then delai := 10000 ;
nombrePoints := StrToInt(Form1.Edit3.Text) ;
If nombrePoints < 1 Then nombrePoints := 1 ;
If nombrePoints > 1000 Then nombrePoints := 1000 ;
SetLength(tableauMesures1, nombrePoints + 1 ) ;
SetLength(tableauMesures2, nombrePoints + 1 ) ;
lu2 := 0 ;
QueryPerformanceCounter(lu3) ;
For i := 0 To nombrePoints-1 Do Begin  //1° mesure mauvaise
tableauMesures1[i] := Candibus.LireVoie1 ;
tableauMesures2[i] := Candibus.LireVoie2 ;
Candibus.LancerEchantNumVoie1 ;
Candibus.LancerEchantNumVoie2 ;
QueryPerformanceCounter(lu1) ;
dateArret := lu1 + Trunc((delai * frequence)/10000) ;
while (lu2 <= dateArret) do Begin
QueryPerformanceCounter(lu2) ;
//Application.ProcessMessages ;
End ; End ;

QueryPerformanceFrequency(frequence) ; donne la fréquence du compteur 'haute performance' de Windows.

Nous avons trouvé 1 193 180 Hz sur quelques machines vieilles de 2 ou 3 ans.
QueryPerformanceCounter(lu3) ; lit la valeur du compteur de temps qui tourne à la fréquence précédente depuis la mise en marche de la machine. C'est un TLARGEINTEGER, type Microsoft que Delphi 4 convertit directement en entier.
Dans notre exemple,  Trunc((delai * frequence)/10000), en divisant delai par 10 000 et en tronquant le résultat, nous faisons en sorte que delai exprime un délai en 1 / 10 000 seconde.
Delphi 3 ne convertit pas le type TLARGEINTEGER. Voici ce qu'il convient de faire :
var
frequence, lu1, lu2, lu3, lu4 : TLARGEINTEGER;
dateArret, delai, depart, dateLue, freq : Integer;
i, nombrePoints : Integer ;
begin
QueryPerformanceFrequency(frequence);
freq := frequence.LowPart ;

Le grand entier Microsoft n'est en fait pas un entier. (Chacun sait que même avec de la rigueur, un programme peut planter ; alors sans rigueur ... )
Pour connaître sa constitution, déclarez frequence comme TLARGEINTEGER, puis dans le corps de votre programme entrez : frequence. et attendez que Delphi 3 vous propose diverses éventualités. LowPart est un entier. Merci Delphi.
Delphi 3 n'accepte pas des déclarations du genre :
Var
tableauMesures2 : Array Of Real
SetLength(tableauMesures2, 1000 ) ;
Il faut faire :
Var
tableauMesures2 : Array [0..1000] Of Real
Ce qui est plus rigide.
Dans les deux cas, la régularité de l'horloge obtenue n'est pas fantastique, mais elle tourne assez vite.

Pour obtenir mieux, il faut masquer les interruptions et employer soit l'horloge intégrée à la carte d'acquisition, soit une des horloges du PC, mais alors attention aux erreurs de programmation qui se terminent par un "plantage" de la machine. Vous consulterez avec profit l'ouvrage : "PC, programmation système,  ressources d'experts, CampusPress, S&SM".
 

Haut de cette page

Composant PhyJiC, pilotant les cartes d'acquisition Candibus


Vous le trouverez au chapitre Logiciels.