WhyCan Forum(哇酷开发者社区)

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn

您尚未登录。

#1 2020-11-19 13:09:13

thy442156388
会员
所在地: 新疆乌鲁木齐
注册时间: 2018-10-21
累计积分: 72

Modbus TCP通信问题!

本人最近尝试使用NUC977与PLC之间进行通信, 测试PC端使用模拟软件,Modbus Poll和Modbus Slave测试,但是发现一个奇怪的问题:
1. PLC作为Server,NUC977作为Client,同时Modbus Poll检测通信结果,可以通信;
2. NUC977作为Server,PLC作为Client,同时Modbus Poll检测通信结果,可以通信;
3. Nuc977作为Server,另一个NUC977作为Client,作为Client的NUC977读取不到数据,但是Modbus Poll可以正确读取到结果,通信失败。
想请教一下有没有使用过libmodbus的大神,给点建议,这中间哪里出了问题??附上NUC977的Modbus代码。
PS:PLC和PC模拟测均是使用很久的厂家提供代码,应该不存在问题。
Server端代码

void *modbusTcp_process(void *arg)
{
    uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
    int master_socket;
    int rc;
    fd_set refset;
    fd_set rdset;
    /* Maximum file descriptor number */
    int fdmax;

    ctx = modbus_new_tcp("192.168.150.159", 502);
    printf("Modbus Context Created OK!\n");
    mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 
                                    MODBUS_MAX_WRITE_BITS,
                                    MODBUS_MAX_READ_REGISTERS, 
                                    MODBUS_MAX_WRITE_REGISTERS);
    if (mb_mapping == NULL)
    {
        fprintf(stderr, "Failed to allocate the mapping: %s\n",
                modbus_strerror(errno));
        modbus_free(ctx);
        exit(-1);
    }

    server_socket = modbus_tcp_listen(ctx, NB_CONNECTION);
    if (server_socket == -1)
    {
        fprintf(stderr, "Unable to listen TCP connection\n");
        modbus_free(ctx);
        exit(-1);
    }

    signal(SIGINT, close_sigint);

    /* Clear the reference set of socket */
    FD_ZERO(&refset);
    /* Add the server socket */
    FD_SET(server_socket, &refset);

    /* Keep track of the max file descriptor */
    fdmax = server_socket;

    for (;;)
    {
        rdset = refset;
        
        if (select(fdmax + 1, &rdset, NULL, NULL, NULL) == -1)
        {
            perror("Server select() failure.");
            close_sigint(1);
        }

        /* Run through the existing connections looking for data to be
            * read */
        for (master_socket = 0; master_socket <= fdmax; master_socket++)
        {

            if (!FD_ISSET(master_socket, &rdset))
            {
                continue;
            }

            if (master_socket == server_socket)
            {
                /* A client is asking a new connection */
                socklen_t addrlen;
                struct sockaddr_in clientaddr;
                int newfd;

                /* Handle new connections */
                addrlen = sizeof(clientaddr);
                memset(&clientaddr, 0, sizeof(clientaddr));
                newfd = accept(server_socket, (struct sockaddr *)&clientaddr, &addrlen);
                if (newfd == -1)
                {
                    perror("Server accept() error");
                }
                else
                {
                    FD_SET(newfd, &refset);

                    if (newfd > fdmax)
                    {
                        /* Keep track of the maximum */
                        fdmax = newfd;
                    }
                    printf("New connection from %s:%d on socket %d\n",
                           inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port, newfd);
                }
            }
            else
            {
                modbus_set_socket(ctx, master_socket);
                rc = modbus_receive(ctx, query);
                if (rc > 0)
                {
                    update_modbusmapping(mb_mapping);
                    modbus_reply(ctx, query, rc, mb_mapping);
                }
                else if (rc == -1)
                {
                    /* This example server in ended on connection closing or
                        * any errors. */
                    printf("Connection closed on socket %d\n", master_socket);
                    close(master_socket);

                    /* Remove from reference set */
                    FD_CLR(master_socket, &refset);

                    if (master_socket == fdmax)
                    {
                        fdmax--;
                    }
                }
            }
        }
    }
}

Client端代码

void *modbusTcp_process(void *arg){
	modbus_t *ctx;

    char index = 0;
    float fl1;
	int i=0;
    /* TCP 127.0.0.1 port 502*/
    ctx = modbus_new_tcp("192.168.150.159", 502);
	if (modbus_set_slave(ctx, 1) == -1)
    {
        fprintf(stderr, "Invalid slave ID\n");
        modbus_free(ctx);
        exit(-1);
    }
    if (modbus_connect(ctx) == -1)
    {
        fprintf(stderr, "Modbus connect failed: %s\n",
                modbus_strerror(errno));
        modbus_free(ctx);
        exit(-1);
    }
	while(1){
		modbus_read_registers(ctx, WT_START_ADDR, 
			24, modbusDataBuf);
		printf("Read hold rigister %d.\n",sizeof(modbusDataBuf));
		//ModbudDataPrase(modbusDataBuf);
		ModbusReceived = 1;
		//debug_LoadData_print();
		for(i=0;i<12;i++)
			printf("modbusDataBuf%d %7d\n",i,modbusDataBuf[i]);

        index++;
	}

    /*turn off connect*/
    modbus_close(ctx);
    modbus_free(ctx);
}

离线

#2 2020-11-19 13:47:32

smartcar
会员
注册时间: 2018-02-19
累计积分: 704

Re: Modbus TCP通信问题!

有没有试过抓包,看用你的client和plc client,数据包的收发有没有区别?

离线

#3 2020-11-19 14:04:17

thy442156388
会员
所在地: 新疆乌鲁木齐
注册时间: 2018-10-21
累计积分: 72

Re: Modbus TCP通信问题!

smartcar 说:

有没有试过抓包,看用你的client和plc client,数据包的收发有没有区别?

使用调试模式看一下结果么 ? 我看Libmodbus有一个调试模式,ModbusPoll中间有一个traffic monitor。你的意思是使用这两个对比一下,看接收到的数据包之间有没有差别么 ?

离线

#4 2020-11-19 14:16:34

smartcar
会员
注册时间: 2018-02-19
累计积分: 704

Re: Modbus TCP通信问题!

wireshark/commview 之类的网络抓包工具

离线

#5 2020-11-19 17:18:11

thy442156388
会员
所在地: 新疆乌鲁木齐
注册时间: 2018-10-21
累计积分: 72

Re: Modbus TCP通信问题!

我用调试模式测试了下,发现NUC977的ModbusServer 正常,提供服务中,但是NUC977客户端却一直提示请求超时,
服务器调试日志

Waiting for a indication...
<0D><32><00><00><00><06><01><03><00><00><00><18>
[0D][32][00][00][00][33][01][03][30][00][00][73][16][73][16][73][16][73][16][73][16][73][16][73][16][73][16][73][16][73][16][73][16][73][16][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]
ERROR Broken pipe
Waiting for a indication...
<0D><33><00><00><00><06><01><03><00><00><00><18>
[0D][33][00][00][00][33][01][03][30][00][00][73][16][73][16][73][16][73][16][73][16][73][16][73][16][73][16][73][16][73][16][73][16][73][16][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]
ERROR Broken pipe
Waiting for a indication...
<0D><34><00><00><00><06><01><03><00><00><00><18>
[0D][34][00][00][00][33][01][03][30][00][00][73][17][73][17][73][17][73][17][73][17][73][17][73][16][73][16][73][16][73][16][73][16][73][16][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]
ERROR Broken pipe
Waiting for a indication...
<0D><35><00><00><00><06><01><03><00><00><00><18>
[0D][35][00][00][00][33][01][03][30][00][00][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]
ERROR Broken pipe
Waiting for a indication...
<0D><36><00><00><00><06><01><03><00><00><00><18>
[0D][36][00][00][00][33][01][03][30][00][00][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]
ERROR Broken pipe
Waiting for a indication...
<0D><37><00><00><00><06><01><03><00><00><00><18>
[0D][37][00][00][00][33][01][03][30][00][00][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]
ERROR Broken pipe
Waiting for a indication...
<0D><38><00><00><00><06><01><03><00><00><00><18>
[0D][38][00][00][00][33][01][03][30][00][00][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]
ERROR Broken pipe
Waiting for a indication...
<0D><39><00><00><00><06><01><03><00><00><00><18>
[0D][39][00][00][00][33][01][03][30][00][00][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][73][27][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]
ERROR Broken pipe
Waiting for a indication...

ERROR Broken pipe 是由于NUC977的Modbus客户端连接出错导致的,正常响应客户端为ModbusPoll软件(PC模拟软件)的结果。
客户端调试记录

[00][05][00][00][00][06][01][03][00][00][00][18]
Waiting for a confirmation...
ERROR Connection timed out: select
Read hold rigister 120.
[00][06][00][00][00][06][01][03][00][00][00][18]
Waiting for a confirmation...
ERROR Connection timed out: select
Read hold rigister 120.
[00][07][00][00][00][06][01][03][00][00][00][18]
Waiting for a confirmation...
ERROR Connection timed out: select
Read hold rigister 120.
[00][08][00][00][00][06][01][03][00][00][00][18]
Waiting for a confirmation...
ERROR Connection timed out: select
Read hold rigister 120.
[00][09][00][00][00][06][01][03][00][00][00][18]
Waiting for a confirmation...
ERROR Connection timed out: select
Read hold rigister 120.
[00][0A][00][00][00][06][01][03][00][00][00][18]
Waiting for a confirmation...
ERROR Connection timed out: select
Read hold rigister 120.
[00][0B][00][00][00][06][01][03][00][00][00][18]
Waiting for a confirmation...
ERROR Connection timed out: select
Read hold rigister 120.
[00][0C][00][00][00][06][01][03][00][00][00][18]
Waiting for a confirmation...
ERROR Connection timed out: select

!!!!!怀疑会不是是nuc977的网卡配置有问题
Modbus的代码应该没问题,因为对PLC以及PC端的模拟软件都做过交叉测试,都可以正确收发数据。

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB