ModbusTcp主站接口说明
一、使用示例
创建一条ModbusTcp主站通讯通道,在通道上创建1个站点,循环获取站点的值或写入站点的值
#include "modbus_host/modbustcp_host_ch.h"
#include "modbus_host/modbus_host_dev.h"
#include <stdio.h>
#include <unistd.h>
void read_test(const char *name, ModbusHostDev *pdev, int code, int startaddr, int size)
{
uint16_t data[1024] = { 0 };
printf("%s, code=%d, addr=[%04X]%d, size=%d--------------------------------------------\r\n",
name, code, startaddr, startaddr, size);
pdev->GetCycleReadDataBlookValue((ModbusHost::ReadCode_E)code, startaddr, data, size);
for(int i = 0; i < size; i++) {
printf("%s, code=%d, addr=[%04X]%d, value=[%04X]%d\r\n",
name, code, startaddr+i, startaddr+i, data[i], data[i]);
}
}
int main(int argc, char *argv[])
{
// 创建通道
ModbusTcpHostCh *pch = new ModbusTcpHostCh("192.168.100.204", 502);
pch->SetBitSingleMaxPoint(4);
pch->SetRegSingleMaxPoint(6);
printf("创建通讯通道 [%08X]\r\n", pch);
// 创建设备1-PCS
ModbusHostDev *pdev1 = new ModbusHostDev(pch, 1);
pdev1->AddCycleReadDataBlock(ModbusHost::kReadCodeBits, 0x0000, 10);
pdev1->AddCycleReadDataBlock(ModbusHost::kReadCodeBits, 0x1000, 10, 5000);
pdev1->AddCycleReadDataBlock(ModbusHost::kReadCodeInputBits, 0x2000, 10, 5000);
pdev1->AddCycleReadDataBlock(ModbusHost::kReadCodeHoldRegs, 0x3000, 10, 5000);
pdev1->AddCycleReadDataBlock(ModbusHost::kReadCodeInputRegs, 0x4000, 12, 5000);
printf("创建设备1 [%08X]\r\n", pdev1);
// 启动通道
pch->Run();
printf("启动通讯通道\r\n");
int bits[1024] = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 };
int regs[1024] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
int ret_write = 0;
// 等待
for(int i = 0; i < 1000; i++) {
sleep(10);
uint16_t data[1024];
// 设备1读取测试 功能码01,起始地址0x0000,点数10
int code = ModbusHost::kReadCodeBits;
int startaddr = 0x0000;
int size = 10;
read_test("pdev1", pdev1, code, startaddr, size);
// 设备1读取测试 功能码01,起始地址0x1000,点数10
code = ModbusHost::kReadCodeBits;
startaddr = 0x1000;
size = 10;
read_test("pdev1", pdev1, code, startaddr, size);
// 设备1读取测试 功能码02,起始地址0x2000,点数10
code = ModbusHost::kReadCodeInputBits;
startaddr = 0x2000;
size = 10;
read_test("pdev1", pdev1, code, startaddr, size);
// 设备1读取测试 功能码03,起始地址0x3000,点数10
code = ModbusHost::kReadCodeHoldRegs;
startaddr = 0x3000;
size = 10;
read_test("pdev1", pdev1, code, startaddr, size);
// 设备1读取测试 功能码04,起始地址0x4000,点数12
code = ModbusHost::kReadCodeInputRegs;
startaddr = 0x4000;
size = 12;
read_test("pdev1", pdev1, code, startaddr, size);
printf("[%s][%d][%s] i=%d\r\n", __FILE__, __LINE__, __FUNCTION__, i);
// 设备1写入测试 功能码15,起始地址0x0000,点数10
ret_write = pdev1->AddWriteDataBlock(ModbusHost::kWriteCodeBits, 0x0000, bits, 10);
printf("[%s][%d][%s] ret_write=%d\r\n", __FILE__, __LINE__, __FUNCTION__, ret_write);
// 设备1写入测试 功能码16,起始地址0x3000,点数10
ret_write = pdev1->AddWriteDataBlock(ModbusHost::kWriteCodeHoldRegs, 0x3000, regs, 10);
printf("[%s][%d][%s] ret_write=%d\r\n", __FILE__, __LINE__, __FUNCTION__, ret_write);
// 获取设备1和设备2的超时状态
printf("[%s][%d][%s] pdev1->GetTimeoutStatus()=%d\r\n",
__FILE__, __LINE__, __FUNCTION__, pdev1->GetTimeoutStatus());
}
return 1;
}
二、ModbusHostCh类
ModbusHostCh类为ModbusRtuHostCh类、ModbusTcpHostCh类的基类,提供Modbus主站通道的通用属性
1. 构造函数
2. 析构函数
3. 获取数据区指针
获取ModbusHost通道的数据区指针
/**
* @brief 获取数据区指针
*
* 获取ModbusHost通道的数据区指针
*
* @param 无
*
* @return 数据区的指针
*/
ModbusHostData *GetDataArea();
- 参数
- 无;
- 返回值
- 数据区指针;
4. 获取通讯超时状态
/**
* @brief 获取通讯超时状态
*
* @param slaveid 站地址
*
* @return 是否超时:1-超时;0-未超时;-1-站地址错误;
*/
int GetTimeoutStatus(int slaveid);
- 参数
- slaveid 站地址;
- 返回值
- 是否超时:1-超时;0-未超时;-1-站地址错误;
5. 设置通讯超时时间
/**
* @brief 设置通讯超时时间
*
* @param sec 超时时间的秒数;
* @param usec 超时时间的微秒数;
*
* @return 无
*/
void SetResponseTimeout(long sec, long usec);
- 参数
- sec:超时时间的秒数;
- usec:超时时间的微秒数;
- 返回值
- 无
6. 设置Modbus通讯异常的判定次数
modbus帧通讯超时次数超过此值时,认为Modbus通讯异常
/**
* @brief 设置Modbus通讯异常的判定次数
*
* Modbus帧通讯超时次数超过此值时,认为Modbus通讯异常
*
* @param count 次数;
*
* @return 无
*/
void SetTimeoutMaxCount(uint32_t count);
- 参数
- count:次数;
- 返回值
- 无
7. 轮询帧时间间隔 毫秒
/**
* @brief 轮询帧时间间隔
*
* 每2帧通讯报文的之间的间隔时间
*
* @param ms 间隔时间,毫秒;
*
* @return 无
*/
void SetPollFrameIntervalMs(uint32_t ms);
- 参数
- ms:每2帧通讯报文的间隔时间,毫秒;
- 返回值
- 无
8. 轮询总时间间隔 毫秒
/**
* @brief 轮询总时间间隔
*
* 所有帧通讯报文之间的间隔时间,即所有报文轮训一遍后等待一定时间后再进行下次轮训
*
* @param ms 所有帧通讯报文的间隔时间,毫秒;
*
* @return 无
*/
void SetPollTotalIntervalMs(uint32_t ms);
- 参数
- ms:所有帧通讯报文的间隔时间,毫秒;
- 返回值
- 无
9. 设置是否打印报文
/**
* @brief 设置是否打印报文(通过printf输出到命令行中)
*
* @param debug 是否开启,0-关闭;1-开启;
*
* @return 无
*/
void SetPollTotalIntervalMs(int debug);
- 参数
- debug :是否开启,0-关闭;1-开启;
- 返回值
- 无
10. 设置线圈单帧最大读点个数
11. 设置寄存器单帧最大读点个数
12. 设置收发报文内容回调函数
/**
* @brief 设置收发报文内容回调函数
*
* @param *s_callback 发送报文回调函数(参数,报文内容,报文长度);
* @param *r_callback 接收报文回调函数(参数,报文内容,报文长度);
* @param arg 回调参数;
*
* @return 无
*/
void set_MessageCallback(
void (*s_callback)(void *, const uint8_t *, int),
void (*r_callback)(void *, const uint8_t *, int),
void *arg = NULL);
- 参数
- *s_callback:发送报文回调函数(参数,报文内容,报文长度);
- *r_callback:接收报文回调函数(参数,报文内容,报文长度);
- arg:回调参数;
- 返回值
- 无
13. 设置收发报文内容回调使能
/**
* @brief 设置收发报文内容回调使能
*
* @param en 是否使能:0-未使能;1-使能;
*
* @return 无
*/
void set_MessagrCallbackEn(int en);
- 参数
- en:是否使能:0-未使能;1-使能;
- 返回值
- 无
14. 获取指定设备地址的通讯计数信息
/**
* @brief 获取指定设备地址的通讯计数信息
*
* @param slave 指定的Modbus设备站地址,1~255;
* @param *total_recvok_count 输出参数,总接收成功(通讯正常)的帧数量
* @param *total_recvfail_count 输出参数,总接收失败(通讯异常)的帧数量
* @param *curr_timout_count 输出参数,当前接收成功(通讯正常)的帧数量
*
* @return 是否获取成功:1-获取成功;-1-获取失败;
*/
int get_CommunicatCount(int slave,
uint64_t *total_recvok_count, uint64_t *total_recvfail_count,
uint64_t *curr_timout_count = NULL);
- 参数
- slave:指定的Modbus设备站地址,1~255;
- *total_recvok_count:输出参数,总接收成功(通讯正常)的帧数量
- *total_recvfail_count:输出参数,总接收失败(通讯异常)的帧数量
- *curr_timout_count:输出参数,当前接收成功(通讯正常)的帧数量
- 返回值
- 是否获取成功:1-获取成功;-1-获取失败;
三、ModbusTcpHostCh类
ModbusTcpHostCh类,继承自ModbusHostCh类,用于创建ModbusTcp主站通讯通道
1. 构造函数
/**
* @brief 构造函数
*
* @param *ipaddr IP地址,例"192.168.1.123";
* @param port 端口号,一般为502;
*/
ModbusTcpHostCh(const char *ipaddr, int port = 502);
- 参数
- *ipaddr:IP地址,例"192.168.1.123";
- port:端口号,一般为502;
- 返回值
- 返回值
2. 析构函数
3. 启动函数
- 参数
- 无
- 返回值
- 无
4. 设置回调函数-重连回调
/**
* @brief 设置回调函数-重连回调
*
* 当ModbusTcp发送连接断开自动进行重连时,会触发次回调函数
*
* @param fun 回调函数名;
* @param arg 回调函数;
*
* @return 无
*/
void SetFunReconnectCallback(fpReconnect_Callback fun, void *arg = NULL);
// 重连回调函数(参数,目标IP,目标端口,总重连次数,总重连成功次数,总重连失败次数, 当前失败次数)
typedef void (*fpReconnect_Callback)(void *arg,
const char* ip, const int port, const int rcount, const int rsconut, const int rfcount, const int crfcount);
- 参数
- fun:回调函数名;
- arg:回调参数;
- 返回值
- 无
四、ModbusHostDev类
Modbus主站模式下的站点类
1. 构造函数
构造函数,用于创建主站模式下的站点
/**
* @brief 构造函数
*
* @param pch ModbusHost通道
* @param slave 站地址
*/
ModbusHostDev(ModbusHostCh *pch, int slave = 1);
-
参数
-
pch: ModbusHost通道
- slave:站地址;
-
返回值
-
返回值
2. 析构函数
3. 获取站点ID
- 参数
- 无;
- 返回值
- 站地址
4. 添加回读数据块
/**
* @brief 添加循环回读数据块
*
* @param code 功能码;
* @param startaddr 点的起始地址,一般为0~65535;
* @param nb 点的个数;
* @param cycle 该数据块通讯周期
*
* @return 是否添加成功:
* 1 :添加成功;
* -1:站地址错误;
* -2:添加失败(数据越界);
* -3:添加失败(已存在冲突的数据块);
*/
int AddCycleReadDataBlock(ModbusHost::ReadCode_E code, int startaddr, int nb, int cycle = 1000);
-
参数
-
code 功能码;
- addr 点的起始地址,一般为0~65535;
- nb 点的个数;
- cycle 该数据块通讯周期
-
返回值
-
是否添加成功:1-添加成功;
5. 获取回读数据区多个连续数据点的值
/**
* @brief 获取回读数据区多个连续数据点的值
*
* 获取指定数据类型、多个连续点地址的值
*
* @param code 功能码;
* @param startaddr 点的起始地址,一般为0~65535;
* @param *point 返回参数,点的值;
* @param nb 点的数量;
*
* @return 是否获取成功:1-获取成功;-1-返回参数为空;-2-未找到数据块;
*/
int GetCycleReadDataBlookValue(ModbusHost::ReadCode_E code, int startaddr, uint16_t *point, int nb = 1);
-
参数
-
code 功能码;
- addr 点的起始地址,一般为0~65535;
- *value 返回参数,点的值;
- nb 点的个数;
-
返回值
-
是否获取成功:1-获取成功;-1-返回参数为空;-2-未找到数据块;
6. 添加写数据块
/**
* @brief 添加写数据块
*
* @param code 功能码;
* @param startaddr 点的起始地址,一般为0~65535;
* @param *value 点的值;
* @param nb 点的个数;
*
* @return 是否添加成功:
* 1 :添加成功;
* -1:站地址错误;
* -2:添加失败(数据越界);
*/
int AddWriteDataBlock(ModbusHost::WriteCode_E code, int startaddr, int *value, int nb = 1);
-
参数
-
code 功能码;
-
startaddr 点的起始地址,一般为0~65535;
- *value 点的值;
- nb 点的个数;
-
返回值
-
是否添加成功:
1 :添加成功;
-1:站地址错误;
-2:添加失败(数据越界);
7. 获取通讯超时状态
- 参数
- 无
- 返回值
- 通讯状态,0-未超时;1-超时;