Siemens 3964 Protokoll



  • Hallo,
    hat sich jemand mit dem Protokoll beschäftigt? Ich möchte eine Kommunikation zur Simatic S/5 schreiben. Hab' das zwar vor 10 Jahren mal unter OS/2 gemacht (das ist lange her) und jetzt ist die Migration nach NT, möglichst mit dem BCC fällig.
    Gruß, Hermann



  • <snip>

    Hallo Hermann,

    schau dir einmal die LUCA von Langner an.
    Mit der habe ich es damals gemacht.

    Gruß Rainer

    Edit:
    Zitate bitte auf das Notwendigste beschränken. Danke!
    -Jansen



  • Ich weiss zwar nicht was die Luca von Langner ist, aber ich habe mal eine Klasse für verschiedene Protokolle geschrieben.
    Setze jetzt mal voraus, dass Dir das 3964(R)-Protokoll bekannt ist.
    Wenn nicht, frag einfach nochmal.

    Habe dir das Senden/Empfangen mal rauskopiert.

    void  TCustomCommHandler::SendDust3964R(string& Str )
    {
    	string sSendData;
      string sDupData;
      bool bWriteOK;
      char cChr;
      int i,iSum;
      string tmpString;
      DWORD dWrCount,
      iRetryCnt;
    
      sSendData ="";
      if (Str.length() >0)
        for( i=0; i < (int) Str.length(); i ++)
          if (Str[i]==DLE)
            sSendData = sSendData+DLE+DLE;
          else
            sSendData =sSendData+Str[i];
    
      sSendData=sSendData+DLE+ETX;
      iSum = 0;
      for( i=0; i < (int) sSendData.length(); i ++) iSum = iSum ^ (int)sSendData[i];
        sSendData = sSendData + char(iSum);
    
      iRetryCnt=0;
      do {
        SendChar(STX);
        cChr = WaitForChar(DLE);
        if ((iLastError==CE_OK) && (cChr==DLE))
        {
          if (cDupChar==NUL)
            bWriteOK=WriteFile(iCommId,sSendData.c_str(),sSendData.length(),&dWrCount,NULL);
          else
          {
            sDupData = "";
            for( i = 0; i < (int) sSendData.length(); i ++)
              if (sSendData[i] == cDupChar)
                sDupData = sDupData+cDupChar+cDupChar;
              else
                sDupData = sDupData+sSendData[i];
            bWriteOK=WriteFile(iCommId,sDupData.c_str(),sDupData.length(),&dWrCount,NULL);
          }
          if (bWriteOK)  iLastError = CE_OK; else iLastError = GetCommError();
          if ((iLastError == CE_OK) && bWithAnswer)
          {
        	tmpString  = DLE;
            tmpString += NAK;
            cChr = WaitForMultiChar(tmpString);
            if ((iLastError == CE_OK) && (cChr!=DLE))
            	iLastError = CE_NAKRECEIVED;
          }
        }
    
        if (iLastError!=CE_OK)
        {
          tmpString = "COMM-Error : ";
          #ifndef __BORLANDC__
            tmpString += IntToStr(iLastError);
          #else
            tmpString += IntToStr(iLastError).c_str();
          #endif
          WriteLog(tmpString,ltWrite);
        }
        else
          WriteLog(sSendData,ltWrite);
    
        iRetryCnt += 1;
      } while (!(((int)iRetryCnt> iRetries) || (iLastError==CE_OK)));
    }
    
    string  TCustomCommHandler::ReceiveDust3964R()
    {
      string sCheckSumStr;
      int iRetryCnt,
      i,
      iSum;
      bool bDLEReceived,
      bSTXReceived;
      char cCheckSumRec;
      char cChr;
      string tmpString;
    
      string ReceiveDust3964R_result;
      iRetryCnt = 0;
      do {
        bSTXReceived = false;
        cChr = WaitForChar((char&)STX);
        if (iLastError == CE_OK)
          {
            bSTXReceived = true;
            SendChar((char&)DLE);
            bDLEReceived = false;
            ReceiveDust3964R_result  = "";
            sCheckSumStr = "";
            while ((iLastError==CE_OK) && !(bDLEReceived && (cChr==ETX)))
              {
                cChr = GetChar();
                if (iLastError == CE_OK)
                  {
                    sCheckSumStr = sCheckSumStr+cChr;
                    if (bDLEReceived)
                      {
                        if (cChr == DLE)
                          {
                            ReceiveDust3964R_result = ReceiveDust3964R_result+DLE;
                            bDLEReceived = false;
                          }
                      }
                    else
                      if (cChr==DLE)
                        bDLEReceived = true;
                      else
                        ReceiveDust3964R_result = ReceiveDust3964R_result+cChr;
                  }
              }
          }
    
        if (iLastError==CE_OK)
          {
            iSum = 0;
            for( i=0; i < (int) sCheckSumStr.length(); i ++)
              iSum = iSum ^ (int)sCheckSumStr[i];
            cCheckSumRec=WaitForChar((char&)NUL);
            if ((iLastError == CE_OK) && (iSum!=(int)cCheckSumRec))
              iLastError = CE_NAKTRANSMIT;
          }
        if (iLastError==CE_OK)
        {
            SendChar((char&)DLE);
        }
        else
          if (bSTXReceived)  SendChar((char&)NAK);
    
        if (iLastError!=CE_OK)
        {
          tmpString = "COMM-Error : ";
          #ifndef __BORLANDC__
            tmpString += IntToStr(iLastError);
          #else
            tmpString += IntToStr(iLastError).c_str();
          #endif
          WriteLog(tmpString,ltWrite);
    		}
        else
          WriteLog(ReceiveDust3964R_result,ltRead);
    
        iRetryCnt += 1;
      } while (!((iRetryCnt>iRetries) ||
            ((iLastError==CE_TIMEOUT) && ! bSTXReceived) ||
            (iLastError==CE_OK)));
      return ReceiveDust3964R_result;
    }
    


  • Erst mal vielen Dank für die promten Postings!!!
    LUCA-Demo habe ich mir sofort runtergeladen und bin am evaluieren. Sieht recht gut aus, ein Riesenpaket, ich fürchte nur die Kosten dafür gibt mein Miniprojekt nicht her. Aber als Anschauung absolut super.
    Auch für den samplecode von Aheim vielen Dank! So ähnlich sieht mein OS/2 Lösung selig auch aus ;=)
    Mein Hauptproblem ist die Synchronisierung von send und receive. Da muss irgend was mit Semaphoren, Threads und Pipes wieder her, da stehe ich mit dem BCC (noch) etwas auf dem Schlauch.
    Gruß Hermann



  • Das Problem mit der Synchronisation hatte ich auch, da ich mit der gleichen Klasse mehrere Schnittstellen, teilweise dieselbe, abfrage.
    Das habe ich dann durch Semaphoren verriegelt. Dies hat aber nichts mit dem BCC zu tun sondern Winapi.

    Habe Dir das auch mal kopiert:

    char* SemaText = new char[Port+10];
    
      // Semaphorenname zusammenbasteln der eindeutig ist
      // Falls ein anderes Objekt erzeugt wurde, was auf denselben Port zugreift
      // kann hiermit sichergestellt werden, daß nicht beide gleichzeitig senden
      sprintf(SemaText,"%s%d","Com",Port);
    
      hSemaphore = CreateSemaphore(
        NULL,   // no security attributes
        1,   // initial count
        1,   // maximum count
        SemaText);  // unnamed semaphore
    
      if(GetLastError()==ERROR_ALREADY_EXISTS)
        ShowMessage("Fehler bei Erstellung der Semaphore\nexistiert schon");
    
      if (hSemaphore == NULL)
      {
        // Check for error.
    //    ~TScaleHandler();
      }
    
    //  ....weiterer hierfür nicht wichtiger Code
    
    // Semaphorenanforderung
    bool TScaleHandler::RequestSema()
    {
      int i = 0;
    
      // insgesamt wird 10 Sekunden auf die Freigabe der Semaphore gewartet
      // mögliche Rückmeldungen von WaitForSingleObject:
      //          WAIT_OBJECT_0 ==> Semaphore freigegeben
      //          WAIT_TIMEOUT  ==> Semaphore belegt
      // mit Infinite würde das aufrufende Programm niemals wieder erreicht werden
    
      do {
        // wir warten 0,1 sec (100ms) für unendlich -> INFINITE
        dwWaitResult = WaitForSingleObject(hSemaphore, 100L);
        ++i;
      }  
      while( (dwWaitResult != WAIT_OBJECT_0) && (i < 100));
    
      if(dwWaitResult == WAIT_OBJECT_0)
        // Semaphore signaled.
        return true;
      else
        iLastError = SE_REQSEMA;
      return false;
    
    }
    
    // Semaphorenfreigabe
    bool TScaleHandler::ReleaseSema()
    {
      if (!ReleaseSemaphore(hSemaphore,1, NULL) )
      {
        iLastError = SE_RELSEMA;
        return false;
      }  
      else
        return true;
    }
    
    // Beispiel, wie und wo Semaphorenverriegelung benutzt wurde
    
    bool TScaleHandler::Auto_Tare()
    {
    
      if(!RequestSema())
        return false;
    
      // hier steht der Code, der nicht "gestört" werden darf
    
      if(!ReleaseSema())
        return false;
    }
    

Anmelden zum Antworten