一.实例测试方法
1.modbus模拟从站选择。
使用“Modbus Slave”工具模拟,如下所示。
配置modbus从站的数据
以功能码3,其实地址为210为例子。Int64的空间占8个字节,由于modbus每个寄占器占2个字节,因此这边需要配置4个寄存器,从210开始,到213结束。如下图所示。
3.在linux下运行程序采集modbus的交互流程及结果显示。
4.查看“Modbus Slave”通信报文,如下图所示。
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();
}