modbusTcp 从站和主站

主要测试读保持寄存器,地址4xxxx开始。不废话直接上代码

下面是从站(server)代码:


#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <iostream>

#include "modbus.h"
#include "modbus-tcp.h"
#include "modbus-version.h"

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

 
#define NB_CONNECTION    5
 

//读保持寄存器地址数据的定义
const uint16_t UT_REGISTERS_ADDRESS = 0;
/* Raise a manual exception when this adress is used for the first byte */
const uint16_t UT_REGISTERS_ADDRESS_SPECIAL = 0;
const uint16_t UT_REGISTERS_NB = 0x10;
const int UT_REGISTERS_TAB[] = { 0x022B, 0x0001, 0x0064 };
const float test[] = { 123.123, 4.012, 5.789, 12345.34, 223.4, 34.2, 33.44, 234.204};
/* If the following value is used, a bad response is sent.
   It's better to test with a lower value than
   UT_REGISTERS_NB_POINTS to try to raise a segfault. */
const uint16_t UT_REGISTERS_NB_SPECIAL = 0x2;

 
modbus_t *ctx = NULL;
int server_socket;
modbus_mapping_t *mb_mapping;
 
static void close_sigint(int dummy)
{
    close(server_socket);
    modbus_free(ctx);
    modbus_mapping_free(mb_mapping);
 
    exit(dummy);
}
 
 
int FloatTohex(float HEX)//浮点数到十六进制转换
{
	return *( int *)&HEX;
}
 
int main(void)
{
    int master_socket;
    int rc;
    int header_length;
    fd_set refset;
    fd_set rdset;
 
    /* Maximum file descriptor number */
    int fdmax;
 
    ctx = modbus_new_tcp("10.88.33.26", 10086);
 
    header_length = modbus_get_header_length(ctx);
    //new一个modbus的映射空间A
    mb_mapping = modbus_mapping_new(
        0,//读线圈
        0,//读离散量输入
        UT_REGISTERS_ADDRESS + UT_REGISTERS_NB,//读保持寄存器
        0);//读输入寄存器
    if (mb_mapping == NULL)
    {
        fprintf(stderr, "Failed to allocate the mapping: %s\n",
                modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    /**初始化读保持寄存器**/
    for(int i=0; i<8; i++)
    {
        
        uint16_t aimReg[2] = { 0 };
        MODBUS_SET_INT32_TO_INT16(aimReg, 0, FloatTohex(test[i]));
        std::cout<<std::hex<<FloatTohex(test[i])<<"; " << std::hex<<aimReg[0]<<", "<<std::hex<<aimReg[1]<<"\n";
        for(int j = 0; j< 2; j++){
            mb_mapping->tab_registers[UT_REGISTERS_ADDRESS+i*2+j]= aimReg[j];
        }
    }
 
    server_socket = modbus_tcp_listen(ctx, NB_CONNECTION);
 
    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))
            {
                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
                {
                    /* An already connected master has sent a new query */
                    uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
                    modbus_set_socket(ctx, master_socket);
                    rc = modbus_receive(ctx, query);
                    if (rc != -1)
                    {
                        modbus_reply(ctx, query, rc, mb_mapping);
                    }
                    else
                    {
                        /* Connection closed by the client, end of server */
                        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--;
                        }
                    }
                }
            }
        }
    }
 
    return 0;
}

我们可以通过modscan32工具来读取数据测试。

下面是主站(client)代码:

#include <stdio.h>

#ifndef _MSC_VER
#include <unistd.h>
#endif

#include <string.h>
#include <stdlib.h>
#include <errno.h>

//包含Modbus相关头文件
#include "modbus.h"
#include "time.h"

//相关参数设置
#define LOOP	1			//循环次数
#define ADDRESS_START	0       //测试寄存器起始地址
#define ADDRESS_END	15	//测试寄存器结束地址

int FloatTohex(float HEX){ return *( int *)&HEX; }


int main(void)
{
	modbus_t* ctx = NULL;


	int ret = -1;
	int nums = 0;
	int addr = 0;
	int i = 0;
	int tmp = 0;

	uint16_t* tab_rq_registers = NULL;
	uint16_t* tab_rp_registers = NULL;

	//设置随机种子
	srand((int)time(0));

	//1. 创建一个TCP类型的变量
	ctx = modbus_new_tcp("10.88.33.26", 10086);
	if (NULL == ctx)
	{
		fprintf(stderr, "Error: %s\n", modbus_strerror(errno));
		return 1;
	}
	else
	{
		printf("设置TCP成功\n");
	}


	//2. 设置Debug模式
	ret = modbus_set_debug(ctx, TRUE);
	if (-1 == ret)
	{
		fprintf(stderr, "Error: 设置Debug模式失败");
		modbus_free(ctx);
		return 1;
	}

	//3. 连接Server
	ret = modbus_connect(ctx);
	if (-1 == ret)
	{
		fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
		modbus_free(ctx);
		return 1;
	}

	//4. 计算需测试的寄存器个数
	nums = ADDRESS_END - ADDRESS_START;

	//5. 申请内存 保存发送和接收的数据
	tab_rq_registers = (uint16_t*)malloc((nums + 1) * sizeof(uint16_t));
	if (NULL == tab_rq_registers)
	{
		fprintf(stderr, "malloc failed\n");
		modbus_free(ctx);
		return 1;
	}
	else
	{
		memset(tab_rq_registers, 0, (nums + 1) * sizeof(uint16_t));
	}


	//7. 测试保持寄存器的单个读写
//随机数字
	const float test[] = { 13.123, 24.012, 5.789, 233.23,11.22,33.44,55.66, 77.88};
	for(int i=0; i< 8; i++)
    {
        
        uint16_t aimReg[2] = { 0 };
        MODBUS_SET_INT32_TO_INT16(aimReg, 0, FloatTohex(test[i]));
        for(int j = 0; j< 2; j++){
            tab_rq_registers[i*2+j]= aimReg[j];
        }
    }
	//换行
	printf("\n");

	addr = ADDRESS_START;

	ret = modbus_write_registers(ctx, addr, nums + 1, tab_rq_registers);
	if (nums + 1 != ret)
	{
		printf("Error modbus_write_registers: %d\n", ret);
		printf("Address: %d nums: %d\n", addr, nums + 1);
	}
	else
	{
		//读取
		printf("success to write");
	}


	//8. 释放内存
	free(tab_rq_registers);

	//9. 断开连接
	modbus_close(ctx);
	modbus_free(ctx);

	return 0;
}

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值