libmodbus学习(二)之Modbus TCP

一、以太网(modbus tcp/ip)

Modbus设备可分为主站(poll)和从站(slave)。主站只有一个,从站有多个,主站向各从站发送请求帧,从站给予响应。在使用TCP通信时,主站为client端,主动建立连接;从站为server端,等待连接。

image.png

二、所需的libmobus API(server端)

  1. 使用modbus_new_tcp创建一个modbus的上下文,ip地址为开发板自身的ip
modbus_t *ctx = modbus_new_tcp(const char *ip_address, int port); //开发板ip自行修改,port常用502。
  1. 地址映射
    使用modbus_mapping_new_start_address初始化从站地址的映射,即线圈状态、离散输入、保持寄存器、输入寄存器的首地址和个数的映射。该首地址供主站进行寻址读取数值或写入数值。
modbus_mapping_t *mb_mapping = modbus_mapping_new_start_address(
    unsigned int start_bits, unsigned int nb_bits,
    unsigned int start_input_bits, unsigned int nb_input_bits,
    unsigned int start_registers, unsigned int nb_registers,
    unsigned int start_input_registers, unsigned int nb_input_registers);

完成mb_mapping的映射后需要绑定table的地址空间,即给相应指针开辟空间。该空间为后续写入和读取数据使用。

    /* map 地址与存储空间 */
    mb_mapping->tab_bits = UT_BITS_TAB;
    mb_mapping->tab_input_bits = UT_INPUT_BITS_TAB;
    mb_mapping->tab_registers = UT_REGISTERS_TAB;
    mb_mapping->tab_input_registers = UT_INPUT_REGISTERS_TAB;

3.监听连接
使用以上创建的modbus tcp server监听客户的接入

int socket = modbus_tcp_listen(modbus_t *ctx, int nb_connection);
modbus_tcp_accept(modbus_t *ctx, int *s);

4.阻塞接收数据
接收主站的请求数据(原始数据)并保存在req指定的空间中。

modbus_receive(modbus_t *ctx, uint8_t *req);

5.响应接收
modbus_reply会自动解析modbus请求并做响应

modbus_reply(modbus_t *ctx, const uint8_t *req,
                            int req_length, modbus_mapping_t *mb_mapping);

三、从站(server)程序

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

#include <modbus/modbus.h>

int main(void)
{
    int socket;
    modbus_t *ctx;
    modbus_mapping_t *mb_mapping;

    ctx = modbus_new_tcp("127.0.0.1", 1502); //开发板ip自行修改
    /* modbus_set_debug(ctx, TRUE); */

    mb_mapping = modbus_mapping_new_start_address(
        UT_BITS_ADDRESS, UT_BITS_NB,
        UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB,
        UT_REGISTERS_ADDRESS, UT_REGISTERS_NB_MAX,
        UT_INPUT_REGISTERS_ADDRESS, UT_INPUT_REGISTERS_NB);

    if (mb_mapping == NULL) {
        fprintf(stderr, "Failed to allocate the mapping: %s\n",
                modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    socket = modbus_tcp_listen(ctx, 1);
    modbus_tcp_accept(ctx, &socket);

    for (;;) {
        uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
        int rc;

        rc = modbus_receive(ctx, query);
        if (rc != -1) {
            /* rc is the query size */
            modbus_reply(ctx, query, rc, mb_mapping);
            printf("In the loop \n");
        } else {
            /* Connection closed by the client or error */
            break;
        }
    }

    printf("Quit the loop: %s\n", modbus_strerror(errno));

    modbus_mapping_free(mb_mapping);
    modbus_close(ctx);
    modbus_free(ctx);

    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容