Archives de catégorie : Labo

cifX : Mise en œuvre : API – Introduction

Bonjour,

Nous avons donc configuré en Modbus TCP Serveur ou en PROFIBUS DP Esclave notre carte Hilscher cifX et avons pu tester notre configuration avec les outils fournis sans avoir à écrire une seule ligne de code.

Donc ça communique mais votre application doit pouvoir utiliser ce canal de communication et ce facilement.

Hilscher propose une API (Application Programming Interface) commune à tous nos produits, quel que soit le protocole de communication mise en œuvre.

Cette API est fournie par une bibliothèque de fonctions, dans une DLL sous Windows®, qui permet l’interaction avec la mémoire double accès (DPM : Dual Port Memory) qui définit l’interface entre le système hôte (Windows®, RTX®, QNX®, VxWorks®, Linux…) et la plateforme Hilscher netX/rcX.

Comme expliqué dans l’article cifX, comX, netJACK : une petite synthèse, votre application peut être élaborée en C/C++, .Net si vous insistez (nos clients l’ont fait), ou sur la base d’un automate logiciel comme Siemens WinAC® RTX® ou ISaGRAF®.

Dans cet article, nous allons compiler le C…

Sur le DVD « Communication Solutions DVD for cifX, comX and netJACK » l’on trouve la documentation suivante :

  • netX Dual-Port Memory Interface (DPM) : ce manuel décrit la structure et le fonctionnement de la DPM, les structures de données et les fonctions communes à tous les firmwares.
  • cifX Device Driver – cifX API : ce document décrit l’interface applicative, c’est à dire l’ensemble des fonctions nécessaires à l’exploitation des cartes Hilscher cifX depuis une application.

Of course, c’est en Anglais.

Sur ce même DVD on trouve également trois exemples de mise en œuvre, l’un très basique, « cifXDemo », « cifXTest_Console », une application plutôt complète en mode console, et « cifXTest », le code source de l’application de test graphique installée avec le pilote cifX.

A quoi peut bien ressembler un programme en C minimum, mais qui fasse quand même quelque chose, en l’occurrence la recopie des entrées sur les sorties ?
A ceci :

#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include "cifxuser.h"
#include "cifxErrors.h"

#define IO_WAIT_TIMEOUT     10

/*****************************************************************************/
/*! The main function
 *   \return 0 on success                                                     */

/*****************************************************************************/
int main(int argc, char* argv[])
{
  HANDLE hDriver  = NULL;
  HANDLE hChannel = NULL;
  long   lRet     = CIFX_NO_ERROR;

  UNREFERENCED_PARAMETER(argc);
  UNREFERENCED_PARAMETER(argv);

  /* Open the cifX driver */
  lRet = xDriverOpen(&hDriver);
  if(CIFX_NO_ERROR != lRet)
  {
    printf("Error opening driver. lRet=0x%08X\r\n", lRet);
  } else
  {
    lRet = xChannelOpen(hDriver, "cifX0", 0, &hChannel);
    if(CIFX_NO_ERROR != lRet)
    {
      printf("Error opening Channel. lRet=0x%08X\r\n", lRet);
    } else
    {
      /* Read and write I/O data (32Bytes) */
      unsigned char abSendData[32] = {0};
      unsigned char abRecvData[32] = {0};

      /* Do I/O Data exchange until a key is hit */
      printf("Hit any key to stop the process!\r\n");
      while(!kbhit())
      {
        lRet = xChannelIORead(hChannel, 0, 0, sizeof(abRecvData), abRecvData, IO_WAIT_TIMEOUT);
        if(CIFX_NO_ERROR != lRet)
        {
          printf("Error reading IO Data area. lRet=0x%08X\r\n", lRet);
          break;
        } else
        {
          memcpy(abSendData, abRecvData, sizeof(abSendData));

          lRet = xChannelIOWrite(hChannel, 0, 0, sizeof(abSendData), abSendData, IO_WAIT_TIMEOUT);
          if(CIFX_NO_ERROR != lRet)
          {
            printf("Error writing to IO Data area. lRet=0x%08X\r\n", lRet);
            break;
          }
        }
      }
      /* Close the communication channel */
      xChannelClose(hChannel);
    }
    /* Close the cifX driver */
    xDriverClose(hDriver);
  }
  return 0;
}

Trop facile non ?
En l’occurrence aussi, ce code consomme toute la CPU… Je vous laisse le soin de l’améliorer.
Mais cela fonctionne !

Ainsi :

  • xDriverOpen : on ouvre le pilote, ce qui alloue les ressources nécessaires.
  • xChannelOpen : on ouvre le canal de communication 0 de la carte « cifX0 ».

Puis on boucle jusqu’à appui sur une touche :

  • xChannelIORead : on lit les entrées depuis la mémoire image procédé dans le tampon des entrées abRecvData.
  • memcpy : on recopie le tampon des entrées abRecvData dans le tampon des sorties abSendData.
  • xChannelIOWrite : on écrit les sorties depuis le tampon des sorties abSendData dans la mémoire image procédé.

Enfin on referme derrière soi en sortant :

  • xChannelClose : on ferme le canal de communication.
  • xDriverClose : on ferme le pilote, ce qui libère les ressources.

Veuillez noter que cet échange de données entre l’application et l’automate, ici une CPU Siemens S7 315-2DP via PROFIBUS DP, aurait lieu de la même façon avec un autre protocole et un autre partenaire de communication sans modifier le code, comme par exemple un automate Schneider Electric et Modbus TCP ou Ethernet/IP.

Bien sûr, l’API cifX est riche et permet de nombreuses péripéties que j’espère vous dévoiler au fur et à mesure, so stay tuned !

Cordialement,
Stéphane