Modbus TCP Client开发步骤 点击:1356 | 回复:0



opcfan

    
  • 精华:0帖
  • 求助:0帖
  • 帖子:62帖 | 58回
  • 年度积分:0
  • 历史总积分:667
  • 注册:2004年9月29日
发表于:2008-01-18 11:13:00
楼主
  开发OPC服务器需要开发相应的通信程序(搞电气的人习惯喊驱动)
在这里谈一下比较常用的Modbus TCP现场总线协议的开发。


在这里我采用API的方式使用Socket, 
第一步:添加头文件和库文件 
#include "winsock2.h" 
wsock32.lib 
第二步:用WSAStartup函数初始化Winsock.dll 
   int errCode; 
m_wVersionRequested = MAKEWORD( 1, 1 ); 
errCode = WSAStartup( m_wVersionRequested, &(m_WSAData) ); 
if ( errCode != 0 ) 

  m_wsaInitialized = FALSE; 

else 

  m_wsaInitialized = TRUE; 

  说明:由于Winsock目前有两个版本:2.2和1.1。1.1版本的DLL为Winsock.dll,而2.2版本的DLL则为Wsock32.dll。 
  WSAStartup函数函数原型为: int WSAStartup (WORD wVersionRequested,LPWSADATA lpWSAData); 其第一个参数为Winsock版本!低字节为主版本,高字节为副版本!由于目前Winsock有两个版本:1.1和2.2,因此该参数可以是0x101或0x202;第2个参数是一个WSADATA结构,用于接收函数的返回信息!WSAStartup函数调用成功会返回0,否则返回非0值! 

第三步:创建Socket套接字
  m_socket = socket(PF_INET, SOCK_STREAM, 0); 
  if (INVALID_SOCKET == m_socket)  // recommended NT error check
  {
   GetSockError(errStr);
   sprintf(debugStr, "Cannot create Link socket :%s",errStr);
   OutputDebugString(debugStr);
   return FALSE;
  }
  创建套接字有两个函数,socket和WSASocket,前者是标准的Socket函数,而后者是微软对Socket的扩展函数。socket函数有3个参数,第一个是指定通信发生的区域,在UNIX下有AF_UNIX、AF_INET、AF_NS等,而在Winsock1.1下只支持AF_INET,到了2.2则添了AF_IRDA(红外线通信)、AF_ATM(异步网络通信)、AF_NS、AF_IPX等;第2个参数是套接字的类型,在AF_INET地址族下,有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW三种套接字类型。SOCK_STREAM也就是通常所说的TCP,而SOCK_DGRAM则是通常所说的UDP,而SOCK_RAW则是用于提供一些较低级的控制的;第3个参数依赖于第2个参数,用于指定套接字所用的特定协议,设为0表示使用默认的协议。socket函数调用成功返回一个套接字描述符,错误则返回SOCKET_ERROR。
  我们是在Windows操作系统下写Modbus TCP Client程序,所以在这里的第一个参数是PF_INET,第二个参数是SOCK_STREAM。

第四步:连接服务器

  if(connect(m_socket, (LPSOCKADDR)&m_destSockaddr_in, sizeof(SOCKADDR)) < 0)
  {
   shutdown(m_socket, SD_BOTH);
   closesocket(m_socket);
   m_socket = INVALID_SOCKET;
   return FALSE;
  }

connect函数有3个参数,第1个是连接所使用的套接字描述符,第2个参数是一个sockaddr结构,sockaddr结构是一个通用的结构,它只是简单地定义了一个字节数组。在TCP/IP下一般将其解释为sockaddr_in结构,第3个参数则是该结构的长度,一般用sizeof函数来取得。connect函数调用失败则返回SOCKET_ERROR。

第五步:发送和接收数据

dwWritten = send(m_socket, (CHAR*)msg->m_buffer, msg->m_wLength, 0);
send函数有4个参数:
第一个是发送操作所用的套接字描述符;
第二个是所要发送的数据缓冲区的地址为CHAR类型,至于其它类型的数据可以用强制类型转换CHAR。在接收端再用强制类型转换转换回来;
第三个参数是所发送的缓冲区的大小,也就是所要发送的字节数;
第四个参数是一个附加标志,如果对所发送的数据没特殊要求,则直接设为0。
CMODMessage msg; 
msg.Add(0x00);
msg.Add(0x00);
msg.Add(0x00);
msg.Add(0x00);
msg.Add(0x00);
msg.Add(0x06);
msg.Add(0x01);
msg.Add(0x02);
msg.Add(0x00);
msg.Add(0x00);
msg.Add(0x00);
msg.Add(0x0A);
针对Modbus TCP,发送之前用msg来组合发送的数据帧。这里是读02 Input Status寄存器的0X0000到0X000A的数据。

dwRead = recv(m_socket, &input, RX_QUEU, 0);

recv函数的参数也是4个,其涵义与send函数差不多。只是其第二个参数是指向用于接收数据的缓冲区的地址。
msg->m_buffer[msg->m_wLength++] = input;

第六步:断开连接 用closesocket 

第七步:退出程序 
  if(m_wsaInitialized) 
{
   WSACleanup();
}


热门招聘
相关主题

官方公众号

智造工程师