libmodbus學(xué)習(xí)(二)之Modbus TCP

一、以太網(wǎng)(modbus tcp/ip)

Modbus設(shè)備可分為主站(poll)和從站(slave)。主站只有一個(gè),從站有多個(gè),主站向各從站發(fā)送請(qǐng)求幀,從站給予響應(yīng)。在使用TCP通信時(shí),主站為client端,主動(dòng)建立連接;從站為server端,等待連接。

image.png

二、所需的libmobus API(server端)

  1. 使用modbus_new_tcp創(chuàng)建一個(gè)modbus的上下文,ip地址為開發(fā)板自身的ip
modbus_t *ctx = modbus_new_tcp(const char *ip_address, int port); //開發(fā)板ip自行修改,port常用502。
  1. 地址映射
    使用modbus_mapping_new_start_address初始化從站地址的映射,即線圈狀態(tài)、離散輸入、保持寄存器、輸入寄存器的首地址和個(gè)數(shù)的映射。該首地址供主站進(jìn)行尋址讀取數(shù)值或?qū)懭霐?shù)值。
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的地址空間,即給相應(yīng)指針開辟空間。該空間為后續(xù)寫入和讀取數(shù)據(jù)使用。

    /* map 地址與存儲(chǔ)空間 */
    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.監(jiān)聽連接
使用以上創(chuàng)建的modbus tcp server監(jiān)聽客戶的接入

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

4.阻塞接收數(shù)據(jù)
接收主站的請(qǐng)求數(shù)據(jù)(原始數(shù)據(jù))并保存在req指定的空間中。

modbus_receive(modbus_t *ctx, uint8_t *req);

5.響應(yīng)接收
modbus_reply會(huì)自動(dòng)解析modbus請(qǐng)求并做響應(yīng)

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); //開發(fā)板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;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容