---
# 指示属于哪一个CPU和哪一种功能
# 下例指示CPU名字为AS1，功能为SC(串行通信 serial commnucation)
# SC 也可以写为 MB、modbusRTU
name: AS1-SC

description: |
  使用 CP340 通信，必须在step7工程中加入以下库

  * FB2 P_RCV
  * FB3 P_SEND

  使用 CP341 通信，必须在step7工程中加入以下库

  * FB7 P_RCV_RK
  * FB8 P_SND_RK

includes:
# 可通过指定includes，系统自动添加对应代码进 CP_Loop.scl 中。
# 如果发送接收块的FB背景块，建议将该FB的定义文件放入includes中
- A101.SCL      # 该文件包含 A101L FB 的实现
- FXGasFlow.scl

symbols:
# 系统已有5个内置符号：
# - [CP340_Poll, FB340] CP340通信主处理函数
# - [CP341_Poll, FB341] CP341通信主处理函数
# - [CRC16, FC464, CRC16, modbus CRC16 check] CRC16校验函数
# - [SC_Loop, FC341]      表示主循环调用FC，将这个加入OB1中
# - [SC_polls_DB, DB880]  将用于保存轮询命令数据
# 可以在对上述内置符号的地址进行更改，只要重新定义就可以了，注意保持名称一致

# 以下为自定义符号，这里是接收块
# 建议所有的接收块都用FB定义结构，不仅减少接收块的定义工作量，还能在FB中方便地对接收后的数据进一步处理和转换。
# 如果发送数据需要动态更改，则建议发送和接收都用同一个FB背景块方便处理。
# 转换程序能对发送块接收块是FB背景块的情况自动生成FB调用代码，注意接收FB不要有参数！
# 这类FB不通用，需要另外单独写SCL代码。
- [A101L, FB802]
- [FXGasFlow, FB803, ~, 福鑫天然气流量接收块]
- [write_SC, FB811, ~, 写处理块]
- [Flow30, DB830, JS_flow]
- [GAS, DB841, FXGasFlow]
- [cmd_ret, DB+, write_SC]
# JS_Flow 已在 CPU 文档中定义

list : # CP 模块列表

# 可以在一个模块中混用 modbus 和原始串行通信
# modbus协议暂只支持 01 02 03 04 05 06 号功能码
# 列表第一层为模块配置
# 模块和下一层为poll配置
#   在poll配置项中，通常不需要指定 send_DB
#   转换程序会自动把配置里的发送数据放在SC_polls_DB中
#   否则指定 send_DB 后，配置里的发送数据将无效，由指定的send_DB send_start send_length 决定发送内容
#   recv_DB recv_start 必须指定CPU中的地址，不会自动生成。

- comment: CP01 Module736 储罐液位

  # 值: 字符串 指定CP通信硬件类型，默认CP341
  model: CP340

  # 值: 字符串 省略时默认为 polls_<module_address>
  name: polls_LIT

  # 值: WORD
  # 类型: S7符号定义 | S7符号引用
  # module 和 module_addr 必须填写一个，用于指明使用哪一个CP模块硬件
  module: [CP01, IW736]
  #module_addr: 736

  # 值: DB
  # 类型: S7符号定义 | S7符号引用
  DB: [CP_01, DB881]

  polls:
  - comment: '液位'                   # 值: 字符串
    # 值: 字符串 必须是一个由空格分隔的16进制字节的字符串
    # send_data 定义了通用485通信的发送数据，modbus数据见第二个CP模块的poll
    send_data: 31 31 30 30 0D
    # 值: DB
    # 类型: S7符号定义 | S7符号引用
    # 注意，同一个DB符号只允许定义一次
    # 如另一poll要使用相同的DB块，要在另一poll中使用S7符号引用指向这里
    recv_DB: [tankLitre, DB20, A101L]
    # 值: 正整数
    recv_start: 0
    extra_code: FB

- comment: CP02 Module752
  name: polls_flow
  # module 和 module_addr 必须填写一个，用于指明使用哪一个CP模块硬件
  # 值: 正整数
  #module: [CP02, IW752]
  module_addr: 752

  DB: [CP_02, DB882]

  polls:
  - comment: 流量计30

    # 轮询模式，可省略，默认为 continuous
    # 值: 字符串
    # 有3种模式可供选择: continuous, periodicity, custom
    mode: continuous

    # 超时或周期时间，单位ms，默认 2000ms
    # 值: 正整数
    # continuous 或 custom 模式下，代表一个询问的最长等待时间
    # periodicity 模式下，代表一个询问的周期时间
    timeout: 2000

    # 没有 send_DB 和 send_data 配置项时， 由以下配置项定义 modbusRTU 发送数据
    # unit_ID func_code address data|length 配置项为十进制整数
    # 但如果采用字符串，则表示16进制，两种类型数字都是允许的。
    # 运行时会自动处理CRC校验
    # 配置项 length 和 data 本质是一样的，只是名称不同
    # 但在生成的SCL中只有 data 这一字段
    # 采用2个配置名称是为了功能码的读写语义，建议为了配置的可阅读性
    # 01 02 03 04 功能用 length，05 06 功能用 data
    unit_ID: 0x1e                      # 16进制数用字符串形式 等同于 30
    func_code: 0x4                     # 16进制数用字符串形式 等同于 4
    address: 12                        # 10进制数用整数形式 等同于 'c'
    length: 0x1c                       # 16进制数用字符串形式 等同于 28

    # 类型: S7符号定义 | S7符号引用
    recv_DB: Flow30
    recv_start: 0

    extra_code: FB                    # 将自动产生 `JS_flow.Flow30();`

  - comment: 天然气3#流量计            # 非modbus发送，不要有unit_ID属性，直接在send_data属性上写16进制发送数据
    # 自定义函数可通过 SC_polls_DB.poll_{序号}_data.{数据符号} 来处理发送数据
    # 比如本poll的发送数据SCL符号地址为：
    #   `"SC_polls_DB".polls_HK[2].sendLength` 发送长度
    #   `"SC_polls_DB".poll_2_data.send_data` (ARRAY OF BYTE)
    # 如果 send_data 要动态变化，send_data要填充0满足最大长度
    send_data: 03 03 00 00 0C 8E 5D   # send_data 必须是一个由空格分隔的16进制字节的字符串
    recv_DB: GAS                      # 接收块，引用GAS符号
    recv_start: 20                    # 要注意开始地址不一样

    mode: periodicity  # 周期模式
    timeout: 1000 # 指定1秒同期
    extra_code: FB

  - comment: 读取线圈
    unit_ID: 4
    func_code: 1
    address: 0
    length: 8
    recv_DB: cmd_ret
    recv_start: 0

  - comment: 写线圈
    mode: custom  # 人工控制写，不会自动轮询
    # 正常情况下，无论是不是modbus，发送的数据都是固定的。
    # 固定数据时，转换程序会自动为接收块为背景块的情形自动调用接收块处理FB
    # 当发送数据不固定时，比如 modbus 05 命令，建议使用指定的FB背景块作为发送数据区
    send_DB: cmd_ret
    send_start: 20
    recv_DB: cmd_ret
    recv_start: 0
    extra_code: |- # 通过设置 custom_trigger 来控制发送
      "write_SC"."cmd_ret"(writing := "SC_polls_DB".CP01[4].custom_trigger);

# 用户自写SCL代码，放在循环的开始和结束处。
loop_begin: |-
  // 这里的代码将在 AI_Loop 循环开始时执行
loop_end: |-
  // 这里的代码将在 AI_Loop 循环结束时执行

...
