询价热线: 15000687827,021-60512610
以下各节说明如何使用SQL数据库,使用VB脚本的摘录。这些脚本也在本条目的项目下载中。
1. 管理
在 SQL 数据库中可以创建一个或多个不同结构的数据表。
- 1.1 创建 SQL 数据库:脚本“Create_database”
为防止脚本中万一发生错误需要使用“On Error Resume Next”指令。这样一旦错误发生,程序会自动跳到错误的下一行执行。
为了创建到 SQL 数据库的连接需要使用对象“ADODB.Connection”。“ADODB.Recordset”用于创建、编辑或者删除数据库或者表,例如。
只有知道这个数据源的提供者和名字该数据源才能被打开。到数据源连接的建立需要使用“conn”对象的“Open”方法实现。
如果连接过程中出现超时,会产生以下错误,输出系统错误,脚本立即停止。
通过 SQL 命令“CREATE DATAbase”创建并命名一个新的数据库;这些通过“conn”对象的“Execute( SQL Table )”方法实现。
如果数据库已经存在,则执行相应的创建错误判断程序。“Close”方法用于断开和数据源的连接。
Fig. 02
SQL 语法:
CREATE DATAbase <数据库名>
- 1.2 删除 SQL 数据库: 脚本"Delete_database"
理论上,其脚本结构和“Create_database”脚本相同。可以使用 SQL 命令“DROP DATAbase”删除数据库和数据库名称。
Fig. 03
SQL 语法:
DROP DATAbase <数据库名>
2. 表
在任何一个 SQL 数据库中都可以创建一个具有单独结构的数据表。表01的数据结构创建如下:
表的数据结构 | ||||
列 | 1 | 2 | 3 | 4 |
数据类型 |
SMALLINT |
Char(30) | SMALLINT | SMALLINT |
表的数据结构可以以任何方式编译。附件的样例程序使用的就是上面的数据结构。
- 2.1 创建表: 脚本"Create_new_table"
为了打开数据源中的一个数据源以便连接数据库,脚本中需要下面的两个对象:“ADODB.Connection”用于建立连接和“ADODB.Recordset”用于编辑数据源。
“Open”中的“Initial Catalog”参数用于建立和数据源中特定数据库的连接。“Database_1”,在Windows中创建的数据源,用参数“DSN” 表示。
使用 SQL 语法“CREATE TABLE”创建 SQL 表,以及表的名称和布局(数据结构)。
Fig. 04
SQL 语法:
CREATE TABLE <表名称> (列名 类型,...)
注意:
对于“CREATE TABLE”命令还有其它可选的扩展参数。
- 2.2 复制表:脚本 "Copy_table"
连接访问需要用到对象“ADODB.Connection”和“ADODB.Recordset”。
使用 SQL 命令“SELECT * INTO”和扩展参数“FROM”,可将特定表中的所有数据复制到一个新表中。语法“SELECt *”和命令“SELECT ALL”意义相同,通过“FROM”命令表示在前一个表中的所有数据。目的表通过“INTO”定义。
注意:
SQL 语句“SELECt”可以随意的和其它命令参数组合使用。更多的信息请参考相关文献或者互联网。
Fig. 05
SQL 语法:
SELECT <表达式> INTO <新表的名称> FROM <已有表的名称>
注意:
对于 SQL 命令“SELECt”还有其它的命令可以选择组合使用。
- 2.3 删除表:脚本 "Delete_table"
为了删除表,用户必须连接相应的数据源。使用命令“DROP TABLE”从数据库中删除表及其名称。
Fig. 06
SQL 语法:
DROP TABLE <表名称>
注意:
删除表时没有确认删除表的提示信息。当表删除后,表中的所有数据也无可挽回的被删除。
3. 数据记录
每个 SQL 表都包含一定数量的数据记录。数据记录的结构取决于数据表的结构。
- 3.1 读数据记录: 脚本"Read_data_record_from_a_table"
如上所述,通过两个 ADODB 对象读数据记录。**初使用 SQL 语句“SELECt * FROM”和数据表的名称可以查询出数据库中该表的所有数据记录。
Column 1 Column 2 Column 3 >> Data 10 Data 20 Data 31 >> Data 11 Data 21 Data 32 >> Data 12 Data 22 Data 33 使用扩展命令“WHERe”和特定的列/数据记录号,仅选择表中特定的数据记录。
Column 1 Column 2 Column 3 Data 10 Data 20 Data 31 >> Data 11 Data 21 Data 32 Data 12 Data 22 Data 33
Fig. 07
SQL 语法:
SELECt <表达式> FROM <表名> WHERe <条件>
注意:
对于 SQL 命令“SELECt”还有其它可选的命令组合。
使用“if”语法结构或者“rst.EOF”和“rst.BOF”可以判断数据记录是否存在。如果选择数据记录不存在,使用“rts.MoveFirst”指向**条数据记录。
使用下面的语法可以传输列名:
szColumnName_1 = rst.Fields(1).Name
使用下面的语法可以用来得到数据记录中特定的数据:
nDataRecord_2 = rst.Fields(2).Value
Fig. 08
- 3.2 写数据记录: 脚本"Write_data_record_into_a_table"
访问中使用到的对象和从 SQL 表中读数据记录使用的对象相同。
在数据源提供者已经存在的情况下,通过 SQL 命令“SELECT * FROM”"联合表名和扩展项“WHERe”选择适当的数据记录。
Fig. 09
SQL 语法:
SELECt <表达式> FROM <表名> WHERe <条件>
注意:
对于 SQL 命令“SELECt”还有其它可选的扩展参数。
如果数据记录不存在,指针将复位到表的**行。如在3.1中查询“EOF = End of File”和“BOF = Begin ofFile”用于检测数据记录是否存在。
为了添加数据记录需要使用 SQL 命令“INSERT INTO”和SQL表名。另外,输入表中的所有参数通过“VALUES”指定,使用逗号作为分隔符。
通过“conn”对象的“Execute”方法执行 SQL 语句。
Fig. 10
SQL 语法:
INSERT INTO <表名> VALUES <值, ...>
- 3.3 编辑数据记录:脚本 "Edit_data_record"
访问数据源需要两个 ADODB 对象。一旦使用“Open”方法打开数据库,如果数据存在则选择特定的数据记录。
Fig. 11
SQL 语法:
SELECT <表达式> FROM <表名> WHERe <条件>
注意:
对于 SQL 命令“SELECt”还有其它可选的扩展参数。
使用查询“EOF”和“BOF”如果数据记录存在,脚本首先赋值给表中指定的列。
使用 SQL 语句“UPDATE”结合扩展命令“Set”和 SQL 表名可以实现对数据记录元素的赋值,该 SQL 语句通过“conn.Execute(SQL_表)”执行。
Fig. 12
SQL 语法:
UPDATE <表名> SET <列名 = 新值, ...>
注意:
该 SQL 命令也可能使用扩展的“WHERe < >”表达式。
- 3.4 删除数据记录: 脚本"Delete_data_record"
为了连接 SQL 数据库需要两个 ADODB 对象。
为了从一个数据库中删除数据记录,该 SQL 数据库必须被打开。通过比较记录数和相应的列,使用“DELETE FROM”结合 SQL 表的详细内容以及“WHERe”扩展参数来删除特定的数据记录。使用连接中的语句“conn.Execute(SQL 表)”执行删除特定数据记录的操作。
Fig. 13
SQL 语法:
DELETe FROM <表名> WHERe <条件>
注意:
选择的数据记录在删除时没有确认信息。
4. 数据记录表
SQL 也可以用于显示一个 SQL 表中全部或多个数据记录的内容。为了连接数据库需要使用到“ADODB.Connection”和“ADODB.Recordset”两个对象。
- 4.1 从表中读取所有数据:脚本 "Show_all_entries_of_a_table"
SQL 数据库中的数据记录并不一定是按照顺序存储的。因此,为了按照顺序显示必须对数据进行排序。如果希望按照列来排序,那么必须知道列名。由于本样例中列名作为变量,所以列名也必须明确的读出来。为了完整的读出 SQL 表,当“Execute”方法执行“SELECt * FROM”加 SQL 表名语句时就会返回整个表的内容。
表的内容被分配到对象“rst”。可以通过该对象指定被排序后表的列名。使用带有“ORDER BY”加列名的 SQL 命令可以实现将表按照列升序排列。
Fig. 14
SQL 语法:
SELECt <表达式> FROM <表名> ORDER BY <列名> ASC
注意:
指令“ASC”指按照升序分类,指令“DESC”指按照降序分类。除非另有说明默认按照升序分类。SQL 指令“SELECt”可与其它语法结合使用。
表中的记录是使用“Do...Loop Until”循环和“MoveNext”指令输入的。指令“rst.MoveFirst”将指针指向到表的**个条目。
在本例中的表**多可以同时输出6条记录,在 WinCC flexible 中可以使用箭头按钮实现对表的选取。变量"Tab"的值会在零和条目数减去显示的数据记录数量之间变化。当选择的表发生变化,SQL 表的指针也发生移动。这是通过指令“MoveNext”来实现的。
Fig. 15
下面的语法用于访问数据记录中的单个数据:
Value_1_0 = rst.Fields(0).Value
Value_1_1 = rst.Fields(1).Value
Value_1_2 = rst.Fields(2).Value
Fig. 164.2 将所有数据写入表:脚本 "Write_all_entries_in_a_table"
一旦数据源被打开,可以使用 SQL 命令“SELECT * FROM”加表名并结合参数“WHERe”实现对特定数据的读取,通过特定列的内容和数据记录的详细信息相比较来选择数据。
Fig. 17
SQL 语法:
SELECt <表达式> FROM <表名> WHERe <条件>
注意:
SQL 命令“SELECT”可以和其它指令一起使用。
如果数据记录包含在表中,SQL 命令“UPDATE”用于使用新的参数覆盖数据记录。如果数据记录不包含在表中,使用 SQL 命令“INSERT INTO”添加。
Fig. 18
如在3.1中查询“EOF = End of File”和“BOF = Begin of File”用于检测数据记录是否存在。
Modbus RTU 主站指令库
西门子在 Micro/WIN V4.0 SP5 中正式推出 Modbus RTU 主站协议库(西门子标准库指令)。
图 1. 西门子标准指令库(Micro/WIN V4.0 SP5)
注意- 1. Modbus RTU 主站指令库的功能是通过在用户程序中调用预先编好的程序功能块实现的,该库对 Port 0 和 Port 1 有效。该指令库将设置通信口工作在自由口模式下。
- 2. Modbus RTU 主站指令库使用了一些用户中断功能,编其他程序时不能在用户程序中禁止中断。
- 3. Modbus RTU 主站库对CPU的版本有要求。CPU 的版本必须为 2.00 或者 2.01(即订货号为 6ES721*-***23-0BA*),1.22版本之前(包括1.22版本)的 S7-200 CPU 不支持。
使用 Modbus RTU 主站指令库,可以读写 Modbus RTU 从站的数字量、模拟量 I/O 以及保持寄存器。
要使用 Modbus RTU 主站指令库,须遵循下列步骤:
- 1.安装西门子标准指令库
- 2.按照要求编写用户程序调用 Modubs RTU 主站指令库 安装西门子标准指令库
1.2 Modbus RTU 主站功能编程
1. 调用 Modbus RTU 主站初始化和控制子程序
使用 SM0.0 调用 MBUS_CTRL 完成主站的初始化,并启动其功能控制:
图 2. 用 SM0.0 调用 Modbus RTU 主站初始化与控制子程序
各参数意义如下:
a. | EN | 使能: | 必须保证每一扫描周期都被使能(使用 SM0.0) |
---|---|---|---|
b. | Mode | 模式: | 为 1 时,使能 Modbus 协议功能;为 0 时恢复为系统 PPI 协议 |
c. | Baud | 波特率: | 支持的通讯波特率为1200,2400,4800,9600,19200,38400,57600,115200。 |
d. | Parity | 校验: | 校验方式选择 |
0=无校验 | |||
1=奇较验 | |||
2=偶较验 | |||
e. | Timeout | 超时: | 主站等待从站响应的时间,以毫秒为单位,典型的设置值为 1000 毫秒(1 秒),允许设置的范围为 1 - 32767。 |
注意: 这个值必须设置足够大以保证从站有时间响应。 | |||
f. | Done | 完成位: | 初始化完成,此位会自动置1。可以用该位启动 MBUS_MSG 读写操作(见例程) |
g. | Error | 初始化错误代码(只有在 Done 位为1时有效): | |
0= 无错误 | |||
1= 校验选择非法 | |||
2= 波特率选择非法 | |||
3= 模式选择非法 |
2. 调用 Modbus RTU 主站读写子程序MBUS_MSG,发送一个Modbus 请求;
图 3. 调用Modbus RTU 主站读写子程序
各参数意义如下:
a. | EN | 使能: | 同一时刻只能有一个读写功能(即 MBUS_MSG)使能 |
---|---|---|---|
注意:建议每一个读写功能(即 MBUS_MSG)都用上一个 MBUS_MSG 指令的 Done 完成位来激活,以保证所有读写指令循环进行(见例程)。 | |||
b. | First | 读写请求位: | 每一个新的读写请求必须使用脉冲触发 |
c. | Slave | 从站地址: | 可选择的范围 1 - 247 |
d. | RW | 从站地址: | 0 = 读, 1 = 写 |
注意: | |||
1. 开关量输出和保持寄存器支持读和写功能 | |||
2. 开关量输入和模拟量输入只支持读功能 | |||
e. | Addr | 读写从站的数据地址: | |
选择读写的数据类型 | |||
00001 至 0xxxx - 开关量输出 | |||
10001 至 1xxxx - 开关量输入 | |||
30001 至 3xxxx - 模拟量输入 | |||
40001 至 4xxxx - 保持寄存器 | |||
f. | Count | 数据个数 | 通讯的数据个数(位或字的个数) |
注意: Modbus主站可读/写的**数据量为120个字(是指每一个 MBUS_MSG 指令) | |||
g. | DataPtr | 数据指针: | 1. 如果是读指令,读回的数据放到这个数据区中 |
2. 如果是写指令,要写出的数据放到这个数据区中 | |||
h. | Done | 完成位 | 读写功能完成位 |
i. | Error | 错误代码: | 只有在 Done 位为1时,错误代码才有效 |
0 = 无错误 | |||
1 = 响应校验错误 | |||
2 = 未用 | |||
3 = 接收超时(从站无响应) | |||
4 = 请求参数错误(slave address, Modbus address, count, RW) | |||
5 = Modbus/自由口未使能 | |||
6 = Modbus正在忙于其它请求 | |||
7 = 响应错误(响应不是请求的操作) | |||
8 = 响应CRC校验和错误 | |||
- | |||
101 = 从站不支持请求的功能 | |||
102 = 从站不支持数据地址 | |||
103 = 从站不支持此种数据类型 | |||
104 = 从站设备故障 | |||
105 = 从站接受了信息,但是响应被延迟 | |||
106 = 从站忙,拒绝了该信息 | |||
107 = 从站拒绝了信息 | |||
108 = 从站存储器奇偶错误 |
- 如果多个 MBUS_MSG 指令同时使能会造成 6 号错误
- 库存储区被程序其它地方复用,有时也会造成6 号错误
- 从站 delay 参数设的时间过长会造成主站 3 号错误
- 从站掉电或不运行,网络故障都会造成主站 3 号错误
3. 在 CPU 的 V 数据区中为库指令分配存储区(Library Memory)
Modbus Master 指令库需要一个284个字节的全局 V 存储区。
参考:分配库指令数据区
1.3 关于 Modbus RTU 主站协议及地址
此为西门子正式推出的标准库指令说明资料。
在 Modbus RTU Master 协议和 PPI 协议之间切换:Modbus RTU Master 协议指令库使通信口工作在自由口模式下,此时不能与 Micro/WIN 软件通信。要在切换回 PPI 协议,可以:
- 将 MBUS_CTRL 指令的 Mode 输入端设置为逻辑"0"
- 将 CPU 的允许模式选择开关置为 STOP 位置
Modbus RTU Master 协议库的 MBUS_CTRL 指令不需要很长的执行时间。MBUS_需要 1.11 ms 用于初始化,在后续的每个扫描周期中只占用 0.41 ms。
调用 MBUS_MSG 子程序会加长处理时间。大部分时间都用于 CRC 校验的计算。每读、写一个字的数据就需要 1.85 ms 扫描时间。数据**多的情况下(读、写 120 字的数据),扫描时间大概会扩增加 222 ms。读操作的时间主要消耗在接收数据上;写操作的时间主要消耗在发送数据上。
Modbus 地址通常 Modbus 地址由 5 位数字组成,包括起始的数据类型代号,以及后面的偏移地址。Modbus Master 协议库把标准的 Modbus 地址映射为所谓 Modbus 功能号,读写从站的数据。Modbus Master 协议库支持如下地址:
- 00001 - 09999:数字量输出( 线圈)
- 10001 - 19999:数字量输入(触点)
- 30001 - 39999:输入数据寄存器(通常为模拟量输入)
- 40001 - 49999:数据保持寄存器
为了支持上述 Modbus 地址的读写,Modbus Master 协议库需要从站支持下列功能:
表 1. 需要从站支持的功能
Modbus 地址 | 读/写 | Modbus 从站须支持的功能 |
---|---|---|
00001 - 09999 数字量输出 |
读 | 功能 1 |
写 | 功能 5:写单输出点 功能 15:写多输出点 |
|
10001 - 19999 数字量输入 |
读 | 功能 2 |
写 | - | |
30001 - 39999 |
读 | 功能 4 |
写 | - | |
40001 - 49999 保持寄存器 |
读 | 功能 3 |
写 | 功能 6:写单寄存器单元 功能 16:写多寄存器单元 |
S7-200 通过 Modbus Master 和 Slave 协议库通信时,Modbus 地址和 S7-200 内存储区地址的 映射关系都类似。
Modbus 保持寄存器地址映射举例:
Modbus 数字量地址映射举例:
位地址(0xxxx 和 1xxxx)数据总是以字节为单位打包读写。**个字节中的**有效位对应 Modbus 地址的起始地址。如下图所示:
图 4. 数字量地址映射举例
1.4 Modbus RTU 主站例程
为了更好地理解 Modbus 主站的编程,可参考下面的例程。
例子程序1: 多个MBUS_MSG指令轮询执行,
注意- 1. 该例程使用 Micro/WIN V4.0 SP5 保存。
- 2. 该例程仅访问一个从站,若访问不同的从站,可通过改变从站地址来实现。
Modbus RTU 主站指令库应用例程
例子程序2:反复激活单个MBUS_MSG指令:Modbus RTU 主站变址方式轮询访问应用例程
注意:此指令库/程序的作者和拥有者对于该软件的功能性和兼容性不负任何责任。使用该软件的风险完全由用户自行承担。由于它是免费的,所以不提供任何担保,错误纠正和热线支持,用户不必为 此联系西门子技术支持与服务部门。
1.5 Modbus RTU 主站常问问题
Modbus RTU 主站库对 CPU 的版本是否有要求,为什么编译例子程序时,会遇到 4 个错误?
Modbus RTU 主站库对 CPU 的版本确实有要求,CPU 的版本必须为 2.00 或者 2.01(即订货号为6ES721*-***23-0BA*),1.22 版本之前(包括 1.22 版本)的 S7-200 CPU 不支持。
Modbus 指令库启动后,如何通过同一个通信端口进行 CPU 监控?
Modbus 指令库使用的是 CPU 的自由口通信功能,工作在自由口模式下的通讯口不能使用 Micro/WIN 的 PPI 编程通信监控。如果通信口都已经被占用,可以考虑:
- 加一个通信模块(如 EM 277、CP 243-1、EM 241 等)扩展出一个编程通信口
- 中止自由口模式,可以将 CPU 上的模式开关从 RUN 拨到 STOP;或者保持处于 RUN 状态,用程序停止指令库的 Modbus 模式(参见指令库应用)
如何理解 Modbus 地址与功能码的区别?
Modbus 地址与 Modbus 的功能码是两个层次的概念。
根据 Modbus 通信协议,Modbus 数据的地址使用 0xxxx、1xxxx、3xxxx 和 4xxxx 的形式,分别表示数字量输出、数字量输入、模拟量输入等数据地址。在使用 S7-200 的指令库时,Modbus 数据地址与 S7-200 的 I/O 和数据存储区地址间有特定的对应关系。
有些设备表明它支持 Modbus RTU 通信协议,但也详细提供了读写数据的详细通信帧格式,其中包括如何指定 Modbus 站的地址,需要读写数据类型、长度等等。数据帧有特定字节指出此指令读写的数据类型和地址,此字节的数据内容即所谓"功能码",如功能 1 指定读取单个/多个数字量输出点的值。
支持 Modbus 协议的设备或软件,使用时用户直接设置或看到的应当是 Modbus 数据地址。Modbus 地址所访问的数据,是通过各种"功能"读写而来。功能码是 Modbus 地址的底层。如果 Modbus 通信的一方提供的所谓 Modbus 协议只有功能码,则需要注意了解此功能号与 Modbus 地址间的对应关系。