跳转至

ModbusRtu从站接⼝说明

一、使用示例

创建⼀条ModbusRtu从站通讯通道,在通道上创建1个Modbus从站站点(RTU模式下一条从站通道只能接一个设备),循环获取站点的值或写⼊站点的值

MRTU从站

#include "modbus_slave/modbusrtu_slave_ch.h"
#include "modbus_slave/modbus_slave_dev.h"
#include <stdio.h>
#include <unistd.h>

// 写数据回调函数(参数,站地址,命令,地址,值)
void DataRenewCallback(void *arg,
    const int slaveid, const int code, const int addr, const int value)
{
    printf("[%s][%d][%s] slaveid=%d, code=%d, addr=[%04X]%d, value=%d\r\n",
        __FILE__, __LINE__, __FUNCTION__, slaveid, code, addr, addr, value);
}

int main(int argc, char *argv[])
{
    for(int i = 0; i < 10; i++) {
        printf("\r\n[%s][%d][%s] i=%d\r\n", __FILE__, __LINE__, __FUNCTION__, i);
        ModbusRtuSlaveCh *pch = new ModbusRtuSlaveCh("/dev/ttysWK2", 115200, 'N', 8, 1);
        printf("创建通讯通道 [%08X]\r\n", pch);
        ModbusSlaveDev *pmsd = new ModbusSlaveDev(pch, 2, 0x0000, 10, 0x0000, 11, 0x0000, 12, 0x0000, 13);
        printf("创建站点 [%08X]\r\n", pmsd);
        pch->SetDataRenewCallback(DataRenewCallback);
        pch->Run();
        printf("启动通讯通道 [%08X]\r\n", pch);

        for(int j = 0; j < 20; j++) {
            sleep(5);
            printf("\r\n[%s][%d][%s] i=%d, j=%d\r\n", __FILE__, __LINE__, __FUNCTION__, i, j);
            uint16_t bits[11] = { 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000 };
            uint16_t regs[13] = { 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D };
            pmsd->SetDataValues(ModbusSlave::kCode01H, 0x0000, bits, 10);
            pmsd->SetDataValues(ModbusSlave::kCode02H, 0x0000, bits, 11);
            pmsd->SetDataValues(ModbusSlave::kCode03H, 0x0000, regs, 12);
            pmsd->SetDataValues(ModbusSlave::kCode04H, 0x0000, regs, 13);
            printf("------------------------------------------------------------------------\r\n");
        }
        printf("释放通讯通道 [%08X]\r\n", pch);
        delete pch;
        pch = nullptr;
        printf("释放站点 [%08X]\r\n", pmsd);
        delete pmsd;
        pmsd = nullptr;
        printf("[%s][%d][%s] i=%d\r\n\r\n", __FILE__, __LINE__, __FUNCTION__, i);
        sleep(5);
    }

    return 0;
}

二、ModbusSlaveCh类

ModbusSlaveCh类为ModbusRtuSlaveCh类、 ModbusTcpSlaveCh类的基类,提供Modbus从站通道的通⽤属性

1. 构造函数

/**
 * @brief 构造函数
 *
 * @param
 */
ModbusSlaveCh(/* args */);

2. 析构函数

/**
 * @brief 析构函数
 */
~ModbusSlaveCh();

3. 获取数据区指针

/**
 * @brief 获取数据区指针
 *
 * @param 无
 *
 * @return 返回数据区指针
 */
ModbusSlaveData *GetData();
  • 参数

  • 无;

  • 返回值

  • 返回数据区指针;

4. 设置是否打印报文

/**
 * @brief 设置是否打印报文(通过printf输出到命令行中)
 *
 * @param debug 是否开启,0-关闭;1-开启;
 *
 * @return 无
 */
void SetDebug(int debug);
  • 参数
  • debug :是否开启, 0-关闭; 1-开启;
  • 返回值

5. 设置收发报文内容回调函数

/**
 * @brief 设置收发报文内容回调函数
 *
 * @param *s_callback 发送报文回调函数(参数,报文内容,报文长度);
 * @param *r_callback 接收报文回调函数(参数,报文内容,报文长度);
 * @param arg         回调参数;
 *
 * @return 无
 */
void SetMessageCallback(
        void (*s_callback)(void *, const uint8_t *, int),
        void (*r_callback)(void *, const uint8_t *, int),
        void *arg = NULL);
  • 参数
  • *s_callback:发送报⽂回调函数(参数,报⽂内容,报⽂⻓度);
  • *r_callback:接收报⽂回调函数(参数,报⽂内容,报⽂⻓度);
  • *arg:回调参数;
  • 返回值

6. 设置收发报⽂内容回调使能

/**
 * @brief 设置收发报文内容回调使能
 *
 * @param en 是否使能:0-未使能;1-使能;
 *
 * @return 无
 */
void SetMessagrCallbackEn(int en);
  • 参数
  • en:是否使能: 0-未使能; 1-使能;
  • 返回值

7. 设置收发报⽂内容回调使能

/**
 * @brief 设置写数据回调函数
 *
 * @param *callback 写数据回调函数(参数,站地址,命令,地址,值)
 * @param arg      回调参数
 *
 * @return 无
 */
void SetDataRenewCallback(fpMscDataRenewCallback callback, void *arg = NULL);

// 写数据回调函数(参数,站地址,命令,地址,值)
typedef void (*fpMscDataRenewCallback)(void *arg,
    const int slaveid, const int code, const int addr, const int value);
  • 参数
  • callback:写数据回调函数(参数,站地址,命令,地址,值);
  • *arg:回调参数;
  • 返回值

三、ModbusRtuSlaveCh类

ModbusRtuSlaveCh类,继承⾃ModbusSlaveCh类,⽤于创建ModbusRtu从站通讯通道

1. 构造函数

/**
 * @brief 构造函数
 *
 * @param *device  串口的文件描述符;
 * @param baud     波特率;
 * @param parity   校验位,可选'N'(无校验)、'O'(奇校验)、'E'(偶校验);
 * @param data_bit 数据位,可选5、6、7、8;
 * @param stop_bit 停止位,可选1、2;
 */
ModbusRtuSlaveCh(const char *device, int baud = 115200,
            char parity = 'N', int data_bit = 8, int stop_bit = 1);
  • 参数
  • *device:串⼝的⽂件描述符;
  • baud:波特率;
  • parity:校验位,可选'N'(⽆校验)、 'O'(奇校验)、 'E'(偶校验);
  • data_bit:数据位,可选5、 6、 7、 8;
  • stop_bit:停⽌位,可选1、 2;
  • 返回值
  • 返回值

2. 析构函数

/**
 * @brief 析构函数
 */
~ModbusRtuSlaveCh();

3. 启动函数

/**
 * @brief 启动函数
 *
 * 启动ModbusRtu从站监听数据
 *
 * @param 无
 *
 * @return 无
 */
void Run();
  • 参数
  • 返回值

四、ModbusSlaveDev类

Modbus从站模式下的站点类

1. 构造函数

/**
 * @brief 构造函数
 *
 * @param ch                    ModbusSlaveCh通道
 * @param slave                 站地址;
 * @param nb_bits               线圈点数量;
 * @param start_bits            线圈点起始地址;
 * @param nb_input_bits         离散输入点数量;
 * @param start_input_bits      离散输入点起始地址;
 * @param nb_input_registers    输入寄存器点数量;
 * @param start_input_registers 输入寄存器点起始地址;
 * @param nb_registers          保持寄存器点数量;
 * @param start_registers       保持寄存器点起始地址;
 */
ModbusSlaveDev(
        ModbusSlaveCh *pch,
        int slave,
        int nb_bits,
        int start_bits,
        int nb_input_bits,
        int start_input_bits,
        int nb_input_registers,
        int start_input_registers,
        int nb_registers,
        int start_registers
    );
  • 参数

  • ch:ModbusSlaveCh通道;

  • slave:站地址;
  • nb_bits:线圈点数量;
  • start_bits:线圈点起始地址;
  • nb_input_bits:离散输入点数量;
  • start_input_bits:离散输入点起始地址;
  • nb_input_registers:输入寄存器点数量;
  • start_input_registers:输入寄存器点起始地址;
  • nb_registers:保持寄存器点数量;
  • start_registers:保持寄存器点起始地址;
  • 返回值

  • 返回值

2. 析构函数

/**
 * @brief 析构函数
 */
~ModbusSlaveDev();

3. 获取站点ID

获取站点ID(站地址)

/**
 * @brief 获取站点ID(站地址)
 *
 * @return 站地址
 */
int get_SlaveId();
  • 参数

  • 返回值

  • 站地址

4. 设置连续多个数据点的数值

/**
 * @brief 设置连续多个数据点的数值
 *
 * @param code      数据点类型
 * @param startaddr 数据点地址;
 * @param *value    点的值;
 * @param nb        数据点个数;
 *
 * @return 是否设置成功 :
 *      1-设置成功;
 *      -1-失败:未找到对应站点ID的数据区;
 *      -2-失败:未知功能码
 *      -3-失败:点地址越界;
 */
int SetDataValues(ModbusSlave::CodeSet_E code, int startaddr, uint16_t *value, int nb = 1);
  • 参数

  • code:数据点类型;

  • addr:数据点起始地址;
  • *value:点的值;
  • nb:数据点个数
  • 返回值

  • 是否设置成功 :

    • 1-设置成功;
    • -1-失败:未找到对应站点ID的数据区;
    • -2-失败:未知功能码
    • -3-失败:点地址越界;

5. 获取连续多个数据点的数值

/**
 * @brief 获取连续多个数据点的数值
 *
 * @param code      数据点类型
 * @param startaddr 数据点地址;
 * @param *value    点的值;
 * @param nb        数据点个数;
 *
 * @return 是否获取成功 :
 *      1-获取成功;
 *      -1-失败:未找到对应站点ID的数据区;
 *      -2-失败:未知功能码
 *      -3-失败:点地址越界;
 */
int GetDataValues(ModbusSlave::CodeGet_E code, int startaddr, uint16_t *value, int nb = 1);
  • 参数

  • code:数据点类型;

  • addr:点地址;
  • *value:输出参数,返回点的值;
  • nb:数据点个数
  • 返回值

  • 是否获取成功 :

    • 1-获取成功;
    • -1-失败:未找到对应站点ID的数据区;
    • -2-失败:未知功能码
    • -3-失败:点地址越界;