今次我會寫1些關於program的knowhow。其實也不算是甚麼了不起的事,例如我們的在和其他裝置通信的時侯很多時侯都會用byte配列作為data傳送的buffer,最後會用人手作mapping。例如頭4個byte是小數,之後2byte是整數。
首先我們試試想一下將最初的4bytes轉換成小數。
在google有很多的web有hex轉變器,例如今次我用的時這個↓
https://gregstoll.com/~gregstoll/floattohex/
3.41242=0x405a6517
我們要小心byte的順序是samll還是big;這樣會影響byte排列的次序。
方法1-UNION構造體
利用UNION 可簡單地處理這種問題。union是一種data type是data type內每1個變數都持有同一樣的memory offset。那就算儘管變數是不同,但每個變數都有同樣的memory offset。用文字說明很難明白,我會用例子向大家說明一下。
説明
首先DUT>ADD>DUT新增1個dut。
然後選最下面的union,open。
首先我們再定義另1個dut,是由8個bit data組成。
TYPE DUT_8Bits : STRUCT bBit1 : BIT; bBit2 : BIT; bBit3 : BIT; bBit4 : BIT; bBit5 : BIT; bBit6 : BIT; bBit7 : BIT; bBit8 : BIT; END_STRUCT END_TYPE |
然後我們追加1個union dut,名為uDUT_16Bits。
大家都從下面的例子看見,example多了1個UNION的預約語。
然後我們同時定義了3個變數,iValue,bBytes,arrBool。
因為這個dut是union,iValue=bBytes=arrBool。
TYPE uDUT_16Bits : UNION iValues :UINT; bBytes :ARRAY[0..1] OF BYTE; arrBool :ARRAY[0..1] OF DUT_8Bits; END_UNION END_TYPE PROGRAM MAIN_UNION_SAMPLE VAR u:uDUT_16Bits; END_VAR |
現在我們做1點測試,iValues=0。同時見到arrBool和bBytes的現在值都是0。
iValues=1的時侯,arrBool[0].bBit1變成True,bBytes[0]的值也變成1。
所有的變數值也是一致。
今次將bBytes[0]=255,bBytes[1]=3,大家也看到其他變數也有同樣的轉變。
Example
那我們就再寫1點程式。
定義1個union的dut,入面為4bytes的array,另1個變數是小數=4Bytes。
DUT
TYPE DUT_Bytes2LReal : UNION arrBytes :ARRAY[0..3] OF BYTE; rReal :REAL; END_UNION END_TYPE |
VAR
PROGRAM MAIN_UsingUNION
VAR
rMyRealValue :REAL;
data :Dut_Bytes2LReal;
cLSB :BOOL:=TRUE;
END_VAR
Code
IF NOT cLSB THEN data.arrBytes[0]:=16#40; data.arrBytes[1]:=16#5A; data.arrBytes[2]:=16#65; data.arrBytes[3]:=16#17; ELSE data.arrBytes[0]:=16#17; data.arrBytes[1]:=16#65; data.arrBytes[2]:=16#5A; data.arrBytes[3]:=16#40; END_IF rMyRealValue:=data.rReal; |
結果
4Bytes的配列轉換成32bit小數。
方法2-使用Pointer
第2個方法是利用ADR將byte array的memory address offset,然後定義1個pointer,最後用^將byte array作為1個小數去讀取。我們會見到在beckhoff的function,functon blocks都見到有很好多時侯見到這個引數。
Example
VAR
PROGRAM MAIN_UsingPointer VAR rMyRealValue:REAL; arrBytes :ARRAY[0..3] OF BYTE; cLSB :BOOL:=TRUE; pReal :POINTER TO REAL; END_VAR |
Code
IF NOT cLSB THEN arrBytes[0]:=16#40; arrBytes[1]:=16#5A; arrBytes[2]:=16#65; arrBytes[3]:=16#17; ELSE arrBytes[0]:=16#17; arrBytes[1]:=16#65; arrBytes[2]:=16#5A; arrBytes[3]:=16#40; END_IF pReal:=ADR(arrBytes); rMyRealValue:=pReal^ ; |
結果
同樣地,4Bytes的配列轉換成32bit小數。
Sample Code:
https://github.com/soup01Threes/TwinCAT3/blob/main/TwinCAT%20Project_ConvertBytesArray2Real.tnzip
Twitter:@3threes2
email:soup01threes*gmail.com (*>@)