每个编程语言都有自己的风格,有很多约定俗成的。在一个Team中,一个完整的大型设备是多人共同完成,以及后期的维护等等。这就需要将程序做到模块化,架构要清晰。在PLC的编程中,很多没有这个概念,但是在计算机高级语言的编程中,都比较注重这一点。你是在一个团队中工作,所以请考虑到你的同事,他们可能不会喜欢凌乱的变量定义与程序编写风格。所以至少有一个约定的规则。
我们要对创建的代码负责。做好这件事,然后为你所创造和取得的成就感到骄傲!
就算当前项目完成以后,维护的人员接手以后,也能很轻松的
一、介绍
“B&R”的编程风格,如何用它写出高质量的程序,以生产、测试和记录高质量的源代码。
高质量代码的特征包括:
1、简单明了的架构和设计。
2、有很强可读性。
3、易于维护。
4、高复用性。
5、注释清晰。
6、减小程序Bug的存在。
本文将帮助您提高代码质量。如果您遵循这里列出的指导方针,您的代码应该具有合理的质量B&R程序,当然其它PLC或者编程语言也可以这样来做。但是最好遵循当前品牌自己的推荐定义方式和方法。
任何优秀软件的基础都是干净的架构和设计。在概念阶段花点时间,继续设计,直到你对软件概念满意为止。在编写代码之前,请注意本文档中讨论的概念和方法。
二、B&R的命名规则
良好的变量名和数据类型名是程序可读性的关键因素。所有的名字应该是描述性的,易于阅读。在复合名称中使用下划线或大写字母(不要将它们混在一起)来增强可读性,比如:
actPressure = actForce / pistonArea;
cmdCount++;
或者
act_pressure = act_force / piston_area;
cmd_count++;
标识符可以包含字母和数字,并且必须以字母开头。
不能使用保留关键字作为标识符。Automation Studio的帮助中可找到每种编程语言的保留关键字的完整列表。例如ST的关键字在帮助中的列表如下:
三、AS变量的定义/声明规则
如果客户没有给出不同的规范,强烈建议使用英语进行编码和注释,以便在国际上无故障地使用软件。在B&R,这一建议是强制性的。在创建变量中,尽量不要使用拼音的缩写,注释可根据使用场景用中文。
3.1 结构体变量
用户数据类型以大写字母开头,以后缀结尾’ _type ',在小写和大写字母之间可能是混合的。
TYPE
Recipe_type: STRUCT
base: UINT;
binder: UINT;
additive: USINT;
END_STRUCT;
MachineParams_type: STRUCT
speed: REAL;
pressure: REAL;
temperature: INT;
pRecipe: REFERENCE TO Recipe_type;
END_STRUCT;
END_TYPE
3.2 常量的声明
常量都是大写的。使用下划线_来增强可读性
VAR CONSTANT
STEP_CONDITIONING: USINT := 23; (* [-] )
HEATING_TIME_OUT: UINT := 5000; ( [s] )
MAX_PRESSURE: REAL := 6.7e+006; ( [Pa]*)
END_VAR
这些规则也适用于由#define预处理器指令和C源代码中的enum语句定义的常量。请注意,通过#define指令和enum语句的声明在C代码的作用域内是局部的!
3.3 局部变量
局部变量以小写字母开头。大写字母(或下划线“_”)仅用于增强可读性
VAR
machineStep: USINT; (* [-] )
actPressure: REAL; ( [bar] )
avgTemperature: INT; ( [0.1°C] )
END_VAR
VAR
machine_step: USINT; ( [-] )
act_pressure: REAL; ( [bar] )
avg_temperature: INT; ( [0.1°C] *)
END_VAR
3.4全局变量的声明
全局变量以前缀“g”开头,后跟大写字母或者“_”:
VAR
gHeaterOn: BOOL;
gActCmd: Cmd_typ;
gCmdCount: UINT;
END_VAR
这个约定是为全局变量保留的——不要将它用于非全局变量。这样的话,在别人看程序时,很清楚明了就知道这是个一个全局变量还是一个局部变量了。就具备很强的可读性。
3.5 指针的声明
本地指针以前缀“p”开头,后跟大写字母或“”。全局指针以前缀“gp”开头,后跟大写字母或“”:
VAR
pActRecipe: REFERENCE TO Recipe_type;
END_VAR
VAR
gpActRecipe: UDINT;
END_VAR
上面的约定是为指针保留的——不要将它用于其他变量。
全局指针的数据类型为“UDINT”,因为IEC不支持指向通用数据类型的指针。将全局指针转换为通用本地指针,以访问结构成员:
pActRecipe = (Recipe_type*)gpActRecipe;
actSpeed = pActRecipe->speed;
3.6 硬件连接变量的声明
硬件连接变量就是分配给硬件I/O点的变量以定义
I / O点类型:
| 前缀 | 说明 |
|---|---|
| di | 数字量输入 |
| do | 数字量输出 |
| ai | 模拟量输入 |
| ao | 模拟量输出 |
前缀后面跟一个大写字母或’ _ ’ ,例如:
VAR diEmergencyOff: BOOL; doSolidStateOn: BOOL; aiActTemp: INT; (* [0.1°C] *) aoValvePos: INT; (* 0=closed, 32767=open *) END_VAR
这个约定是为HW连接变量保留的——不要将它用于其他变量。
3.7 C本地变量
在C源代码中定义的变量在其定义范围之外是不可见的——您不能在监视或跟踪窗口中看到它们。
Recipe_type* pPrevRecipe = 0;
USINT cmdCount = 0;
REAL actSpeed = 0; /* [m/s] */
如果没有声明为“静态”,则在每次执行C例程(因此非remanent)且未初始化时,从堆栈中分配它们!因此,明智的做法是在声明中初始化它们(如上所述)。
3.8 功能块实例
Function实例的命名应该包含Function块的名称:
VAR
valveSwitchTON: TON_type;
solidStateTOF: TOF_type;
pressureLCPID: LCPID_type;
END_VAR
四、代码格式
适当的缩进是代码可读性的关键因素,也是所有程序中必须的!缩进背后的整个思想就是清晰地可视化控制块的开始和结束位置。较大的缩进尺寸(6或8个字符)使代码结构更容易看到,而较小的缩进尺寸(2或4个字符)则节省了屏幕右侧的空间。我们建议缩进大小为4个字符。如果你有自己的习惯,选择另一个你喜欢的缩进大小,并坚持下去。
4.1括号的使用(C)
或者下面这种方式。一般推荐第一种,第二种是会C++或者Java的人可能比较常用,根据自己熟悉的方式来即可。
4.2空格的使用
为了便于阅读,请在每个操作符之前和之后添加空格:
4.3代码对齐方式
4.4程序设计
4.4.1 硬件I/O点的变量
在编写程序中,尽量避免一直使用硬件I/O对应的直接变量,我们应该使用一个中间变量,当外部I/O故障时,我们可以很方便更改他,而不用重复进行全部替换。
4.4.2 模块间通讯变量
模块间的通信必须使用全局数据结构来实现。因此,它需要特别小心地设计。请注意通信数据结构的适当命名。