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; }