SylixOS Modbus 开发

更新时间:
2024-04-26
下载文档

SylixOS Modbus 开发

本节将通过 Modbus TCP 对从站 0 - 16 位线圈状态(Coil Status)进行读写,0 - 16 位输入寄存器 (Input Status) 进行读取,实现快速体验中的 Modbus 控制效果。

环境准备

设备列表

序号设备名称数量备注
1IGC1503 控制器1必选
2Modbus TCP 远程 IO 模块1可选
3交换机1可选

软件列表

序号软件名称数量备注
1RealEvo-IDE1必选
2Modbus 从站仿真软件1必选
3PuTTY 终端工具1必选

下载列表

与 Modbus 从站仿真软件数据交互

使用 Modbus TCP 协议实现“功能 1 为线圈状态”和“功能 2 为输入状态”的数据交互,具体操作如下。

说明:

本小节对于 Modbus 从站仿真软件的配置效果与“极速体验”章节提供的 Modbus Slave 工作空间完全一致,用户可直接按照“快速体验 > SylixOS 数据采集 > 部署应用”中 步骤 4 操作。

前提条件

  1. 根据“快速体验 > SylixOS 数据采集 > 环境准备”中 步骤 1 操作,将硬件设备进行连接。

  2. 根据“快速体验 > SylixOS 数据采集 > 部署应用”中 步骤 1 操作,设置本机 IP 与 IGC1503 处于同一网段。

步骤 1:连接从站仿真软件

  1. 单击 Connection > Connect…,会弹出设置窗口 Connection Setup。

  2. Connection Setup 窗口中选择 Modbus TCP/IP,勾选 Any AddressIgnore Unit ID,使得 Modbus Client 可以响应任意 Modbus Server 的请求。

步骤 2:配置线圈通道

  1. 单击 Mbslave1 窗口,选择菜单栏 Setup > Slave Definition

  2. Slave Definition 窗口中配置 Slave ID1Function01 Coil Status (0x),寄存器值 16,单击 OK 完成配置。

步骤 3:配置状态寄存器通道

  1. 单击菜单栏 File > New 新建 Mbslave2 通道,

  2. 单击 Mbslave2 窗口,选择菜单栏 Setup > Slave Definition

  3. Slave Definition 窗口中配置 Slave ID1Function02 Input Status (1x),寄存器值 16,单击 OK 完成配置。

  4. 双击第二列任意单元格,勾选 Auto change,单击 OK 即可实现对应状态寄存器通道自动跳变的功能。

步骤 4:创建 Base 工程

  1. 打开 RealEvo-IDE,单击 Browse... 选择一个新文件夹作为工作空间,单击 Launch 进入开发界面。

  2. 在主菜单中选择 File > New > SylixOS Base 新建 Base。

  3. Project name 中自定义 Base 工程名,单击 Next 进入下一步。

  4. 在 SylixOS version 下拉菜单中选择 default,并在列表中选择 SylixOS Standard Base 后,单击 Next

  5. 如图所示选择 ToolchainDebug LevelCPU TypeFPU Type,并单击 Next

    说明:

    IGC1500,IGC1503 的 CPU Type 均为 cortex-a7

  6. 在 SylixOS 组件配置界面,如下图进行默认选择,并单击 Finish 完成 Base 新建工作。

  7. 编译 Base 工程。右键 base_a7 工程 > Build Project

步骤 5:创建 App 工程

  1. 新建 App 工程。在主菜单中选择 File > New > SylixOS App

  2. 输入工程名,单击 Next

  3. 单击 Workspace 选择上步骤创建的 SylixOS Base 工程 base_a7,并单击 Finish 完成创建。

  4. 在工程栏中 app_modbus > src,打开 app_modbus.c 文件编辑代码,示例代码如下。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <pthread.h>
    #include <assert.h>
    #include "modbus.h"
    
    /*********************************************************************************************************
    Config slave ip & port
    *********************************************************************************************************/
    #define MODBUS_TCP_SLAVE_IP     "192.168.1.8"
    #define MODBUS_TCP_SLAVE_PORT   (502)
    /*********************************************************************************************************
    ** 函数名称: main
    ** 功能描述: 主函数
    ** 输  入  : argc      参数个数
    **           argv      参数指针数组
    ** 输  出  : 0 or -1
    *********************************************************************************************************/
    int main (int  argc, char  **argv)
    {
       modbus_t           *mbtCtx;
       unsigned int        uiPos        = 0;
       uint8_t             ucInput[16]  = {0};
       uint8_t             ucOutput[16] = {0};
       char                cBuf[512]    = {0};
       char                cTempBuf[64] = {0};
       int                 i            = 0;
       int                 iOutputSize  = sizeof(ucOutput) / sizeof(ucOutput[0]);
       int                 iInputSize   = sizeof(ucInput) / sizeof(ucInput[0]);
       int                 iTempBufSize = sizeof(cTempBuf);
    
       /* 
        *  New modbus master. 
        *  argv[1] modbus device ip, argv[2] modbus device port
        */
       if (argc > 2) {
          mbtCtx = modbus_new_tcp(argv[1], atoi(argv[2]));
          
       } else {
          mbtCtx = modbus_new_tcp(MODBUS_TCP_SLAVE_IP, MODBUS_TCP_SLAVE_PORT);
       }
    
       if (NULL == mbtCtx) {
          fprintf(stderr, "Create modbus failed!\n");
    
          return  (-1);
       }
    
       /* 
        *  Connect slave.
        */
       if (modbus_connect(mbtCtx) == -1) {
          fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
          modbus_free(mbtCtx);
          mbtCtx = NULL;
    
          return  (-1);
       }
    
       while (1) {
          sleep(1);
    
          for (i = 0; i < iOutputSize; i++) {
                ucOutput[i] = (i == uiPos) ? 1 : 0;
          }
    
          uiPos++;
    
          if (uiPos >= iOutputSize) {
                uiPos = 0;
          }
    
          /* 
           *  Write Coil Status. 
           */
          modbus_write_bits(mbtCtx, 0, iOutputSize, ucOutput);
    
          /* 
           *  Read Coil Status. 
           */
          memset(ucOutput, 0, iOutputSize);
          modbus_read_bits(mbtCtx, 0, iOutputSize, ucOutput);
    
          /* 
           *  Read Input Registers. 
           */
          memset(ucInput, 0, iInputSize);
          modbus_read_input_bits(mbtCtx, 0, iInputSize, ucInput);
    
          /* 
           *  Print results. 
           */
          sprintf(cBuf, "input(DI0~DI%d):       ", iInputSize);
    
          for (i = 0; i < iInputSize; i++) {
                memset(cTempBuf, 0, iTempBufSize);
                sprintf(cTempBuf, " %d", ucInput[i]);
                strcat(cBuf, cTempBuf);
          }
    
          strcat(cBuf, "\r\n");
          memset(cTempBuf, 0, iTempBufSize);
          sprintf(cTempBuf, "output(DO0~DO%d):      ", iOutputSize);
          strcat(cBuf, cTempBuf);
    
          for (i = 0; i < iOutputSize; i++) {
                memset(cTempBuf, 0, iTempBufSize);
                sprintf(cTempBuf, " %d", ucOutput[i]);
                strcat(cBuf, cTempBuf);
          }
    
          printf("%s\r\n", cBuf);
       }
    
       /* 
        *  Close the connection.
        */
       if (mbtCtx != NULL) {
          modbus_close(mbtCtx);
          modbus_free(mbtCtx);
          mbtCtx = NULL;
       }
    
       return  (0);
    }
    
  5. 在工程中加入 Modbus 相关的依赖头文件和库文件,整体工程结构如下所示。

    说明:

  6. 设置依赖文件。右键 app_modbus 工程 > Properties 打开设置界面。

  7. 在窗口进入 SylixOS Project > Compiler Setting > Include Path > Current Project 界面,设置依赖头文件。

  8. 在窗口中选择头文件所存放的 inc 文件夹,单击 OK 完成头文件路径的选择。

  9. 在窗口进入 SylixOS Project > Linker Setting > Linker Setting > Current Project 界面,设置依赖库文件并添加库路径。

  10. 在窗口中选择依赖的库文件 libmodbus.so,单击 OK 完成库文件的选择。

  11. 在弹框中选择,工程会自动添加依赖库文件的路径。

  12. 保存所有工程配置。单击 Apply 使配置生效。最后,单击 OK 完成配置。

  13. 编译 App 工程。右键 app_modbus 工程 > Build Project

步骤 6:部署 App

  1. 设置部署的设备及应用。右键 app_modbus 工程 > Properties 打开设置界面。

  2. 在窗口进入 SylixOS Project > Device Setting > New Device 界面,添加部署的目标设备。

  3. 添加 IGC1503 的 IP:192.168.1.253,单击 Finish 完成设置。

  4. 在窗口进入 SylixOS Project > Device Setting > Add 界面,添加库文件的部署。

  5. 单击 Workspace 选择 app_modbus > lib > libmodbus.so 库文件,并输入 Remote path,单击 OK 完成库文件的部署信息。

  6. 配置完成后,信息如下图所示。单击 Apply 使配置生效,再单击 OK 完成配置。

  7. 右键 app_modbus 工程,选择 SylixOS > Upload 将工程上传部署。

步骤 7:登录 IGC 控制器

根据“快速体验 > SylixOS 数据采集 > 部署应用”中 步骤 3 操作,登录 IGC 控制器。

步骤 8:查看运行效果

input 显示为 Mbslave2 窗口的输入状态,即 Mbslave2 的通道值改变,input 的打印信息也会打印相同的值,实现 Client 主动读取 Server 输入通道值功能。

Mbslave1 窗口显示为 output 的输出状态,即 output 打印出的值,将会在 Mbslave1 窗口中同步显示。output 值的变动实现 Client 控制 Server 流水灯功能,“1”为亮灯,“0”为灭灯,模拟了流水灯亮灭的操作。

  1. IGC1503 运行获取寄存器状态打印如下所示。

    [root@sylixos:/apps/app_modbus]# ./app_modbus
    input(DI0~DI16):        0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0
    output(DO0~DO16):       1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    
    input(DI0~DI16):        0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    output(DO0~DO16):       0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    
    input(DI0~DI16):        0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0
    output(DO0~DO16):       0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
    
  2. Modbus 从站仿真软件状态如下所示。

与 Modbus TCP 远程 IO 数据交互

  1. 代码程序可从 步骤 4 开始参考操作。

  2. 运行效果与“快速体验 > SylixOS 数据采集 > 运行效果”中 Modbus 远程 IO 一致。

文档内容是否对您有所帮助?
有帮助
没帮助