OpenPLC源码分析(一)概述
OpenPLC项目由两个部分组成:Runtime和Editor,Editor没有开源,而Runtime的开源地址为:https://github.com/thiagoralves/OpenPLC_v3
首先做好准备工作(后来发现这些步骤都非必须的,可以忽略):
(1)VSCode配置C++环境:https://blog.xi-xu.me/Getting-Started-with-VS-Code-C/
(2)下载Keil5:https://mp.weixin.qq.com/s/RDXclumIiSAoLDSGIJ0_vQ
然后整体了解一下Runtime项目的整体架构,下图参考:https://blog.csdn.net/qq_37887537/article/details/81030534

我也画了一个架构图:

一、其他散落文件
-
.sh UNIX/LINUX操作系统的脚本文件
- .db 数据库文件
- .conf, .yml 配置文件
- .gitattributes 配置git系统
-
.gitignore 告诉git不要跟踪的文件
二、documentation
其中包含一个EtherNet-IP文件夹,其中有实现EtherNet/IP的所有相关文档
1、PCCC Documentation
PCCC.cpp会实现所有EtherNet/IP功能,这是有关的技术文档
2、Definition of Done
OpenPLC的期望功能及完成情况,主要是通信方面
3、ENIP.cpp Documentation
ENIP.cpp有所有EtherNet/IP有关的接口,这是有关的技术文档
4、PCCC Address Mapping
PLC寄存器地址映射关系,主要包括以下几个寄存器
- Coil Registers 线圈寄存器(?)
- Discrete Input Registers
- Holding Registers(3个,分别是模拟输出,通用16位,通用32位)
5、Testing Method OpenPLC
测试OpenPLC的所有方法
(1)OpenPLC runtime ——> Virtual PLC
(2)Cygwin ——> 在Windows上运行本该运行在Linux上的应用
(3)Wireshark ——> 抓包工具,验证内容是否发送和接收
(4)AdvancedHMI ——> HMI 用来测试程序
具体介绍了如何下载使用AdvancedHMI,同时介绍了如何设置AdvancedHMI来测试OpenPLC项目实现的功能。
AdvancedHMI Tests
所有的测试和验证都可以使用阶梯逻辑文件“alltest3.st”和单个Advanced HMI setup来完成。Wireshark也会检查报文的格式是否正确。
(一)功能
PCCC支持三种不同的读写操作
- Protected Logical Read 用于从内存中读取数据
- Protected Logical Write 用于将数据按字节写入内存
- Protected Logical Write with Mask 用于将数据按位写入内存
(二)支持的文件类型
PCCC协议将数据存储在“文件”中被阻塞的内存部分中,每个部分都有相应的文件类型和文件编号。
OpenPLC实现了四种文件类型:
- Input Logical by Slot
- Output Logical by Slot
- Integer
- Float
(三)具体测试
介绍了以下功能的具体测试方法,在只介绍各个功能
- Read Digital Output: PLC会从digital output memory返回一个二进制值
- Read Digital Input: PLC从digital input memory返回一个二进制值
- Read Integer: PLC从memory中返回一个整数值
- Read Float: PLC会从memory中返回一个浮点数
- Write Digital Output: PLC将一个二进制值写入digital output memory
- Write Integer: PLC将一个整数值写入memory
- Write Float: PLC将一个浮点数写入memory
三、webserver
1. scripts文件夹
包括两个shell脚本,change_hardware_layer.sh和compile_program.sh
(1) change_hardware_layer.sh
作用:根据传入的参数设置相应的硬件层和平台信息
代码流程为:
![]()
第3步具体使用一系列的 if-elif-else 条件语句实现,每个条件块都包括以下步骤:
- 激活相应的硬件层驱动文件:复制相应的
.cpp文件(在core/hardware_layers文件夹中)到hardware_layer.cpp。 - 设置平台信息,通过在
openplc_platform和openplc_driver文件中写入相应的值
(2) compile_program.sh
作用:根据不同的平台和硬件驱动类型编译程序,生成相应平台上的可执行文件
代码流程为:

①第5步的代码

./st_optimizer的绝对路径应该是:OpenPLC_v3-master\utils\st_optimizer_src\st_optimizer_src.cpp
②第7步中将平台分为三种,Windows、Linux、Raspberry Pi,以Linux为例

2. lib文件夹
包括很多.txt文件,.LESSER文件,.sh文件,.c文件
(1)COPYING.LESSER
这是GNU Lesser General Public License(LGPL)的第3版。
LGPL是一种自由软件许可证,它是GNU General Public License(GPL)的一个较为宽松的替代版本。LGPL允许在某些条件下将库用于非开源软件而无需公开该软件的源代码。
(2)create_standard_function_txt.sh
作用:生成满足IEC 61131-3标准中定义的各种函数,用于产生特定数据类型的标准函数的声明和定义。
(3)很多.txt文件
目前看来都是Structured Text(ST)的文件,应该是为了(2)中生成函数(但目前还不知道怎么弄的)
(4)test_iec_std_lib.c
主函数为空,包含头文件:"iec_std_lib.h",头文件位于:OpenPLC_v3-master\webserver\core\lib\iec_std_lib.h
3. core文件夹
包含3个文件夹和多个散落文件
(1)hardware_layers文件夹
支持scripts文件夹中change_hardware_layer.sh中有关操作
(2)lib文件夹
一些.h头文件,是和通信、IEC 61131-3标准功能块库有关的代码
(3)psm文件夹
其中包括三个文件
①main.original/main.py:与OpenPLC Python SubModule (PSM)有关。PSM是连接 OpenPLC 内核与 Python 程序的桥梁。PSM 允许使用 Python 直接连接 OpenPLC IO,甚至使用普通 Python 为扩展板编写驱动程序。PSM API 非常简单,只有几个函数。
给出了一个用PSM的示例代码,可以通过PSM与OpenPLC核心连接,实现对OpenPLC的IO操作。
硬件初始化的有关代码,可能有必要继续深入
注:.original文件好像是maven打包jar包时才会生成的?
②psm.py: 给出了一个使用 pymodbus 库实现的 Modbus TCP 服务器的示例
注1:Modbus TCP服务器是一种实现了Modbus通信协议的服务器,通过TCP/IP网络提供数据交换服务。
Modbus是一种用于工业自动化领域的通信协议,它通常用于连接和控制自动化设备,例如传感器、执行器、PLC等。在Modbus TCP服务器负责处理来自客户端的请求,执行相应的操作,并返回结果。
注2:pymodbus 是一个用于处理 Modbus 协议的 Python 库,括 Modbus TCP 和 Modbus RTU 的支持。
(4)其他散落文件
实现了在OpenPLC中支持TCP、EtherNet/IP、Ethercat、Modbus、DNP3、ENIP等通信协议
四、utils文件夹
1、matiec_src文件夹
(下段内容来自 readme文件)
作用:为IEC 61131-3标准中定义的编程语言制作的开源编译器,用于PLC
该标准定义了5种编程语言:
- IL(指令列表):一种文本编程语言,与汇编语言相似。
- ST(结构化文本):一种文本编程语言,与Pascal相似。
- FBD(功能块图):一种图形编程语言,与基于小规模集成电路(IC)的电路图相似(计数器,与/或/XOR等逻辑门,定时器等)。
- LD(梯形图):一种图形编程语言,与基于继电器的电路图相似(用于基本的有线逻辑控制器)。
- SFC(顺序功能图):一种图形编程语言,定义了一个状态机,主要基于Grafcet(也可以以文本格式表达)。
在上述5种语言中,标准为IL、ST和SFC定义了文本表示形式。OpenPLC目标是支持这三种语言(只要它们以标准中定义的文本格式表达的)
目前,matiec项目生成两个编译器:iec2c和iec2iec,它们接受相同的输入——包含ST、IL和/或SFC代码的文本文件。
iec2c编译器生成等效于输入文件中表示的IEC 61131-3代码的ANSI C代码。
iec2iec编译器生成等效于输入文件中表示的IEC 61131-3代码的IEC 61131-3代码。
这个编译器工作在4(+1)个阶段:
- 阶段1 - 词法分析器(使用flex实现)
- 阶段2 - 语法解析器(使用bison实现)
- 阶段pre3 - 填充符号表(为抽象符号树中的符号提供搜索的符号表)
- 阶段3 - 语义分析器(目前仅执行类型检查,还未实现)
- 阶段4 - 代码生成器(使用gcc、javac等工具,生成ANSI C代码)
还有一个额外的阶段5 - 二进制代码生成器,由用户显式调用(不集成到matiec编译器中)。
具体内容还未看,包含多个文件夹,如下

2、libmodbus_src文件夹
实现与遵循Modbus协议的设备的通信(数据发送/接收)
3、glue_generator_src文件夹
包含一个文件夹和两个文件:
①CMakeLists.txt
一个CMake构建脚本,用于OpenPLC glue generator。glue generator接收MATIEC编译器生成的C代码,然后生成必要的代码,将MATIEC代码与OpenPLC runtime绑定在一起。
②glue_generator.cpp
作用:读取MATIEC编译器生成的LOCATED_VARIABLES.h文件,解析其中的IEC变量信息,然后生成OpenPLC runtime所需的glueVars.cpp文件。
也有人说是,生成iec到openplc共享内存的链接
③test文件夹
测试glue_generator
4、dnp3-src文件夹
实现DNP3协议栈,支持在多个并发的 TCP 会话或进行大规模设备模拟等场景中使用。在此省略具体内容。
5、apt-cyg文件夹
一个 Bash 脚本,用于在 Cygwin 环境下安装类似于 Debian 的 apt-get 工具的工具,被命名为apt-cyg 。该脚本的主要功能是简化在 Cygwin 中安装软件包的过程,类似于在 Debian 系统中使用 apt-get 进行软件包管理。
浙公网安备 33010602011771号