Serielle Kommunikation TwinCAT3 mit Beckhoff CX2030 und EL 6001

AdamMax

Level-1
Beiträge
6
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Liebes Forum,

ich möchte von einem PC über RS232 mit der CX2030 kommunizieren. Ich kann auch bereits Daten empfangen und auch senden.
Ich sende vom PC eine Anfrage an die CX2030, welche sich lediglich an einer Stelle unterscheidet.

Diese Stelle wird als CMD Byte angegeben. Ich benutze die Funktion ReceiveData, welche mir den Request in einen ByteArray schreibt.
Das Problem ist nun, dass ich in einer "Endlosschleife" lande wenn ich eine Anfrage sende. Die States 1-3 laufen im Dauerlauf sobald eine korrekte Anfrage erfasst wurde.

Problem ist: Man kann den rxBuffer nicht mit 0en Belegen nachdem die Kommunikation einmal komplett durchgelaufen ist. D.h. ein zweiter Request ist gar nicht erst möglich.


Mein Quellcode:




(*
BYTE 0 = TOKEN = 16#FC
BYTE 1 = DAB = 0x01 - 0x06 je nach Station Number
BYTE 2 = SAB = N.D.
BYTE 3 = LEN Byte
BYTE 4 = CMD Byte
BYTE 6 + LEN + 1 = CRC LOW
BYTE 7 + LEN + 2 = CRC HIGH
BYTE 8 + LEN + 3 = STOP BYTE = 16#CF
insgesamt 9 Bytes
*)
// State Machine
CASE n_state OF
1: //Lese 9 Byte
fb_read_data(
pPrefix:= ADR(b_prefix),
LenPrefix:= UINT_TO_BYTE(SIZEOF(b_prefix)),
pSuffix:= ADR(b_suffix),
LenSuffix:= UINT_TO_BYTE(SIZEOF(b_suffix)),
pReceiveData:=ADR(ar_receive) ,
SizeReceiveData:= SIZEOF(ar_receive),
Reset:= ,
Timeout := ,
DataReceived=> ,
busy=> ,
Error=> fbLineError ,
RxTimeout=> ,
LenReceiveData=> ,
RXbuffer:= rxBuffer);
IF NOT fb_read_data.busy THEN
n_state := 2;
END_IF
2: // Verarbeitung
IF ar_receive[0] = 252 AND ar_receive[1] = stationNumber THEN
TokenDABError := FALSE;
//Buffer auslesen und Kommunikation fuer den Pruefplatz vorbereiten
copiedSABByte := ar_receive[2]; //SAB Byte wird von der Pruefplatz Software festgelegt (.ini Datei)
//copied SAB Byte muss wieder über den Bus verschickt werden
copiedLENByte := ar_receive[3]; //LEN Byte ist bei der Anfrage von der Pruefplatz Software immer = 1
//CMD Bytes auswerten. Das Byte ist entscheidend, welche Information ueber den Bus gesendet werden soll
copiedCMDByte := ar_receive[4];
IF copiedCMDByte = GVL_CMD.CMD_Ping THEN
sendPing := TRUE;
cmdError := FALSE;
ELSIF copiedCMDByte = GVL_CMD.CMD_PowerMeas1 THEN
sendPowerMeas1 := TRUE;
cmdError := FALSE;
ELSIF copiedCMDByte = GVL_CMD.CMD_PowerMeas2 THEN
sendPowerMeas2 := TRUE;
cmdError := FALSE;
ELSIF copiedCMDByte = GVL_CMD.CMD_Signals THEN
sendSignals := TRUE;
cmdError := FALSE;
ELSIF copiedCMDByte = GVL_CMD.CMD_HP_LP THEN
sendHPLP := TRUE;
cmdError := FALSE;
ELSE
cmdError := TRUE;
END_IF
(*
ar_receive[5] //CRC Low
ar_receive[6] //CRC High
ar_receive[7] //Stop Byte
*)
//SendData vorbereiten----------------------------------------------------------------------------------------------------------------------------------------------
//CRC16 mit Polynom 0x1021
crcInitValue := 65535;
crcInitValue := F_DATA_TO_CRC16_CCITT( pData := ADR(rxBuffer),
cbData := lengthCRCData,
crc := crcInitValue);
// Low Byte
pCrcPointer := ADR(crcInitValue);
crcLow := pCrcPointer^;
// High Byte
pCrcPointer := pCrcPointer +1;
crcHigh := pCrcPointer^;
//Daten aus den Klemmen in den prepareSPSData Buffer schreiben-------------------------------------------------------------------------------------------------------
//Bytes die immer konstant fuer jedes Frame sind:
//Byte 0 TOKEN
txBuffer[0] := GVL_RS232.Token;
//Byte 1 DAB Byte
txBuffer[1] := ar_receive[2];
(*
Byte 2 SAB Byte
SAB Byte PP1 = 1
SAB Byte PP2 = 2
SAB Byte PP3 = 3
SAB Byte PP4 = 4
SAB Byte PP5 = 5
SAB Byte PP6 = 6
*)
IF GVL_PP.PP1 = 1 THEN
txbuffer[2] := IN_DABByte; //DAB Byte von der SPS wird zu SAB Byte an den PC
END_IF
IF cmdError = FALSE THEN //Wenn das CMD Byte richtig ist, wird die Kommunikation vorbereitet
//Prepare Ping Message
IF sendPing = TRUE THEN
txBuffer[3] := GVL_LEN.LEN_Ping;
txBuffer[4] := GVL_CMD.CMD_ANSWER_Ping; //CMD Byte
txBuffer[5] := pingCounter;
txBuffer[6] := pingID;
txBuffer[7] := crcHigh;
txBuffer[8] := crcLow;
sendCommand := TRUE;
sendLEN := 9;
crcLength := BYTE_TO_UINT(GVL_LEN.LEN_Ping);
END_IF
//Prepare PowerMeasurement 1
IF sendPowerMeas1 = TRUE THEN
txBuffer[3] := GVL_LEN.LEN_PowerMeas1;
txBuffer[4] := GVL_CMD.CMD_ANSWER_Powermeas1;
(* txBuffer[5] := L1VoltageMSB;
txBuffer[6] := L1VoltageLSB;
txBuffer[7] := L2VoltageMSB;
txBuffer[8] := L2VoltageLSB;
txBuffer[9] := L3VoltageMSB;
txBuffer[10] := L3VoltageLSB;
*) // filled with Fake Data for Testing
txBuffer[5] := 255;
txBuffer[6] := 255;
txBuffer[7] := 200;
txBuffer[8] := 200;
txBuffer[9] := 150;
txBuffer[10] := 150;

txBuffer[11] := L1CurrentMSB;
txBuffer[12] := L1CurrentLSB;
txBuffer[13] := L2CurrentMSB;
txBuffer[14] := L2CurrentLSB;
txBuffer[15] := L3CurrentMSB;
txBuffer[16] := L3CurrentLSB;
txBuffer[17] := crcHigh;
txBuffer[18] := crcLow;
sendCommand := TRUE;
sendLEN := 19;
crcLength := BYTE_TO_UINT(GVL_LEN.LEN_PowerMeas1);
END_IF
//Prepare PowerMeasurement 2
IF sendPowerMeas2 = TRUE THEN
txBuffer[3] := GVL_LEN.LEN_PowerMeas2;
txBuffer[4] := GVL_CMD.CMD_ANSWER_Powermeas2;
txBuffer[5] := ActivePowerMSB;
txBuffer[6] := ActivePowerLSB;
txBuffer[7] := ReactivePowerMSB;
txBuffer[8] := ReactivePowerLSB;
txBuffer[9] := ComplexPowerMSB;
txBuffer[10] := ComplexPowerLSB;
txBuffer[11] := crcHigh;
txBuffer[12] := crcLow;
sendPowerMeas2 := FALSE;
sendCommand := TRUE;
crcLength := BYTE_TO_UINT(GVL_LEN.LEN_PowerMeas2);
sendLEN := 14;
END_IF
//Prepare Signals
IF sendSignals = TRUE THEN
txBuffer[3] := GVL_LEN.LEN_Signals;
txBuffer[4] := GVL_CMD.CMD_ANSWER_Signals;
txBuffer[5] := inputSignalsMSB;
txBuffer[6] := inputSignalsLSB;
txBuffer[7] := outputSignalsMSB;
txBuffer[8] := outputSignalsLSB;
txBuffer[9] := crcHigh;
txBuffer[10] := crcLow;
sendCommand := TRUE;
sendLEN := 11;
sendSignals := FALSE;
crcLength := BYTE_TO_UINT(GVL_LEN.LEN_Signals);
END_IF
//Prepare High-Pressure, Prepare Low-Pressure
IF sendHPLP = TRUE THEN
txBuffer[3] := GVL_LEN.LEN_HP_LP;
txBuffer[4] := GVL_CMD.CMD_ANSWER_HP_LP;
txBuffer[5] := highPressureMSB;
txBuffer[6] := highPressureLSB;
txBuffer[7] := lowPressureMSB;
txBuffer[8] := lowPressureLSB;
txBuffer[9] := crcHigh;
txBuffer[10] := crcLow;
sendCommand := TRUE;
sendHPLP := FALSE;
crcLength := BYTE_TO_UINT(GVL_LEN.LEN_HP_LP);
sendLEN := 11;
END_IF
ELSE
sendCommand := FALSE;
END_IF

IF sendCommand = TRUE THEN
n_state := 3; //sending
ELSE n_state := 1; ///noSending
END_IF
ELSE
TokenDABError := TRUE;
n_State := 1;
END_IF

IF cmdError THEN
//n_State := 10;
END_IF

3: // Sende x Byte
//Send Data from TxBuffer
Line01SendData( pSendData := ADR(txBuffer),
Length := sendLen,
Busy => dataSendBusy,
Error => TxComError,
TXbuffer := SerialLineControl_BG.BG_TxBuffer[1]);
IF dataSendBusy = TRUE THEN
dataSendCounter := dataSendCounter + 1;
END_IF

IF NOT Line01SendData.Busy THEN
n_State := 1;
END_IF
sendCommand := FALSE;
ClearComBuffer( Buffer := rxBuffer);
fb_read_data.Reset := TRUE;
10: //Error
//n_State := 1;
ELSE
n_state := 1;
END_CASE
 
Vorweg: Stell bitte Code in Code Tags, damit er besser lesbar ist.
Ohne alles gelesen zu haben: Du musst in Schritt 2 DataReceived des fb_read_data auswerten. Der wird immer für einen PLC-Zyklus true, wenn ein Datensatz empfangen wurde. Dann brauchst Du auch den Empfangspuffer nicht löschen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das mit den Code-Tags merke ich mir. Dankeschön.
Das DateReceived habe ich auch schon mal ausgewertet. Leider wird das auch TRUE, wenn ich vom PC keine Anfrage sende.
 
Dann passt irgendwas mit der Vorgabe von Prefix/Suffix oder Datensatzlänge nicht, so dass irrtümlich "Datensatz komplett" erkannt wird.
 
Zurück
Oben