简介:在工业自动化领域,西门子TIA Portal编程组件STEP 7 Professional(博图)用于开发PLC程序。本文介绍了如何用SCL语言在博图中创建一个记录和追踪设备状态的FB功能块,特别是时间戳功能块的设计与实现。时间戳功能块对于分析设备周期时间至关重要,有助于优化生产效率和提升设备性能。文章详细阐述了创建此FB的步骤,包括变量声明、初始化、主程序循环、输入输出接口和程序结束时的处理。这使得功能块可以被集成到复杂程序中,并通过博图项目重复使用,从而提高了代码的模块化和可维护性。
1. 西门子TIA Portal与PLC编程概述
西门子TIA Portal(Totally Integrated Automation Portal)是一个先进的工程集成自动化平台,为设计、编程和测试自动化系统提供了一个统一的工程环境。在本章节中,我们将介绍TIA Portal与PLC(可编程逻辑控制器)编程的基础知识,为读者打造一个坚实的理解基础。
1.1 PLC编程的重要性
可编程逻辑控制器(PLC)是现代工业自动化不可或缺的核心组件。它们在制造业、运输、能源等众多行业中,用来控制机械和生产流程。通过编程,PLC可以执行逻辑运算、顺序控制、计时、计数和算术运算等操作,实现复杂的自动化任务。
1.2 TIA Portal的集成优势
TIA Portal提供了一个集成的开发环境,使工程师能够在同一个平台上完成从项目创建、配置和编程到模拟和诊断的所有任务。它支持多种西门子自动化产品,包括S7系列PLC、HMI(人机界面)和驱动器。这种集成化方法减少了项目中可能发生的错误,提高了开发效率和系统可靠性。
1.3 PLC编程语言
PLC编程支持多种语言,包括梯形图、功能块图、指令列表、结构化文本和顺序功能图。TIA Portal为这些语言提供了统一的编程和调试界面,简化了开发过程。掌握基础的PLC编程概念和语言特性,是利用TIA Portal进行高效开发的关键。
通过本章节的介绍,我们为理解接下来章节的深入探讨打下了基础,从博图软件的界面布局到SCL语言的应用,再到工站周期时间和代码维护性的优化策略,将一一展开。
2. STEP 7 Professional(博图)深入解析
2.1 博图软件的界面布局与功能模块
2.1.1 登录与配置环境设置
博图(TIA Portal)是西门子自动化与驱动技术部开发的一个集成自动化工程软件,是未来自动化工程软件的旗舰平台。在这个平台中,用户可以实现从配置硬件到编程、仿真、调试和维护的全过程工程设计。使用博图软件时,用户首先会面对登录界面,通常这个步骤是透明的,如果是第一次使用或者有多个版本的TIA Portal安装在一台电脑上,则需要进行相应的选择。
在登录界面之后,用户需要进行环境配置。环境配置对于提高开发效率至关重要,因为它涉及到软件操作的习惯、功能区的显示偏好、快捷键的设置等。在软件的"选项"菜单下,用户可以详细设置包括项目视图选项、语言、安全设置、自动备份和更新服务器在内的多种环境配置参数。
2.1.2 主要工作区的介绍与操作
博图软件的核心工作区包括项目树、设备视图、程序块编辑器和属性窗口等。项目树显示了整个自动化项目的结构,包含所有设备、程序块和通信网络等。设备视图则是对所选择的设备进行更详细的配置,如设置CPU属性、配置I/O模块等。程序块编辑器用于编写和编辑各种程序块(例如FB、FC、SCL、OB等)。属性窗口在选择了设备或者程序块后,会显示相应的属性和参数设置选项,是进行个性化设置的关键界面。
在操作这些工作区时,用户需要熟悉界面布局及工具栏上各种功能按钮和菜单的使用。例如,通过拖放的方式在设备树中添加和配置硬件组件,使用程序块编辑器编写代码,并通过属性窗口设置程序块的具体参数。熟练掌握这些操作可以让开发者在进行自动化工程设计时更加得心应手。
2.2 博图软件的项目管理
2.2.1 创建和管理项目结构
项目管理是博图软件的一个重要功能,它不仅涉及到如何创建项目,还包括项目结构的管理。创建项目时,用户首先需要在TIA Portal中选择“新建项目”并命名项目,接着选择合适的PLC型号和配置相应的硬件。创建完成后,用户将进入项目树视图,这是一个可以直观地查看整个自动化项目的层次结构的地方。
项目树的管理对于维护项目的清晰和有序至关重要。用户可以按需添加和删除程序块,创建子文件夹来组织程序块。为了方便不同开发者之间协作,还可以通过项目树来设置不同人员的访问权限,以及利用版本控制功能来管理项目的变更历史。
2.2.2 版本控制和备份策略
版本控制是软件开发中非常重要的一个环节,特别是在多人协作的项目中。在TIA Portal中,用户可以启用Git或者集成的版本控制系统(例如S7-VCS)来进行版本管理。每个项目的提交、分支、合并等操作都会被版本控制系统追踪。这不仅可以帮助团队成员之间有效地协作,还可以在遇到问题时迅速回滚到之前的某个工作状态。
除了版本控制,合理的备份策略也是项目管理的一个重要组成部分。TIA Portal提供了自动备份功能,用户可以设置备份频率、备份文件的保存位置等。对于关键项目或重要改动,还可以手动创建备份点,确保在发生错误时能够快速恢复到稳定状态。
2.3 博图软件的编程和调试工具
2.3.1 编程工具的选择与应用
在自动化工程中,编程是实现功能逻辑的关键步骤。博图软件提供了多种编程语言的选择,如梯形图(LAD)、功能块图(FBD)、结构化控制语言(SCL)和指令列表(STL),以及高级编程技术如面向对象编程(OOP)的SCL扩展。
选择合适的编程工具是实现高效开发的第一步。对于简单的逻辑控制,梯形图和功能块图因其直观和易于理解而受到青睐。对于复杂的算法和数据处理,结构化控制语言(SCL)提供了一种更接近传统编程语言的语法。而面向对象编程(OOP)的SCL扩展则允许用户以模块化的方式设计和实现功能。
在应用这些编程工具时,需要理解每种语言的特点和适用场景。例如,梯形图适合实现硬件控制逻辑,而SCL则适合实现数据运算和复杂算法。用户应根据实际需求和自身熟练程度选择合适的编程工具。
2.3.2 调试工具的使用与技巧
编程完成后,调试阶段对于确保程序按预期运行至关重要。TIA Portal提供了多种调试工具,包括断点、变量监视、程序运行控制(如单步执行和全速执行)以及性能分析工具等。调试工具的使用可以大大简化故障诊断和性能优化的过程。
调试的目的是发现并修正程序中的错误,优化程序运行效率。断点的设置可以暂停程序执行在特定位置,以便用户检查变量值和程序流程。变量监视功能可以让开发者实时查看程序运行时的数据变化,有助于快速定位问题。程序运行控制则允许开发者逐步执行程序或让程序运行到下一个断点,这对于复杂的程序逻辑调试尤为重要。
在使用调试工具时,开发者应当掌握一些技巧,例如编写可测试的代码(编写易于设置断点和监视变量的代码)、使用函数调用堆栈来跟踪程序执行路径,以及合理使用日志输出来记录程序的关键操作。掌握这些调试技巧,将帮助开发者更有效地进行问题诊断和性能优化。
graph LR
A[开始调试] --> B[设置断点]
B --> C[单步执行]
C --> D[监视变量]
D --> E[全速运行]
E --> F[检查程序性能]
F --> G[分析日志输出]
G --> H[定位问题]
H --> I[优化程序]
I --> J[结束调试]
在实际的调试过程中,开发者应结合使用这些工具,通过逐步排除法来缩小潜在问题的范围,并最终解决问题。不断的实践和总结调试经验,将会极大提升调试效率和软件质量。
3. SCL语言在PLC编程中的应用
SCL(Structured Control Language)语言是西门子TIA Portal中用于高级编程的一种文本编程语言,类似于Pascal或C语言。由于其结构化和模块化的特点,SCL语言在处理复杂算法和数据处理方面显得尤为强大。在本章节中,我们将详细介绍SCL语言的基本语法、高级特性以及编程实践。
3.1 SCL语言基础与语法
3.1.1 SCL语言结构与数据类型
SCL语言具有清晰的结构化设计,允许程序采用嵌套的函数、过程和块。这对于大型的控制任务特别有用,因为它们可以将程序分割成可管理的部分。
SCL支持的数据类型包括基本数据类型和复合数据类型:
- 基本数据类型:Bool、Int、Real、Byte、Word、DWord等。
- 复合数据类型:Arrays、Structs和Enumerations等。
在编写SCL程序时,定义数据类型是编程的基础。例如,下面的代码段定义了一个结构体和一个数组:
TYPE MyStruct : STRUCT
Val1 : INT;
Val2 : REAL;
END_STRUCT;
TYPE MyArray : ARRAY [1..10] OF INT;
3.1.2 控制语句与程序设计
SCL提供了丰富的控制结构,如条件语句(IF-THEN-ELSE)、循环语句(FOR、WHILE)和开关语句(CASE)。这些控制结构使得程序能够根据不同的条件执行不同的代码路径。
控制语句通常用于实现程序逻辑的决策点。例如,下面的代码段演示了使用IF-THEN-ELSE语句来根据某个条件执行不同的代码块:
IF Condition THEN
// 执行当条件为真时的代码
ELSE
// 执行当条件为假时的代码
END_IF;
3.2 SCL语言高级特性
3.2.1 复杂数据结构的操作
SCL不仅支持简单的数据结构,还支持复杂的结构如动态数组和记录。SCL语言中的动态数组大小可以在程序运行时进行调整,这对于那些需要在运行时根据输入数据动态分配内存的应用场景非常有用。
3.2.2 内置函数库及其应用
SCL语言提供了一个丰富的内置函数库,这些函数可以执行从基本数学运算到复杂的字符串处理等各种操作。掌握这些函数对于高效编程是至关重要的。
例如,数学函数库中常见的Sqrt()函数可以计算一个数的平方根:
Val := Sqrt(X);
3.3 SCL语言编程实践
3.3.1 简单实例操作与分析
为了加深对SCL语言的理解,我们来构建一个简单的实例。假设我们需要编写一个简单的计算器,它可以执行加法操作。
FUNCTION Add : INT
VAR_INPUT
A : INT;
B : INT;
END_VAR
BEGIN
Add := A + B;
END_FUNCTION
在这个函数中,我们定义了两个输入参数A和B,然后将它们相加并返回结果。
3.3.2 SCL语言在实际项目中的应用案例
在实际的工业项目中,SCL语言通常用于执行特定的算法或数据处理任务。比如,在一个生产过程中,可能需要根据多个传感器的数据来计算最优的机器运行参数。
下面的代码段展示了一个真实应用案例,它使用SCL语言来计算平均值和标准差:
FUNCTION ComputeStatistics : VOID
VAR_INPUT
DataArray : ARRAY [1..100] OF REAL;
END_VAR
VAR
Sum : REAL := 0;
Mean : REAL;
StandardDeviation : REAL;
i : INT;
END_VAR
FOR i := 1 TO 100 DO
Sum := Sum + DataArray[i];
END_FOR;
Mean := Sum / 100;
FOR i := 1 TO 100 DO
StandardDeviation := StandardDeviation + POWER(DataArray[i] - Mean, 2);
END_FOR;
StandardDeviation := SQRT(StandardDeviation / 100);
// 输出计算结果到日志文件或者其他需要的地方
END_FUNCTION
通过这个案例,我们可以看到SCL语言如何在复杂的数据处理和算法实现中发挥作用。程序首先计算输入数组的总和,接着得出平均值,然后通过一个循环计算所有数据与平均值差异的平方和,最后计算出标准差。
在本章节中,我们初步了解了SCL语言的语法和结构,以及如何在实际项目中应用SCL。在下一章节中,我们将进一步探讨功能块(FB)的创建与应用,以及如何在PLC编程中更有效地使用这些强大的工具。
4. 功能块(FB)的创建与应用
4.1 功能块的基本概念与优势
4.1.1 功能块定义与功能分类
功能块(Function Blocks, FB)是可重复使用并带有参数的程序模块,在工业自动化领域中,它们为PLC编程提供了极大的灵活性。功能块由一组用于执行特定任务的程序代码组成,包括输入输出参数、局部变量及程序代码。功能块可以分类为输入输出块(I/O Blocks)、算法块(Algorithm Blocks)和逻辑块(Logic Blocks),每个分类在控制系统中发挥不同的作用。
输入输出块负责与外部设备的接口,例如读取传感器数据或控制执行器。算法块执行数学和逻辑运算,例如PID控制、滤波器设计等。逻辑块则负责实现更高级的决策和控制逻辑。正确地使用功能块分类,可以提高程序的可读性和维护性。
4.1.2 功能块在PLC程序中的作用
在PLC程序中,功能块充当构建模块的角色,用于简化程序设计和提高代码重用性。通过使用功能块,开发者可以将复杂的控制逻辑封装起来,从而在主程序中通过简单的调用来使用这些复杂逻辑,减少代码冗余,提升程序结构的清晰度。
功能块的另一个重要作用是简化程序的调试和维护过程。由于功能块是独立的程序模块,因此当一个功能块出现问题时,只需对该功能块进行调试,而不需要在整个程序中追踪错误。此外,功能块的参数化设计使得程序更加灵活,能迅速适应不同的工况需求。
4.2 功能块的创建步骤详解
4.2.1 功能块接口参数配置
创建一个功能块首先需要定义其接口参数。在TIA Portal中,创建功能块的第一步是选择合适的模板并为其命名。之后,在功能块的编辑界面中,需要详细配置其输入、输出和输入/输出参数。
输入参数允许外部传入值以执行功能块内的操作,输出参数允许功能块将结果返回给调用它的主程序或其他功能块。输入/输出参数则同时具有输入和输出的功能。参数配置时要注意数据类型的一致性,例如整型、实型、布尔型等,以及是否为数组或引用类型。
FUNCTION_BLOCK FB_Counter
VAR_INPUT
Increment : INT; // 输入参数,用于计数增加的值
END_VAR
VAR_OUTPUT
CounterValue : INT; // 输出参数,计数结果
END_VAR
VAR
Count : INT := 0; // 局部变量,用于实际计数
END_VAR
CounterValue := Count;
Count := Count + Increment;
END_FUNCTION_BLOCK
4.2.2 功能块内部逻辑实现
配置完接口参数后,接下来就是实现功能块的内部逻辑。这个部分是功能块的核心,根据功能块的类型和预期功能,开发者将编写相应的代码,如控制算法、数据处理、逻辑判断等。
例如,在一个计数器功能块中,内部逻辑将包括对输入参数的处理,并更新计数器的值。在这个过程中,需要注意逻辑的健壮性和异常处理,确保功能块在各种情况下都能稳定工作。
// 伪代码示例
IF Increment < 0 THEN
Increment := 0; // 确保输入值不会导致计数器减少
END_IF
Count := Count + Increment;
CounterValue := Count;
内部逻辑中还可能包含对特定事件的响应,如计时器到时或外部触发信号。这要求功能块能够与其他PLC系统组件如中断、定时器等协同工作。因此,功能块的内部实现需要兼顾效率和灵活性。
4.3 功能块的实例应用与测试
4.3.1 功能块与主程序的交互测试
功能块创建完成后,必须进行充分的测试以确保其正确性和稳定性。测试的第一步是在测试环境中模拟与主程序的交互。这需要设置合适的输入参数,然后执行功能块并观察其输出结果是否符合预期。
在TIA Portal中,可以使用内置的模拟器工具来设置测试参数,并监视功能块的执行。开发者需要记录不同的输入情况以及对应的输出结果,验证功能块在各种工况下的响应是否正确。
4.3.2 功能块参数调优与维护
在实际应用中,功能块可能需要根据实际工况进行参数调优。例如,在上述的计数器功能块中,根据不同的计数速度和用途,可能需要调整其计数的初始值或增加一些额外的处理逻辑。
参数调优过程可能需要反复试验和调整。在TIA Portal中,开发者可以利用在线调试功能实时更改功能块的参数,并观察结果的变化,直至功能块的表现完全符合实际应用需求。此外,维护功能块时还需考虑代码的可读性和可维护性,必要时进行重构。
// 示例:修改计数器功能块,增加安全检查
FUNCTION_BLOCK FB_SafeCounter
VAR_INPUT
Increment : INT;
END_VAR
VAR_OUTPUT
CounterValue : INT;
END_VAR
VAR
Count : INT := 0;
END_VAR
IF Increment < 0 THEN
Increment := 0; // 安全检查
END_IF
IF Count > UpperLimit THEN // UpperLimit为新增的安全限制参数
Count := UpperLimit;
END_IF
Count := Count + Increment;
CounterValue := Count;
END_FUNCTION_BLOCK
功能块在实际项目中的应用案例将展示如何将功能块融入到整个PLC程序中,以解决实际的工业自动化问题。通过功能块的创建和测试,我们可以看到它们在提高代码复用性、简化程序设计和提升系统稳定性方面的巨大优势。
5. 时间戳功能块的设计与实现
时间戳功能块是PLC编程中经常使用的一个功能,它可以帮助我们记录和处理系统时间,对于需要进行时间控制和监控的自动化系统来说,是非常重要的。本章节将详细介绍时间戳功能块的设计和实现过程,并提供实例应用和测试方法,以及性能优化与故障排查的技巧。
5.1 时间戳功能块的需求分析
5.1.1 时间戳功能的意义与作用
在自动化控制领域,准确的时间记录对于系统的工作状态监控、故障诊断以及性能优化等都是非常关键的。时间戳功能块能够提供一个精确的参考时间点,帮助程序员记录特定事件发生的时间,或者程序执行的某个阶段。这样可以保证数据的时间一致性,对于实现复杂的控制策略和日志记录是必不可少的。
5.1.2 系统时间与程序时间的同步问题
在分布式控制系统中,不同节点间的时间同步也是一个挑战。时间戳功能块可以辅助解决这个问题,因为我们可以使用它来对不同PLC之间的事件时间进行同步校对。同步问题对于多任务协调、数据记录的一致性以及后续的分析处理至关重要。
5.2 时间戳功能块的具体实现
5.2.1 功能块的输入输出接口设计
时间戳功能块需要设计为能够接收外部触发信号,并在该信号触发时,记录当前的系统时间。通常,这需要以下输入输出接口:
- 一个或多个触发信号输入,用于标记需要记录时间的事件。
- 时间戳输出,即记录下来的时间信息。
- (可选)一个控制信号输入用于启动或停止时间戳功能块。
在设计接口时,我们还需要考虑接口的类型(例如布尔型、整型或定时器等),以及如何通过这些接口精确地控制时间戳的记录时机和条件。
5.2.2 功能块内部的时间记录与处理算法
时间戳功能块的核心是能够处理并记录准确的时间信息。这通常涉及到以下算法或逻辑:
- 时间记录:需要记录的时间信息可以是PLC系统中的绝对时间或相对时间。绝对时间指的是PLC系统时钟中的具体时间点,而相对时间则是事件发生与某一基准点之间的时间差。
- 时间格式转换:根据需求,可能需要将时间信息转换为不同的格式,如将PLC中的时间数据转换为易于人类阅读的日期和时间格式。
- 时间同步:如果应用中有多个时间戳功能块,需要确保它们的时间数据在逻辑上是同步的,这可能需要一种内部算法来校正时间偏差。
5.3 时间戳功能块的测试与优化
5.3.1 功能块在不同工况下的测试方法
功能块的测试是确保其正确性和可靠性的关键步骤。在测试时间戳功能块时,可能需要模拟各种工况,包括但不限于:
- 正常工况测试:确保功能块能够在标准条件下准确记录时间。
- 极限条件测试:将功能块置于极端的输入条件下,例如高频触发或触发信号的抖动,以测试其稳定性和抗干扰能力。
- 多任务同步测试:在多任务环境下,多个时间戳功能块需要同时工作并保持同步,这需要特别测试以确保没有时间偏差。
- 系统重启与故障恢复测试:测试在PLC系统重启或故障后,时间戳功能块是否能够正确地继续其工作,不会丢失时间数据。
5.3.2 功能块性能优化与故障排查
功能块在实际应用中可能会出现性能瓶颈或故障。性能优化和故障排查是确保时间戳功能块长期稳定运行的重要步骤。一些可能的优化和排查步骤包括:
- 性能监控:监控功能块的性能指标,如处理时间、内存使用等。
- 代码剖析:使用专门的工具对功能块代码进行剖析,找出性能瓶颈。
- 日志分析:记录详细的操作和错误日志,帮助定位问题发生的原因。
- 硬件检查:确保PLC的硬件资源如时钟源等正常工作,不会影响时间戳的准确性。
- 软件更新:及时更新博图软件和功能块内部的算法,以适应系统升级或增强功能。
时间戳功能块的设计与实现是PLC编程中的一项基础且重要的技能。本章内容从需求分析入手,逐步深入到具体实现,再到测试与优化,给出了全面的指导和建议。通过仔细遵循本章的建议,PLC程序员可以高效地开发出稳定可靠的时间戳功能块,为复杂控制策略的实施提供有力的时间管理支持。
6. 工站周期时间(CT)与代码维护性
6.1 工站周期时间(CT)的基本概念
在自动化生产线中,工站周期时间(Cycle Time,CT)是指一个生产工站完成特定任务所需的平均时间周期。工站周期时间的精确度和可预测性对于整个生产线的效率至关重要。
6.1.1 工站周期时间的定义与测量
工站周期时间可以通过以下公式进行计算:
CT = (最大周期时间 + 最小周期时间) / 2
测量工站周期时间通常需要实时数据采集系统,如使用PLC采集传感器信号,记录工站开始和结束工作的时刻。
6.1.2 CT对系统性能的影响
工站周期时间的长短直接影响着生产效率和产能。周期时间过长会导致生产线的瓶颈,而周期时间过短可能会增加设备的磨损和故障率。因此,周期时间需要进行严格控制。
6.1.3 工站周期时间的测量方法
工站周期时间的测量可以通过以下步骤进行: 1. 设置传感器记录工站开始和结束的时间戳。 2. 在PLC程序中记录这些时间戳并计算周期时间。 3. 将测量数据传输到监控系统以进行进一步分析。
6.2 工站周期时间分析与优化策略
6.2.1 分析工站周期时间的方法
分析工站周期时间通常涉及以下步骤: 1. 收集历史周期时间数据。 2. 使用统计分析工具识别周期时间的波动和异常值。 3. 分析周期时间与生产线的其他参数之间的相关性。
6.2.2 优化工站周期时间的实践案例
在实践中,以下措施可以帮助优化工站周期时间: - 对生产流程进行重新规划,减少不必要的等待和移动时间。 - 应用预测性维护减少设备故障导致的停机时间。 - 优化PLC程序逻辑,减少不必要的处理时间。
6.3 变量声明、初始化与功能块的模块化设计
6.3.1 变量声明与初始化的重要性
在编程中,变量声明和初始化是基础步骤,它们确保了程序运行的稳定性和可靠性。未初始化的变量可能导致不可预测的程序行为,甚至造成系统崩溃。
6.3.2 功能块模块化设计的优势与实现方法
模块化设计可以显著提升代码的可读性和可维护性。功能块允许开发者将特定功能封装起来,便于复用和维护。模块化设计的实现方法包括: - 定义清晰的接口和参数。 - 使用功能块来实现特定的功能逻辑。 - 通过变量将功能块相互连接,构建复杂的程序结构。
6.4 提升代码维护性的最佳实践
6.4.1 代码重构与模块化编程原则
代码重构是改善代码质量而不改变其外部行为的过程。模块化编程原则要求开发者将程序分解为独立、可复用的模块。这些模块应该设计得具有单一职责,即每个模块只完成一个任务。
6.4.2 维护性提升案例分析与总结
案例分析可以揭示代码维护中常见的问题和改进方法。例如,通过重构一个功能块以减少其内部逻辑复杂性,可以提升维护效率。总结经验教训,并形成标准操作流程,有助于在未来的项目中提升代码质量。
在本章中,我们深入探讨了工站周期时间的计算、测量和优化方法。我们分析了变量声明与初始化的重要性,强调了功能块模块化设计的优势,并分享了提升代码维护性的最佳实践。通过这些策略和技术的应用,可以显著提升PLC系统的性能和可靠性,为自动化生产线提供稳定的支撑。
简介:在工业自动化领域,西门子TIA Portal编程组件STEP 7 Professional(博图)用于开发PLC程序。本文介绍了如何用SCL语言在博图中创建一个记录和追踪设备状态的FB功能块,特别是时间戳功能块的设计与实现。时间戳功能块对于分析设备周期时间至关重要,有助于优化生产效率和提升设备性能。文章详细阐述了创建此FB的步骤,包括变量声明、初始化、主程序循环、输入输出接口和程序结束时的处理。这使得功能块可以被集成到复杂程序中,并通过博图项目重复使用,从而提高了代码的模块化和可维护性。