Modbus-INT64数据类型采集及解析

一.实例测试方法

1.modbus模拟从站选择。

使用“Modbus Slave”工具模拟,如下所示。

配置modbus从站的数据

以功能码3,其实地址为210为例子。Int64的空间占8个字节,由于modbus每个寄占器占2个字节,因此这边需要配置4个寄存器,从210开始,到213结束。如下图所示。

Modbus-INT64数据类型采集及解析_第1张图片

3.在linux下运行程序采集modbus的交互流程及结果显示。

Modbus-INT64数据类型采集及解析_第2张图片

4.查看“Modbus Slave”通信报文,如下图所示。

Modbus-INT64数据类型采集及解析_第3张图片

  • 代码实现及编译

2.1在linux下创建一个名为“mdbs_int64.c”的文件,并复制以下的代码到该文件。

2.2代码编译:gcc -o m mdbs_int64.c

2.3代码运行测试:./m

至此,关于modbus int64类型数据采集及解析流程已经介绍完成。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define BUFSZIE 256

/*
日志打印管理
*/
void LOG(const char *format,...)
{
        va_list argptr;
        char buffer[2048];
        va_start(argptr,format);
        vsprintf(buffer,format,argptr);
        va_end(argptr);
        printf("%s", buffer);

}

/*
缓存日志打印管理
*/
void LOG_DUMP_BUF(char *label, unsigned char *in, int len)
{

    int i=0;
    LOG("%s:\n", label);
    for(i=0;i0) {
        LOG_DUMP_BUF("send==>", in, len);
        return send(sk, in, len, 0);
    }
    return 0;
}

/*
数据接收回调函数
*/
int mdbs_msg_recv(void *fd, unsigned char *out, int len)
{
    int *skfd = (int *)fd;
    int sk = *skfd;
    if(sk>0) {
        int ret= recv(sk, out,len, 0);
        LOG_DUMP_BUF("recv==>", out, ret);
        return ret;
    }
    return 0;
}

int mdbs_start_connect(int *sockfd,char *ip,unsigned short port)
{
        int iRet;
        struct sockaddr_in host;
        fd_set mask;
        iRet=0;
        *sockfd=-1;
        if ((0==port) || 0==strlen(ip))
        {
                LOG("invalid param");
                return 0;
        }
        host.sin_family=AF_INET;
        host.sin_port=htons(port);
        LOG("connect %s:%u\n",ip,port);
        inet_aton(ip,&host.sin_addr);
        if ( (*sockfd=socket(AF_INET,SOCK_STREAM,0))<0 )
        {
                LOG("create sock err");
                iRet=0;
                goto err_out;
        }

        iRet=connect(*sockfd,(struct sockaddr *)&host,sizeof(host));
        if(iRet==0) {
                LOG("connect succ\n");
                if(fcntl(*sockfd,F_SETFL,O_NDELAY) < 0 )
                {
                        LOG("set sock non_block error");
                        iRet=0;
                        LOG("fcntl err");
                        goto err_out;

                }
                return 1;
        }
        LOG("iRet:%d\n", iRet);
err_out:
        return (iRet);

}

/*
TCP链接初始化
*/
int mdbs_tcp_connect_init(char *svr, int port)
{
        int iRet, sockfd = -1;
        iRet=mdbs_start_connect(&sockfd,svr, port);
        if (iRet == 0)
                return -1;
        return sockfd;
}

/*
Modbus数据请求
*/
int mdbs_int64_data_reqst(mdbs_t *m, unsigned char *out)
{
    //00 00 00 00 00 06 01 03 00 D2 00 04
    unsigned char in[64]="";
    int len = 0;
    in[len++]=0x00;
    in[len++]=0x00;
    in[len++]=0x00;
    in[len++]=0x00;
    in[len++]=0x00;
    in[len++]=0x06;
    in[len++]=m->devaddr;
    in[len++]=m->func;
    in[len++]=m->startaddr/256;
    in[len++]=m->startaddr%256;
    in[len++]=m->regcnt/256;
    in[len++]=m->regcnt%256;

    if(m->msg_send) {
        m->msg_send(m->fd, in, len);
    }
    usleep(20000);
    if(m->msg_recv) {
        return m->msg_recv(m->fd, out, BUFSZIE);
    }
    return 0;
}

/*
Modbus数据解析
*/
void mdbs_int64_data_parser(unsigned char *in, int len)
{
    //00 00 00 00 00 0b 01 03 08 00 00 00 00 00 00 00 08
    int pkglen = in[4];
    pkglen=pkglen*256+in[5]+6;
    if(pkglen!=len) {
        LOG("pkglen err!\n");
        return;
    }

    unsigned char tmp[8]="";
    memcpy(tmp, &in[9],8);
    long long l=0;
    int i;
    for(i=0;i<8;i++) {
        l = l*256+tmp[i];
    }

    LOG("result:%lld\n", l);

}

void mdbs_int64_test()
{
    mdbs_t m;
    int ret = 0;
    int skfd = mdbs_tcp_connect_init("192.168.4.127",502);
    m.devaddr = 1;
    m.func = 3;
    m.startaddr = 210;
    m.regcnt = 4;//64位需要4个寄存器的空间
    m.msg_recv = mdbs_msg_recv;
    m.msg_send = mdbs_msg_send;
    m.fd = &skfd;

    unsigned char out[BUFSZIE]="";
    ret = mdbs_int64_data_reqst(&m, out);

    if(ret>0) {
        mdbs_int64_data_parser(out, ret);
    }

}

void main()
{
    mdbs_int64_test();

}

你可能感兴趣的:(C,linux,运维,服务器)