| 作者 | 主题 |
|---|---|
|
yang9188 侠客
经验值:631 发帖数:44 精华帖:2 |
楼主
主题:【实用FC系列】之一,数字转换为字符串 今天有时间,开辟一个新系列--“实用FC”。这个系列给出一些比较通用的功能。这些通用的功能可能在很多项目中都就用到。比如今天给的是“数字转换为字符”。 数字可以是任意值类型。比如int,real等。FC的功能是把值转换为字符串。我的很多项目都会用到这个FC,应该是bug-free的。 下图是使用该块的例子。 这个块有4个优势: 1,无需查看博图自带块VAL_STRG的帮助,无需填写复杂的参数。 2,自动删除字符串前面的空格。 3,自动删除小数中数字的最后一个0。用博图自带块转换的字符串中,小数部分经常最后一位是0。这个块自动删除 这个0。 4,使得程序看起来更整洁。 程序如下 FUNCTION "SECS_STD_Val2Str" : Void { S7_Optimized_Access := 'TRUE' } VERSION : 0.1 VAR_INPUT Value : Variant; END_VAR VAR_OUTPUT FaultCode : Int; END_VAR VAR_IN_OUT Str : String; END_VAR VAR_TEMP IsFloatType : Bool; Size : USInt; tempStr : String[30]; Value_Sint : SInt; Value_Int : Int; Value_Dint : DInt; Value_Byte : Byte; Value_USint : USInt; Value_Word : Word; Value_UInt : UInt; Value_DWord : DWord; Value_UDint : UDInt; Value_Real : Real; Value_Lreal : LReal; Len : Int; END_VAR BEGIN
REGION converter TO str #IsFloatType := FALSE; #FaultCode := 0; #Size := 30; #tempStr := ''; CASE TypeOfElements(#Value) OF SInt: VariantGet(SRC := #Value, DST => #Value_Sint); VAL_STRG(IN := #Value_Sint, SIZE := #Size, PREC := 0, FORMAT := W#16#0000, P := 1, OUT => #tempStr); Int: VariantGet(SRC := #Value, DST => #Value_Int); VAL_STRG(IN := #Value_Int, SIZE := #Size, PREC := 0, FORMAT := W#16#0000, P := 1, OUT => #tempStr); DInt: VariantGet(SRC := #Value, DST => #Value_Dint); VAL_STRG(IN := #Value_Dint, SIZE := #Size, PREC := 0, FORMAT := W#16#0000, P := 1, OUT => #tempStr);
Byte: VariantGet(SRC := #Value, DST => #Value_Byte); #Value_USint := #Value_Byte; VAL_STRG(IN := #Value_USint, SIZE := #Size, PREC := 0, FORMAT := W#16#0000, P := 1, OUT => #tempStr); USInt: VariantGet(SRC := #Value, DST => #Value_USint); VAL_STRG(IN := #Value_USint, SIZE := #Size, PREC := 0, FORMAT := W#16#0000, P := 1, OUT => #tempStr); Word: VariantGet(SRC := #Value, DST => #Value_Word); #Value_UInt := #Value_Word; VAL_STRG(IN := #Value_UInt, SIZE := #Size, PREC := 0, FORMAT := W#16#0000, P := 1, OUT => #tempStr); UInt: VariantGet(SRC := #Value, DST => #Value_UInt); VAL_STRG(IN := #Value_UInt, SIZE := #Size, PREC := 0, FORMAT := W#16#0000, P := 1, OUT => #tempStr); DWord: VariantGet(SRC := #Value, DST => #Value_DWord); #Value_UDint := #Value_DWord; VAL_STRG(IN := #Value_UDint, SIZE := #Size, PREC := 0, FORMAT := W#16#0000, P := 1, OUT => #tempStr); UDInt: VariantGet(SRC := #Value, DST => #Value_UDint); VAL_STRG(IN := #Value_UDint, SIZE := #Size, PREC := 0, FORMAT := W#16#0000, P := 1, OUT => #tempStr);
Real: #IsFloatType := TRUE; VariantGet(SRC := #Value, DST => #Value_Real); VAL_STRG(IN := #Value_Real, SIZE := #Size, PREC := 6, FORMAT := W#16#0000, P := 1, OUT => #tempStr); LReal: #IsFloatType := TRUE; VariantGet(SRC := #Value, DST => #Value_Lreal); VAL_STRG(IN := #Value_Lreal, SIZE := #Size, PREC := 15, FORMAT := W#16#0000, P := 1, OUT => #tempStr); ELSE // other data type #FaultCode := 01; RETURN; END_CASE;
IF ENO = FALSE THEN #FaultCode := 02; //str too short OR Size too small RETURN; END_IF;
END_REGION
REGION del space in front
WHILE #tempStr[1] = CHAR#' ' DO #tempStr := DELETE(IN := #tempStr, L := 1, P := 1); END_WHILE; //#tempStr := CONCAT(IN1 := ' ', IN2 := #tempStr);
END_REGION
REGION del 0 in tail IF #IsFloatType THEN #Len := LEN(#tempStr); WHILE #tempStr[#Len] = CHAR#'0' DO #tempStr := DELETE(IN := #tempStr, L := 1, P := #Len); #Len := LEN(#tempStr); END_WHILE; IF #tempStr[#Len] = CHAR#'.' THEN #tempStr := CONCAT(IN1 := #tempStr, IN2 := '0'); END_IF; END_IF; END_REGION
#Str := ''; #Str := #tempStr;
END_FUNCTION 本FC中用到了VARIANT类型。这个类型是非常好用的类型,可以大大简化复杂项目中PLC软件的结构。 如果各位同行觉得本篇有帮助,请点击“有帮助”。非常感谢。如果希望探讨其他领域的有关主题,也可以给我留言。 |
|
'Razor 至圣 经验值:24975 发帖数:3350 精华帖:42 |
4楼
主题:回复:【实用FC系列】之一,数字转换为字符串坦率地讲,楼主的这个FC写得还有改善空间。 首先可以自行了解一下什么是子程序/函数的“逻辑内聚性”,官方的VAL_STRG指令就挺好用的。 其次,保留原代码风格的话,也是可以改进一下以下代码切片: //下方指令的IN完全可以使用公共tempIN代替,包括此整条指令都可以公用化 VAL_STRG(IN := #Value_UInt, SIZE := #Size, PREC := 0, FORMAT := W#16#0000, P := 1, OUT => #tempStr); 再次,使用CASE,难免会有部分代码是不会执行的“死代码”,在效率上有影响,另外variant的使用有副作用的。 胡言乱语,仅供参考。
少即是多
|