博圖TIA中ModbusRTU_CRC校驗程序的實現


博圖TIA中ModbusRTU_CRC校驗程序的實現

使用SCL語言,在博圖TIA中編寫ModbusRTU_CRC校驗程序,使用兩個FC塊,實現兩種不同的應用CRC1將計算結果直接輸出,CRC2將計算的結果插入到輸入數組的最后端.

TIA中自帶了modbusRTU通訊庫,之所以自己實現CRC校驗碼的計算只是為了更深入的學習TIA SCL編程序.

實現效果及代碼截圖

代碼片段

CRC1

FUNCTION "CRC1" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      CrcData : Variant;
   END_VAR

   VAR_OUTPUT 
      CrcValue : Word;
      CrcErr : Word;
   END_VAR

   VAR_TEMP 
      Preset : Word;
      LoopLength : Int;
      ArrayPoint : Int;
      i : Int;
      ArrayLength : UDInt;
      Array1 : Array[0..999] of Byte;   // 最多1000個字節
      Err : Int;
   END_VAR


BEGIN
	#ArrayLength:= CountOfElements(#CrcData);
	
	IF #ArrayLength <= 1000 THEN //這里的1000如果需要調大,對應的數組臨時變量Array1也要調大
	    #Err := MOVE_BLK_VARIANT(SRC := #CrcData, COUNT := #ArrayLength, SRC_INDEX := 0, DEST_INDEX := 0, DEST => #Array1);
	    #Preset := 16#FFFF;
	    #LoopLength := 0;
	    #ArrayPoint := 0;
	    
	    //計算CRC校驗碼
	    WHILE #LoopLength < #ArrayLength DO    //數據長度
	        #Preset := #Preset XOR #Array1[#ArrayPoint];
	        #ArrayPoint := #ArrayPoint + 1;
	        FOR #i := 0 TO 7 DO
	            IF (#Preset AND 16#01) = 16#01 THEN
	                #Preset := SHR(IN := #Preset, N := 1);
	                #Preset := #Preset XOR 16#A001;
	            ELSE
	                #Preset := SHR(IN := #Preset, N := 1);
	            END_IF;
	        END_FOR;
	        #LoopLength := #LoopLength + 1;
	    END_WHILE;
	    
	    //#CrcValue := #Preset;
	    #CrcValue := SHR_WORD(IN := #Preset, N := 8) + SHL_WORD(IN := #Preset, N := 8);
	    #CrcErr := 16#0000;
	ELSE
	    #CrcErr := 16#8000;
	END_IF;
	
END_FUNCTION

SEND1

DATA_BLOCK "SEND1"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
NON_RETAIN
   STRUCT 
      CrcData : Array[0..5] of Byte;   // 該數組不大於1000字節
      CrcValue : Word;
      CrcError : Word;
   END_STRUCT;


BEGIN
   CrcData[0] := 16#01;
   CrcData[1] := 16#03;
   CrcData[2] := 16#00;
   CrcData[3] := 16#00;
   CrcData[4] := 16#00;
   CrcData[5] := 16#01;

END_DATA_BLOCK

CRC2

FUNCTION "CRC2" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      Command : Variant;
      dataLen : Int;
   END_VAR

   VAR_TEMP 
      buffer : Array[0..#MaxLen] of Byte;
      i : Int;
      j : Int;
      CrcReg : Word;
      Len : Int;
   END_VAR

   VAR CONSTANT 
      MaxLen : Int := 255;
   END_VAR


BEGIN
	IF #dataLen = 0 OR #dataLen > CountOfElements(IN := #Command) - 2 THEN
	    RETURN;
	ELSE
	    #Len := #dataLen;
	END_IF;
	
	#CrcReg := 16#FFFF;
	
	//將數據轉到緩沖區
	VariantGet(SRC:=#Command,
	           DST=>#buffer);
	
	//計算CRC校驗碼
	FOR #i := 0 TO (#Len - 1) DO
	    #CrcReg := #CrcReg XOR #buffer[#i];
	    FOR #j := 0 TO 7 DO
	        IF (#CrcReg AND 16#1) = 1 THEN
	            #CrcReg := SHR_WORD(IN := #CrcReg, N := 1);
	            #CrcReg := #CrcReg XOR 16#A001;
	        ELSE
	            #CrcReg := SHR_WORD(IN := #CrcReg, N := 1);
	        END_IF;
	    END_FOR;
	END_FOR;
	
	#buffer[#Len + 1] := SHR_WORD(IN := #CrcReg, N := 8);
	#buffer[#Len] := #CrcReg AND 16#FF;
	
	//將緩沖區數據再寫入到指針所指向的區域
	VariantPut(SRC := #buffer,
	           DST := #Command);
	
	
END_FUNCTION

SEND2

DATA_BLOCK "SEND2"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
NON_RETAIN
   STRUCT 
      CrcData : Array[0..7] of Byte;   // 該數組不大於1000字節
   END_STRUCT;


BEGIN
   CrcData[0] := 16#01;
   CrcData[1] := 16#03;
   CrcData[2] := 16#00;
   CrcData[3] := 16#00;
   CrcData[4] := 16#00;
   CrcData[5] := 16#01;

END_DATA_BLOCK


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM