ModbusTcp从站接⼝说明
一、使用示例
创建⼀条ModbusTcp从站通讯通道,在通道上创建1个Modbus站点,循环获取站点的值或写⼊站点的值
#include "modbus_slave/modbustcp_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);
ModbusTcpSlaveCh *pch = new ModbusTcpSlaveCh("0.0.0.0", 502);
printf("创建通讯通道 [%08X]\r\n", pch);
ModbusSlaveDev *pmsd1 = new ModbusSlaveDev(pch, 1, 0x0000, 10, 0x0000, 11, 0x0000, 12, 0x0000, 13);
printf("创建站点 [%08X]\r\n", pmsd1);
pch->SetDataRenewCallback(DataRenewCallback);
pch->SetHostActivityInitValue(20);
pch->SetHostDelEsourcesInitValue(60);
pch->Run();
printf("启动通讯通道 [%08X]\r\n", pch);
// 主机连接信息
std::map<int, ModbusTcpSlaveCh::HostInfo_T> host_info_map;
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);
int ret = pch->GetConnectHostInfo(&host_info_map);
printf("当前连接的主机个数:%d\r\n", ret);
if(ret > 0) {
for(auto &it : host_info_map) {
int fd = it.first;
ModbusTcpSlaveCh::HostInfo_T hostinfo = it.second;
printf("fd=%d, ip=%s, port=%d, activity=%d, del_esources=%d\r\n",
fd, inet_ntoa(hostinfo.skaddr.sin_addr), hostinfo.skaddr.sin_port, hostinfo.activity, hostinfo.del_esources);
}
}
uint16_t bits1[11] = { 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001 };
uint16_t regs1[13] = { 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D };
pmsd1->SetDataValues(ModbusSlave::kCode01H, 0x0000, bits1, 10);
pmsd1->SetDataValues(ModbusSlave::kCode02H, 0x0000, bits1, 11);
pmsd1->SetDataValues(ModbusSlave::kCode03H, 0x0000, regs1, 12);
pmsd1->SetDataValues(ModbusSlave::kCode04H, 0x0000, regs1, 13);
printf("------------------------------------------------------------------------\r\n");
}
printf("释放通讯通道 [%08X]\r\n", pch);
delete pch;
pch = nullptr;
printf("释放站点 [%08X]\r\n", pmsd1);
delete pmsd1;
pmsd1 = 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. 构造函数
2. 析构函数
3. 获取数据区指针
-
参数
-
无;
-
返回值
-
返回数据区指针;
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:回调参数;
- 返回值
- ⽆
三、ModbusTcpSlaveCh类
ModbusTcpSlaveCh类,继承⾃ ModbusSlaveCh类,⽤于创建ModbusTcp从站通讯通道
1. 构造函数
/**
* @brief 构造函数
*
* @param *ip_addr 本机监听的IP地址,一般为"0.0.0.0";
* @param port 本机监听的端口号,一般为502;
*/
ModbusTcpSlaveCh(const char *ip_addr = "0.0.0.0", int port = 502);
- 参数
- *ip_address:本机监听的IP地址,一般为"0.0.0.0";
- port:本机监听的端口号,一般为502;
- 返回值
- 返回值;
2. 析构函数
3. 启动函数
- 参数
- 无
- 返回值
- 无
4. 设定连接活性初始值
当主站连续一段时间未访问从站时,从站判定主站离线
/**
* @brief 设定判断连接活性初始值
*
* 当主站连续一段时间未访问从站时,从站判定主站离线
*
* @param value 连接活性初始值,秒
*
* @return 无
*/
void SetHostActivityInitValue(int value);
- 参数
- value 连接活性初始值,秒
- 返回值
- 无
5. 设定删除资源初始值
/**
* @brief 设定删除资源初始值
*
* 当主站连续一段时间未访问从站时,从站将对应的socket关闭
*
* @param value 删除资源初始值,秒
*
* @return 无
*/
void SetHostDelEsourcesInitValue(int value);
- 参数
- value 删除资源初始值,秒
- 返回值
- 无
7. 获取当前连接的主机信息
/**
* @brief 获取当前连接的主机信息
*
* @param host_info_map 连接的主机信息
*
* @return 连接的主机数量
*/
int GetConnectHostInfo(std::map<int, HostInfo_T> *phost_info_map);
- 参数
- host_info_map 返回参数,连接的主机信息
- 返回值
- 连接的主机数量
四、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. 析构函数
3. 获取站点ID
获取站点ID(站地址)
-
参数
-
无
-
返回值
-
站地址
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-失败:点地址越界;