基于libmodbus实现文件传输功能

一、libmodbus 下载

二、更改modbus.c和modbus.h文件

1、首先在modbus.h文件中增加读写文件记录的函数声明。
在这里插入图片描述

//fileNumber  文件名
//startRecordNumber   起始文件记录号
//fileData    需要写入文件的数据
//length      写入文件的数据长度
MODBUS_API int modbus_write_file_record(modbus_t *ctx, uint16_t fileNumber, uint16_t startRecordNumber,
                                        const uint16_t *fileData, uint8_t length);

//fileNumber   文件名
//startRecordNumber  起始文件记录号
//length    需要读取文件数据的长度
//dest      读取到的文件数据存放目标
MODBUS_API int modbus_read_file_record(modbus_t *ctx, uint16_t fileNumber, uint16_t startRecordNumber,
                                       uint16_t length, uint16_t *dest);

2、modbus.h文件中增加读写文件宏定义。
在这里插入图片描述

#define MODBUS_FC_READ_FILE_RECORD          0x14
#define MODBUS_FC_WRITE_FILE_RECORD         0x15

3、modbus.c文件计算读取数据长度函数中增加文件读写的处理。
在这里插入图片描述

        if (function <= MODBUS_FC_READ_INPUT_REGISTERS ||
            function == MODBUS_FC_REPORT_SLAVE_ID ||
            function == MODBUS_FC_WRITE_AND_READ_REGISTERS ||
            function == MODBUS_FC_READ_FILE_RECORD ||
            function == MODBUS_FC_WRITE_FILE_RECORD)
        {
            length = msg[ctx->backend->header_length + 1];
        }
        else
        {
            length = 0;
        }

4、在modbus.c文件计算响应数据长度函数中增加。
在这里插入图片描述

    case MODBUS_FC_WRITE_FILE_RECORD:
        length = 9 + 2 * (req[offset + 7] << 8 | req[offset + 8]);
        break;
    case MODBUS_FC_READ_FILE_RECORD:
        length = 4 + 2 * (req[offset + 7] << 8 | req[offset + 8]);
        break;

在这里插入图片描述
由协议文档可得,写文件收到的回应数据长度应为:
(Record length Hi << 8 | Record length Lo) * 2 + 前面9个除文件数据以外的固定回复数据。
在这里插入图片描述
由协议文档可得,读文件收到的回应数据长度应为:
(Record length Hi << 8 | Record length Lo) * 2 + 前面4个除文件数据以外的固定回复数据。

5、在校验函数中增加读写文件的处理。
在这里插入图片描述
在这里插入图片描述

        case MODBUS_FC_READ_FILE_RECORD:
            /* 保证req_nb_value 和 rsp_nb_value 计算后的值相等,才会通过校验 */
            req_nb_value = (req[offset + 7] << 8) + req[offset + 8];
            rsp_nb_value = ((rsp[offset + 2] - 1) / 2);
            break;
        case MODBUS_FC_WRITE_FILE_RECORD:
            req_nb_value = (req[offset + 7] << 8) + req[offset + 8];
            rsp_nb_value = (rsp[offset + 7] << 8) | rsp[offset + 8];
            break;

这里写文件发送和回复的数据长度是一样的。
在这里插入图片描述
读文件回复数据长度 = (File resp.length - 1) / 2

三、写文件函数定义

int modbus_write_file_record(modbus_t *ctx, uint16_t fileNumber, uint16_t startRecordNumber,
                             const uint16_t *fileData, uint8_t length)
{
    int rc;
    int req_length;
    uint8_t req[MAX_MESSAGE_LENGTH];

    if (ctx == NULL || length <= 0) {
        errno = EINVAL;
        return -1;
    }

    if(fileNumber == 0)
    {
        errno = EINVAL;
        return -1;
    }

	//起始文件记录号范围是  0000-9999
    if(startRecordNumber > 0x270F)
    {
        errno = EINVAL;
        return -1;
    }

	//文件传输一次最多传输122个数据
    if( length > 122 )
    {
        errno = EINVAL;
        return -1;
    }

    req_length = ctx->backend->build_request_basis(ctx,
                                                   MODBUS_FC_WRITE_FILE_RECORD,
                                                   0,0,req);

    req[2] = length*2 + 7;                //request Data length
    req[3] = 0x06;                        //reference type must be specified as 6

    req[4] = fileNumber >> 8;             //File Number High
    req[5] = fileNumber & 0x00ff;         //File Number Low

    req[6] = startRecordNumber >> 8;      //The starting record number high within the file
    req[7] = startRecordNumber & 0x00ff;  //The starting record number low within the file

    req[8] = length >> 8;                 //The length of the record to be written
    req[9] = length & 0x00ff;             //The length of the record to be written

    for(int i = 0; i < length; i++)
    {
        req[2*i + 10] = fileData[i] >> 8;
        req[2*i + 11] = fileData[i] & 0x00ff;
    }

    rc = send_msg(ctx, req, length*2 + 10);
    if (rc > 0)
    {
        uint8_t rsp[MAX_MESSAGE_LENGTH];

        rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);
        if (rc == -1)
            return -1;

        rc = check_confirmation(ctx, req, rsp, rc);
        if (rc == -1)
            return -1;
    }

    return rc;
}

四、读文件函数定义

int modbus_read_file_record(modbus_t *ctx, uint16_t fileNumber, uint16_t startRecordNumber,
                            uint16_t length, uint16_t *dest)
{
    int rc;
    int req_length;
    uint8_t req[MAX_MESSAGE_LENGTH];

    if (ctx == NULL || length <= 0) 
    {
        errno = EINVAL;
        return -1;
    }

    if(fileNumber == 0)
    {
        errno = EINVAL;
        return -1;
    }
    
    //起始文件记录号范围是  0000-9999
    if(startRecordNumber > 0x270F)
    {
        errno = EINVAL;
        return -1;
    }

    req_length = ctx->backend->build_request_basis(ctx,
                                                   MODBUS_FC_READ_FILE_RECORD,
                                                   0,0,req);

    req[2] = 7;                           //request Data length
    req[3] = 0x06;                        //reference type must be specified as 6

    req[4] = fileNumber >> 8;             //File Number High
    req[5] = fileNumber & 0x00ff;         //File Number Low

    req[6] = startRecordNumber >> 8;      //The starting record number high within the file
    req[7] = startRecordNumber & 0x00ff;  //The starting record number low within the file

    req[8] = length >> 8;                 //The length of the record to be written
    req[9] = length & 0x00ff;             //The length of the record to be written

	rc = send_msg(ctx, req, 10);
    if (rc > 0)
    {
        int offset;
        int i;
        uint8_t rsp[MAX_MESSAGE_LENGTH];

        rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);
        if (rc == -1)
            return -1;

        rc = check_confirmation(ctx, req, rsp, rc);
        if (rc == -1)
            return -1;

        offset = ctx->backend->header_length;

        for (i = 0; i < rc; i++)
        {
            /* shift reg hi_byte to temp OR with lo_byte */
            dest[i] = (rsp[offset + 4 + (i << 1)] << 8) |
                rsp[offset + 5 + (i << 1)];
        }
    }

	return rc;
}

五、函数接口用法简单示例
1、写文件。

uint16_t modbusData[122];
for(int i = 0; i < 122; i++)
{
	modbusData[i] = i;
}
modbus_write_file_record(modbus, 1, 1, modbusData,2);

2、读文件。

uint16_t modbusData[100];
modbus_read_file_record(modbus, 1, 1, 2, modbusData)

for(int i = 0; i < 2; i++)
{
	cout << i << ":" << modbusData[i] << endl;
}

六、用串口助手测试
1、写文件测试。
在这里插入图片描述
附上写文件回复的示例数据:
01 15 0D 06 00 01 00 01 00 03 4F 60 59 7D FF 01 19 8B

2、读文件测试。
在这里插入图片描述
附上读文件回复的示例数据:
01 14 06 05 06 4F 60 59 7D 05 71

七、也可以直接下载我改完的modbus.c和modbus.h文件,替换掉原来的文件就可以直接用了

文件下载链接

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: libmodbus是一个开源的用于Modbus通信协议的C语言库文件。Modbus是一种通信协议,常用于工业自动化领域,在现代工业控制系统中得到广泛应用。libmodbus库文件提供了一系列函数,用于实现Modbus通信协议的各种功能。 libmodbus库文件的特点如下: 1. 开源:libmodbus是一个开源的库文件,开放源代码,这意味着用户可以自由地使用、修改和分发这个库文件,非常便于二次开发和定制化需求。 2. 跨平台:libmodbus库文件支持多个操作系统,包括Linux、Windows、Mac等,以及多个嵌入式平台,如ARM、MIPS等,便于在不同的硬件平台上使用。 3. 多种通信方式:libmodbus库文件支持多种通信方式,包括串口(RS-232、RS-485)、以太网(TCP/IP)等,用户可以根据实际需求选择合适的通信方式。 4. 支持多种Modbus协议:libmodbus库文件支持多种Modbus协议,包括Modbus RTU、Modbus ASCII和Modbus TCP等,用户可以根据实际应用场景选择合适的协议。 5. 提供丰富的功能函数:libmodbus库文件提供了一系列功能函数,用于实现读取和写入Modbus设备的输入寄存器、保持寄存器等数据,还可以实现Modbus主机和从机的通信等功能。 6. 完善的文档和示例:libmodbus库文件提供了详细的文档和示例程序,帮助用户快速上手并理解如何使用该库文件。 总的来说,libmodbus是一个强大的Modbus通信协议库文件,具有开源、跨平台、多种通信方式、支持多种Modbus协议、丰富的功能函数以及完善的文档和示例等优点,为用户提供了方便、高效的Modbus通信解决方案。 ### 回答2: libmodbus库文件是一个用于Modbus通信协议的开源库文件。Modbus是一种常用的工业通信协议,用于在不同设备之间进行数据交换。libmodbus库文件提供了一组函数和工具,使开发者能够轻松地实现Modbus通信功能。 libmodbus库文件支持多个通信方式,包括串口通信和TCP/IP通信。对于串口通信,libmodbus库文件提供了一套函数,可以方便地进行串口的初始化、打开、关闭和读写操作。对于TCP/IP通信,libmodbus库文件同样提供了相应的函数,可以创建和管理TCP连接,并进行数据的读写操作。 libmodbus库文件支持Modbus RTU和Modbus TCP两种通信方式。对于Modbus RTU通信,libmodbus库文件支持数据的读写以及读写多个寄存器。对于Modbus TCP通信,libmodbus库文件支持数据的读写以及读写多个寄存器,并且提供了一些额外的功能,如异步通信和从站状态检测。 libmodbus库文件还提供了一些工具,用于辅助开发者进行Modbus通信的调试和测试。其中,最常用的工具是modbus_client,它可以作为Modbus主站与从站进行交互,方便地测试和验证Modbus通信的正确性。 总之,libmodbus库文件是一个功能强大的开源库文件,可以帮助开发者轻松地实现和管理Modbus通信功能。无论是在工业自动化、能源管理还是其他领域,libmodbus库文件都是一个十分值得使用的工具。 ### 回答3: libmodbus是一个开源的Modbus通信协议库文件,用于在计算机系统上实现Modbus通信协议。它提供了一组用于创建Modbus主站和从站的函数和接口,方便用户通过串行线路或以太网来实现Modbus通信。 libmodbus库文件支持多种不同的Modbus通信方式,包括RTU(二进制方式)、ASCII(文本方式)和TCP/IP(以太网方式)。用户可以根据实际应用场景选择合适的通信方式进行数据传输。 利用libmodbus库文件,用户可以轻松地创建和管理Modbus通信的主站或从站设备。主站设备可以通过调用库文件中提供的函数来发送查询(请求)命令,从站设备可以通过该库文件轮询命令并回复相应的应答。 除了基本的Modbus通信功能,libmodbus库文件还提供了许多附加功能,如异常处理、超时设置、并发处理、错误检测等。这些功能可以帮助用户更加可靠地实现Modbus通信,并提高通信的稳定性和效率。 总之,libmodbus库文件提供了一套丰富的函数和接口,用于在计算机系统上实现Modbus通信协议。它简化了Modbus通信的开发和管理过程,使用户能够更方便地创建和使用Modbus主站和从站设备。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值