Simulink 字符串
当您要传递和操作文本时,可以在多个应用程序中使用字符串。例如,在对燃油控制系统建模时,您可以使用 "LOW"
或 "EMPTY"
等字符串,而不是使用枚举数据对燃油油位建模。Simulink® 字符串与 MATLAB® 字符串兼容。
Simulink 字符串是内置的信号数据类型。它们在 Simulink 编辑器中显示为 "strN"
(例如,最大长度为 N 个字符的字符串),或用 "string" 表示没有最大长度的字符串(动态字符串)。字符串长度范围可以在 1 到 32,766 个字符之间。
Simulink 字符串信号本质上是离散的。如果字符串信号具有连续采样时间,则模型在编译时会产生错误。
Simulink 处理字符串变量和表达式(如 "a" + "b")的方式与处理数值变量一样。字符串变量的值既可以是字符向量,也可以是 MATLAB 字符串。字符串变量可以存在于基础工作区、模型工作区和封装工作区中。
字符串文字用双引号 ("Hello"
) 或单引号 ('Hello'
) 指定。为了与 MATLAB 字符串保持一致,请使用双引号。字符串出现在端口和 Display 模块中,并具有双引号。
Simulink 字符串支持 ISO/IEC 8859-1 字符集的 256 个字符。这些字符是 Unicode 的前 256 个代码点。Simulink 不支持第一个字符 char(0)
("NULL"),如果字符串包含此字符,将返回错误。
当某个字符无法显示时,模块会存储实际信息并输出转义字符及该字符相关联的八进制值。例如,BREAK PERMITTED HERE
的十进制值控制字符是 130。模块将此控制字符显示为转义的八进制 \202
。ASCII to String 模块会返回 Unicode 字符集范围 0000-001F 和 007F-009F 中的转义八进制字符。
本主题介绍如何在 Simulink 中使用字符串,包括:
一系列可用的字符串模块和专用于字符串转换的模块
将字符串常量传递到其他字符串模块中
字符串中的空字符
没有最大长度的字符串
与 Stateflow® 的交互
生成的代码
限制
本主题还包括一些说明如何使用字符串模块的简单示例。本主题中的示例允许显示模块名称。要控制模块名称的显示,请在格式选项卡上,选择自动 > 隐藏自动模块名称。例如,您可以使用字符串模块来显示和提取坐标数据,并在字符串中查找模式。
要在模型中使用字符串,请使用下表:
操作 | 模块 |
---|---|
将 uint8 向量转换为字符串信号。 | |
根据格式参数和输入信号组成输出字符串信号。 | |
扫描输入字符串并将其转换为符合格式参数指定格式的信号。 | |
比较两个输入字符串。 | |
串联各个输入字符串以形成一个输出字符串。 | |
输出由字符串参数指定的字符串。 | |
返回文本字符串 str 中首次出现的模式字符串 sub 的索引。 | |
输出在输入字符串中的字符数。 | |
将字符串信号转换为 uint8 向量。 | |
将字符串信号转换为双精度信号。 | |
将字符串信号转换为单个信号。 | |
将输入字符串转换为枚举信号。 | |
从字符串信号中提取子字符串。 | |
将输入信号转换为字符串信号。 |
下列 Simulink 模块支持字符串。
模块 | 注释 |
---|---|
Bus Assignment | 非虚拟和虚拟。 |
Bus Creator | 非虚拟和虚拟。 |
Bus Selector | 非虚拟和虚拟。 |
Data Store Memory | — |
Data Store Read | — |
Data Store Write | — |
Data Type Duplicate | — |
Display | 使用双引号显示字符串。 |
From | — |
From Workspace | 不支持数据插值。 |
Goto | — |
Ground | 接地值为 |
In Bus Element | 包括根级。 |
Inport | 包括根级。 |
Manual Variant Sink | — |
Manual Variant Source | — |
Manual Switch | 没有混合的数值类型和字符串类型。如果有多个字符串,则模块使用最大大小的字符串或动态字符串。 |
MATLAB Function | — |
Merge | — |
Model | — |
Multiport Switch | 没有混合的数值类型和字符串类型。如果有多个字符串,则模块使用最大大小的字符串或动态字符串。 |
Out Bus Element | 包括根级。 |
Outport | 包括根级。 |
Probe | — |
Signal Editor | 不支持数据插值。 |
Signal Specification | — |
Subsystem(所有变体) | — |
Switch | 没有混合的数值类型和字符串类型。如果有多个,则模块使用最大大小的字符串或动态字符串。 |
Terminate Function | — |
Terminator | — |
Variant Source | — |
Variant Model | — |
Variant Subsystem | — |
Width | — |
字符串常量
要指定字符串常量,请使用 String Constant 模块。不要使用 Constant 模块,它不接受字符串。在 String Constant 模块中,在字符串参数中输入带双引号的字符串,如 "Hello!"
。这与在 Constant 模块的常量值参数中添加数值常量相同。
Simulink 字符串和空字符
Simulink 字符串自动处理字符串终止。不要在字符串末尾使用空终止符。如果 Simulink 在字符串中的任何位置检测到空字符,它会产生错误。Simulink 在仿真和代码生成过程中处理字符串的方式如下所示:
在仿真过程中,模型可进行仿真。您不需要进行任何其他操作。
在 C 代码生成过程中,软件会在字符串的末尾添加空终止符。例如,如果字符串缓冲区大小为 10,实际字符串值为
"AB"
,则生成的代码中的第三个字符是空终止符。
字符串数据类型
字符串模块会根据需要创建并使用字符串数据类型,例如,当模块要输出某字符串类型时。您可以在不指定最大字符长度的情况下创建字符串。我们将没有最大字符长度的字符串称为动态字符串。
要为支持字符串的模块创建字符串数据类型,您可以:
使用 Simulink 模块的信号属性选项卡上的输出数据类型或数据类型参数。
要创建没有最大字符长度的字符串数据类型,请指定字符串。此操作创建动一个动态字符串。
要创建具有最大字符长度(如
100
)的字符串数据类型,请输入stringtype(100)
。您还可以在 MATLAB 命令行上使用stringtype
函数来创建字符串数据类型。从 R2024a 开始,字符串数据类型的最大长度支持符号表达式。有关符号维度的详细信息,请参阅Implement Symbolic Dimensions for Array Sizes in Generated Code (Simulink Coder)。
但是,以下限制适用于使用符号表达式作为最大长度的字符串数据类型。
Stateflow 模块、MATLAB Function 模块和 MATLAB System 模块不支持使用符号表达式作为最大长度的字符串数据类型。
具有固定采样时间的模块(如 String Constant 模块)不支持使用符号维度作为最大长度的字符串数据类型。
将
set_param
函数与OutDataTypeStr
参数结合使用,例如:set_param(gcb,'OutDataTypeStr','stringtype(100)')
此函数创建一个最大长度为 100 个字符的字符串数据类型对象。字符串类型长度范围可以在 1 到 32766 个字符(包括二者)之间。
例如,使用 String Constant 模块创建字符串时,将其输出数据类型参数设置为 stringtype(31)
,即可创建一个数据类型为 str31
的字符串。31 是字符串可以包含的最大字符数。
总线对象中的字符串
要使用类型编辑器将 Simulink.Bus
对象的元素配置为接受字符串,请为 Simulink.BusElement
对象的 DataType 参数输入字符串类型。例如,要指定最大字符长度为 10 的字符串数据类型,请输入 stringtype(10)
。模式参数会相应地更新。要指定具有可变长度的动态信号,请输入 string
。您可以为总线元素创建混合使用的数值和字符串对象。有关使用类型编辑器创建 Bus
和 BusElement
对象的详细信息,请参阅类型编辑器。
字符串和生成的代码
对于字符串和生成的 C
和 C++
代码,需要注意下列事项。
动态字符串数据类型的仿真和生成的 C
代码之间的差异
使用动态字符串数据类型的模块的仿真与生成的 C
代码在以下方面有所不同:
string
数据类型的信号在仿真期间具有动态大小。换句话说,字符串的大小可能在 0 到 32766 之间变化。然而,在生成的C
代码中,代码生成器将字符串存储为固定大小的char_T
数组。因此,在生成的C
代码中,字符串的大小受到固定缓冲区大小的限制。软件会截断多余的字符,并在末尾插入空终止符(例如,在 String Concatenate 模块的输出端)。代码生成器以
C
样式的双引号字符串形式生成字符串不变量(参数或信号)。字符串数据类型的信号的默认缓冲区大小为 256 字节(最多包含 255 个 8 位 ASCII 字符)。要更改此缓冲区大小,请使用 Buffer size of dynamically-sized string (bytes) (Simulink Coder) 配置参数。
要覆盖单个字符串信号的模型范围的设置,请使用
stringtype(N)
作为信号数据类型。在生成的C
代码中会为此数据类型的信号分配一个N+1
字节的缓冲区(N 个字符加上一个空终止符)。当字符串存储为与仿真具有相同的动态行为的
std::string
对象时,仿真和生成的C++
代码没有区别。
C++
代码生成 String 库
对于 C++
代码生成,std::string
库适用于具有 Embedded Coder™ 许可证的基于 ERT 的目标。有关详细信息,请参阅Generate Code for String Blocks by Using the Standard C++ String Library (Embedded Coder)。
字符串数据类型转换
您无法使用 Data Type Conversion 模块将字符串数据类型转换为其他数据类型,反之亦然。在这种情况下,请使用下列字符串转换模块。
要进行的转换 | 模块 |
---|---|
字符串信号转换为 uint8 向量信号,同时保留 ASCII 字符 | |
Uint8 向量信号转换为字符串信号 | |
字符串信号转换为数值信号双精度数据类型 | |
字符串信号转换为数值信号单精度数据类型 | |
字符串信号转换为枚举信号数据类型 | |
输入信号转换为字符串信号 |
将字符串转换为 ASCII 代码并转换回字符串
将下列模块添加到模型中:
String Constant
String to ASCII
ASCII to String
两个 Display 模块
连接模块,如下所示。
在 String Constant 模块中,输入一个字符串,如
"Hello!"
。在 String to ASCII 模块中,将最大字符串大小更改为 10。
仿真模型并观察 Display 模块的内容。
Display1 显示
Hello!
已转换为其 ASCII 等效形式。例如,72
是H
的 ASCII 等效形式,33
是!
的 ASCII 等效形式。Display1 用零(空字符)填充剩余空间以达到最大字符串长度 10。
在 ASCII to String 模块将 ASCII 代码重新转换为字符串后,显示画面中显示
Hello!
。
将字符串转换为枚举数据类型
将下列模块添加到模型中:
String Constant
String to Enum
Display
连接模块,如下所示。
在 String Constant 模块中,输入一个字符串,如
"Hello!"
创建一个名为
BasicStrings
的 Simulink 枚举类,并将其存储在当前文件夹中,文件名为BasicStrings.m
,例如:classdef BasicStrings < Simulink.IntEnumType enumeration Hello(0) Red(1) Blue(2) end end
在 String to Enum 模块中,输入枚举类为
Enum: BasicStrings
。仿真模型并观察 Display 模块的内容。
显示和提取坐标数据
此示例说明如何使用 Compose String 和 Scan String 模块将一组数据格式化并输出为地理坐标。Compose String 和 Scan String 模块基于 C 语言的 scanf
和 printf
函数,这些模块在概念上类似于 sprintf
和 sscanf
函数,主要区别在于这些函数适用于数组,而这些模块不适用于数组。有关字符串模块格式化的字符的详细信息,请参阅 Compose String 和 Scan String。
Compose String 模块基于合并的多个字符串和数值输入而构造一个字符串。使用格式参数格式化每个输入的输出,每个输入对应一个格式化操作符。每个格式化操作符以百分号 %
开头,后跟转换字符,例如 %f
生成定点输出。为了补充字符串输出,您还可以向格式设定中添加额外的字符以显示在输出中。
将下列模块添加到模型中:
六个 Constant 模块
一个 Compose String 模块
一个 Scan String 模块
七个 Display 模块
将 Constant 模块常量值更改为所示值,并连接这些模块。
在 Compose String 模块的格式参数中,输入以下格式设定:
'%g° %g'' %f" N, %g° %g'' %f" W'
%g
和%f
格式化操作符将数值输入转换为浮点值。%g
是%f
的简短版本。度符号 (°)、N、W 和
'
是要显示在输出字符串中的补充字符串。
Compose String 模块按输入顺序合并输出,根据其格式化操作符对每个输入进行格式化,添加额外的字符串,并输出字符串,再按照指示进行格式化,然后用双引号 (
"
) 引起来。在 Scan String 模块的格式参数中,输入以下格式设定:
'%g° %g'' %f" N, %g° %g'' %f" W'
%g
和%f
格式化操作符将数值输入转换为浮点值。%g
是%f
的简短版本。度符号 (°)、N、W 和
'
是要显示在输出字符串中的补充字符串。
Scan String 模块读取其输入,根据转换设定指定的格式进行转换,并将结果以标量形式返回。该模块根据其转换设定格式化每个输出。它忽略紧挨在转换设定符前面或后面的指定文本。
在字符串中查找模式
要在字符串中查找模式,请使用 String Find 模块。
将下列模块添加到模型中:
两个 String Constant 模块
String Find
一个 Display 模块
连接模块,如下所示。
在第一个 String Constant 模块中,输入一个字符串,如
"Hello!Goodbye!"
。将此模块连接到 String Find 模块的 str 输入端口会使 String Find 模块在此字符串中寻找模式。
在第二个 String Constant 模块中,输入要在第一个 String Constant 字符串中寻找的字符串(或模式),例如
"Goodbye!"
。将此模块连接到模块的 sub 输入端口意味着 String Find 从 str 输入中寻找此模式。
仿真模型并观察 Display 模块的内容。对于本示例,模块显示
7
,这是字母G
的位置。
提取字符串
要从源字符串中提取一个字符串,请使用 Substring 模块。此示例使用 在字符串中查找模式 中所述的模型。
向该模型添加一个 Substring 模块。
在 Substring 模块中,选择 Output string from 'idx' to end 参数。设置此参数将提取从 idx 端口上的位置输入开始到字符串末尾的字符串。
如图所示连接新模块。
仿真模型并观察 Display 模块的内容。对于本示例,模块显示
"Goodbye!"
,这是提取的从 idx 开始到字符串末尾的子字符串。
获取关键字后的文本
此示例说明使用 Simulink 字符串模块的基本字符串操作。
对如下所示的模型进行仿真。
通过观察可知,该模型执行了以下任务:
使用 String Constant 模块创建两个字符串
"beginning middle end"
和"middle"
。查找
"middle"
(idx) 的第一次出现处,并将第一个字母的位置 (11
) 与"middle"
的长度 (7
) 相加。它使用 String Find 和 String Length 模块。从
"beginning middle end"
提取子字符串,该子字符串从"middle"
的末尾 (idx+string length = 18
) 开始,即字符串"end"
。它使用 Substring 模块。将
"end"
的计算值与实际字符串"end"
进行比较,返回布尔值"1"
。它使用 String Constant 和 String Compare 模块。将布尔值
"1"
转换为其字符串等效形式"true"
。它使用 To String 模块。
要在模型中查看字符的位置,请为 String Find 和 String Length 模块的输出各添加一个 Display 模块,并对其进行仿真。
更改现有模型以使用字符串
除了在新模型中使用字符串之外,您还可以更新现有模型以使用字符串。使用字符串可以简化模型,使其更容易理解。
例如,在旧模型中,您可能使用了枚举数据类型在模型中表示或传递文本。容错燃油控制系统建模 示例模型 sldemo_fuelsys
在多个区域中枚举常量来处理文本数据。
在 sldemo_fuelsys/fuel_rate_control/control_logic
中,Stateflow 图使用枚举的数据来指示燃油油位。
在 sldemo_fuelsys/fuel_rate_control/airflow_calc
中,为了检测燃油是否不足,该模型使用 Enumerated Constant 和 Relational Operator 模块。
您可以通过以下方式使用 String Constant 和 String Compare 模块:
将 String Constant 的字符串参数设置为
LOW
。使用 String Compare 模块检测
LOW
是否来自模型的另一部分。
您可以将字符串与枚举常量结合使用,而不是删除枚举常量的所有实例。这样,您就可以增量迁移模型以使用字符串。在 sldemo_fuelsys/fuel_rate_control/fuel_calc/feedforward_fuel_rate
中,Multiport Switch 模块接受四个枚举的数据输入。
如果 fuel_mode 端口输出字符串,您可以将该字符串转换为枚举的数据类型,以支持此模型中 Constant 模块的输出。
解析 NMEA GPS 文本消息
此示例说明如何使用 Simulink® 字符串模块解析 NMEA GPS 格式的文本消息。
概述
此模型说明如何使用 Simulink® 提供的字符串数据类型和模块来读取输入文本消息并提取数值和文本数据。
读取消息标头并转换为枚举
Simulink® 提供 String To Enum 模块以将字符串转换为对应的枚举值。在该模型中,标题字符串 "RMB" 转换为 NMEASentence.RMB。
使用 Scan String 模块解析文本消息
解析文本消息的一种方法是使用 Scan String 模块。它的作用类似于 C 和 MATLAB® 中的 sscanf
函数。
解析具有固定字段宽度的文本消息
当文本消息的每个数据字段具有固定宽度时,可使用 Simulink® 提供的模块来按索引拆分字符串。在拆分字符串后,可以单独处理每个字段。
Simulink 字符串限制
当前不支持以下功能。
类别 | 限制描述 | 解决方法 |
---|---|---|
字符串数组 | 不支持字符串数组。 | 仅将字符串用作标量。 |
Unicode 字符 | Simulink 字符串不支持整个 Unicode 字符集。 | Simulink 字符串支持 ISO/IEC 8859-1 字符集的 256 个字符(基本 Latin 和 Latin-1 补充)。这些字符是 Unicode 的前 256 个代码点。 |
MATLAB S-Function | 用此模块创建的自定义模块不支持字符串。 | — |
Constant, Initial Condition | 这些模块不适用于处理字符串。 | 使用 String Constant 模块。 |
Switch、Multiport Switch、Switch Case 和 If 模块的控制输入 | Switch 模块的控制输入不接受字符串。 | 使用这些模块的数据输入。 |
|
| — |
|
| — |
Data Type Conversion 模块 | 不要使用 Data Type Conversion 模块转换字符串。 | 使用字符串转换模块 |
To File 模块 | 使用 To File 模块加载字符串。 | — |
Scope 和 Spectrum Analyzer 模块,逻辑分析仪 | Scope 和 Spectrum Analyzer 模块以及逻辑分析仪不显示字符串。 | 使用 Stateflow 中的 Display、Simulation Data Inspector 或 Sequence Viewer。 |
另请参阅
模块
- Compose String | Scan String | String Compare | String Concatenate | String Constant | String Find | String Length | String to Double | String to Single | String to Enum | String to ASCII | Substring | To String