技术论坛

 【实用FC系列】之一,数字转换为字符串

返回主题列表
作者 主题
yang9188
侠客

经验值:631
发帖数:44
精华帖:2
楼主    2025-09-23 10:07:06
主题:【实用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楼    2025-09-28 23:00:29
精华帖  主题:回复:【实用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的使用有副作用的。

胡言乱语,仅供参考。


少即是多
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。