当前位置:网站首页>三菱PLC slmp(mc)协议
三菱PLC slmp(mc)协议
2022-07-07 21:49:00 【weixin_39926429】
//对于三菱PLC,可参考mx component5.0(详见以前的文章)通讯
//本文自写解析协议。
//本文在 c++ builder平台和FX5U调试成功
#ifndef _SlmpProtocolClient_
#define _SlmpProtocolClient_
#include <winsock2.h>
#include <stdlib.h>
#include <iostream>
#include <string>
// using System.Net.Socket;
class SlmpProtocolClient
{
public:
SlmpProtocolClient();
~SlmpProtocolClient();
public :
int Open() ;
int Close();
int ReadDRegister(short address, short len, unsigned short* short_array);
int ReadMBit(short adress, short len, unsigned short* short_array);
int WriteDRegister(short address, unsigned short short_value);
int WriteMBit(short address, unsigned short short_value);
void init2();
public :
bool Connected;
private:
WSADATA wsaData;
sockaddr_in sockAddr;
SOCKET sock;
std::string tipstr[20], tipstr2[20];
void GetHighLowByte(const short addrss, unsigned char& HByte, unsigned char& LByte);
};
#endif
#include "SlmpProtocolClient.h"
//#include <winsock2.h> //
SlmpProtocolClient::SlmpProtocolClient()
{
init2();
}
void SlmpProtocolClient::init2() {
tipstr[0] = "固定";
tipstr[1] = "----";
tipstr[2] = "----";
tipstr[3] = "----";
tipstr[4] = "----";
tipstr[5] = "----";
tipstr[6] = "固定";
tipstr[7] = "长度L";
tipstr[8] = "长度H";
tipstr[9] = " 结束代码L";
tipstr[10] = " 结束代码H";
tipstr[11] = " DXXXn-L";
tipstr[12] = " DXXXn-H";
tipstr[13] = " DXXXn+1-L";
tipstr[14] = " DXXXn+1-H";
tipstr[15] = " DXXXn+2-L";
tipstr[16] = " DXXXn+2-H";
tipstr2[0] = "固定";
tipstr2[1] = "----";
tipstr2[2] = "----";
tipstr2[3] = "----";
tipstr2[4] = "----";
tipstr2[5] = "----";
tipstr2[6] = "固定";
tipstr2[7] = "长度L";
tipstr2[8] = "长度H";
tipstr2[9] = " 结束代码L";
tipstr2[10] = " 结束代码H";
tipstr2[11] = " Mn | Mn + 1";
tipstr2[12] = " MXXX2n+2| MXXXn + 3";
tipstr2[13] = " MXXXn+4| MXXXn + 5";
}
SlmpProtocolClient::~SlmpProtocolClient()
{
Close();
}
int SlmpProtocolClient::Close()
{
closesocket(sock);
//终止使用 DLL
WSACleanup();
Connected=false;
return 0;
}
int SlmpProtocolClient::Open()
{
WSAStartup(MAKEWORD(2, 2), &wsaData);
//创建套接字
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
//向服务器发起请求
memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充
sockAddr.sin_family = PF_INET;
sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//sockAddr.sin_addr.s_addr = inet_addr("192.168.10.150");
sockAddr.sin_port = htons(1234);
// sockAddr.sin_port = htons(4999);
int ret=connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
if (ret==0) {
Connected=true;
}
return ret;
}
int SlmpProtocolClient::ReadDRegister(short address,short len, unsigned short * short_array)
{
SYSTEMTIME sys, sy2;
int a = 0;
char* str = new char[30];
while (a <1)
{
/* GetLocalTime(&sys);
std::cout << sys.wSecond << ":" << sys.wMilliseconds << std::endl;*/
//50 00 00 FF FF 03 00 0C 00 10 00 01 04 00 00 64 00 00 A8 14 00
str[0] = 0x50;//本行开始的7行固定
str[1] = 0x00;
str[2] = 0x00;
str[3] = 0xFF;
str[4] = 0xFF;
str[5] = 0x03;
str[6] = 0x00;//本行及以上固定
str[7] = 0x0C;//长度L字节
str[8] = 0x00;//长度H字节
str[9] = 0x10;//监视定时器L
str[10] = 0x00;//监视定时器H
str[11] = 0x01;//CMD-批量读取-L
str[12] = 0x04;//CMD-批量读取-H
str[13] = 0x00;//子CMD-L
str[14] = 0x00;//子CMD-H
//str[15] = 0x64;//开始地址-L
//str[16] = 0x00;//开始地址-Middle
//str[15] = 0x40;//开始地址-L
//str[16] = 0x01;//开始地址-Middle
unsigned char hByte, lByte;
GetHighLowByte(address, hByte, lByte);
str[15] = lByte;//开始地址-L
str[16] = hByte;//开始地址-Middle
str[17] = 0x00;//开始地址-H
str[18] = 0xA8;//表示D点
unsigned char hByte2, lByte2;
//str[19] = 0x03;//读取长度-L
//str[20] = 0x00;//读取长度-H
GetHighLowByte(len, hByte2, lByte2);
str[19] = lByte2;//读取长度-L
str[20] = hByte2;//读取长度-H
send(sock, str, 21, NULL);//读取D寄存器的发送报文的长度=21字节
// Sleep(1);
//接收服务器传回的数据
char szBuffer[MAXBYTE] = { 0 };
int m;
m=recv(sock, szBuffer, MAXBYTE, NULL);
//输出接收到的数据
//printf("Message form server: %s\n", szBuffer);
//printf("Message form server:\n ");
/* for (size_t i = 0; i < 13; i++)
{
if ((unsigned char)szBuffer[i] < 16)
{
printf("0%x ", (unsigned char)szBuffer[i]);
}
else
{
printf("%x ", (unsigned char)szBuffer[i]);
}
std::cout << "--" << tipstr[i] << std::endl;
}*/
//读出的放在数组里,以下按数组的索引号从0开始说明含义
// szBuffer[0]:0xD0,--固定
// szBuffer[1]:0X00,--固定
// szBuffer[2]:0X00,--固定
// szBuffer[3]:0XFF,--固定
// szBuffer[4]:0XFF,--固定
// szBuffer[5]:0X03,--固定
// szBuffer[6]:0X00,--固定
// szBuffer[7]:响应数据长L字节,如读1个字:0x04,2字:0x06,三个字0x08,依次类推
// szBuffer[8]:响应数据长高字节
// --------从szBuffer[9]开始计算长度-----
// szBuffer[9]:0x00,--结束代码,如不为0则异常
// szBuffer[10]:0x00,--结束代码,如不为0则异常
// szBuffer[11]:Dn的L字节
// szBuffer[12]:Dn的H字节
// szBuffer[13]:Dn+1的L字节
// szBuffer[14]:Dn+1的H字节
// szBuffer[15]:Dn+2的L字节
// szBuffer[16]:Dn+2的H字节
// 接收完成后,第一步先看结束代码是否为0,如为0,进行下一步,否则丢弃数据了
// 第二步判断响应数据长是否等于2*字数+2,如相等,进行下一步
// 第三步从szBuffer[11]开始取几个字的数据,注意高低字节,如Dn=256*szBuffer[12]+szBuffer[11]
short end_code= 256 * (unsigned char)szBuffer[10] + (unsigned char)szBuffer[9];
if (end_code != 0)
{
return -1;
}
short response_len= 256 * (unsigned char)szBuffer[8] + (unsigned char)szBuffer[7];
if (response_len!=(len*2+2))
{
return -1;
}
for (size_t i = 0; i < len; i++)
{
*(short_array+i) = 256 * (unsigned char)szBuffer[12+i*2] + (unsigned char)szBuffer[11+i*2];
//std::cout << "读到的第"<<i+1<<"个字=" << *short_array << std::endl;
}
/*std::cout << "读到的第1个字=" << 256 * (unsigned char)szBuffer[12] + (unsigned char)szBuffer[11] << std::endl;
std::cout << "第2个字=" << 256 * (unsigned char)szBuffer[14] + (unsigned char)szBuffer[13] << std::endl;
std::cout << "第3个字=" << 256 * szBuffer[16] + szBuffer[15] << std::endl;*/
/*GetLocalTime(&sy2);
std::cout << std::endl;
std::cout << sy2.wSecond << ":" << sy2.wMilliseconds << std::endl;
std::cout << std::endl;*/
a++;
// Sleep(1);
}
delete[] str;
return 0;
}
int SlmpProtocolClient::WriteDRegister(short address, unsigned short short_value)
{
SYSTEMTIME sys, sy2;
int a = 0;
char* str = new char[30];
while (a < 1)
{
GetLocalTime(&sys);
std::cout << sys.wSecond << ":" << sys.wMilliseconds << std::endl;
//50 00 00 FF FF 03 00 0C 00 10 00 01 04 00 00 64 00 00 A8 14 00
str[0] = 0x50;//本行开始的7行固定
str[1] = 0x00;
str[2] = 0x00;
str[3] = 0xFF;
str[4] = 0xFF;
str[5] = 0x03;
str[6] = 0x00;//本行及以上固定
//str[7] = 0x12;//长度L字节--------写三个字0x12,写2个字,0x10,写一个字,0X0E
str[7] = 0x0E;//长度L字节--------写三个字0x12,写2个字,0x10,写一个字,0X0E
str[8] = 0x00;//长度H字节--------
str[9] = 0x10;//监视定时器L
str[10] = 0x00;//监视定时器H
str[11] = 0x01;//CMD-批量写-L
str[12] = 0x14;//CMD-批量写-H
str[13] = 0x00;//子CMD-L
str[14] = 0x00;//子CMD-H
//str[15] = 0x64;//开始地址-L-----变化
//str[16] = 0x00;//开始地址-Middle-----变化
unsigned char hByte, lByte;
GetHighLowByte(address, hByte, lByte);
str[15] = lByte;//开始地址-L
str[16] = hByte;//开始地址-Middle
str[17] = 0x00;//开始地址-H-----变化
str[18] = 0xA8;//表示D点
//str[19] = 0x03;//写入长度-L-------变化
str[19] = 0x01;//写入长度-L-------变化
str[20] = 0x00;//写入长度-H-------变化
//str[21] = 0x0C;//写入Dn-L-------变化
//str[22] = 0x00;//写入Dn-H-------变化
unsigned char hByte2, lByte2;
GetHighLowByte(short_value, hByte2, lByte2);
str[21] = lByte2;//读取长度-L
str[22] = hByte2;//读取长度-H
//str[23] = 0x0D;//写入Dn+1-L-------变化
//str[24] = 0x00;//写入Dn+1-H-------变化
//str[25] = 0x0E;//写入Dn+2-L-------变化
//str[26] = 0x00;//写入Dn+2-H-------变化
//"00 FF FF 03 00 0C 00 10 00 01 04 00 00 64 00 00 A8 01 00
//send(sock, str, strlen(str) + sizeof(char), NULL);
send(sock, str, 23, NULL);//-------------注意长度,写3个字:len=27,2个字:len=25,1个字:len=23
// Sleep(20);
//接收服务器传回的数据
char szBuffer[MAXBYTE] = { 0 };
recv(sock, szBuffer, MAXBYTE, NULL);
// PLC反馈: D0 00 00 FF FF 03 00 02 00 00 00 (00:14:55:188)
//输出接收到的数据
//printf("Message form server: %s\n", szBuffer);
if (0xD0 != (unsigned char)(szBuffer[0]) ) return 1;
if (0x02 != (unsigned char)szBuffer[7]) return 2;
if (0 != szBuffer[9]) return 3;
if (0 != szBuffer[10]) return 4;
/* GetLocalTime(&sy2);
std::cout << std::endl;
std::cout << sy2.wSecond << ":" << sy2.wMilliseconds << std::endl;
std::cout << std::endl;*/
a++;
Sleep(1);
}
delete[] str;
return 0;
}
int SlmpProtocolClient::ReadMBit(short address, short len, unsigned short* short_array)
{
SYSTEMTIME sys, sy2;
int a = 0;
char* str = new char[30];
unsigned short temp;
unsigned short q;
unsigned short m;
unsigned short n;
unsigned short k;
m = len % 16;
n = (m==0)? (len - m) / 16:(len - m) / 16+1;
while (a < 1)
{
// GetLocalTime(&sys);
//std::cout << sys.wSecond << ":" << sys.wMilliseconds << std::endl;
//50 00 00 FF FF 03 00 0C 00 10 00 01 04 00 00 64 00 00 A8 14 00
str[0] = 0x50;//本行开始的7行固定
str[1] = 0x00;
str[2] = 0x00;
str[3] = 0xFF;
str[4] = 0xFF;
str[5] = 0x03;
str[6] = 0x00;//本行及以上固定
str[7] = 0x0C;//长度L字节
str[8] = 0x00;//长度H字节
str[9] = 0x10;//监视定时器L
str[10] = 0x00;//监视定时器H
str[11] = 0x01;//CMD-批量读取-L
str[12] = 0x04;//CMD-批量读取-H
str[13] = 0x00;//子CMD-L
str[14] = 0x00;//子CMD-H
//str[15] = 0x64;//开始地址-L---变化
//str[16] = 0x00;//开始地址-Middle---变化
unsigned char hByte, lByte;
GetHighLowByte(address, hByte, lByte);
str[15] = lByte;//开始地址-L
str[16] = hByte;//开始地址-Middle
str[17] = 0x00;//开始地址-H---变化
str[18] = 0x90;//表示M点
unsigned char hByte2, lByte2;
//str[19] = 0x03;//读取长度-L
//str[20] = 0x00;//读取长度-H
GetHighLowByte(n, hByte2, lByte2);
str[19] = lByte2;//读取长度-L
str[20] = hByte2;//读取长度-H
send(sock, str, 21, NULL);// /读取M的发送报文的长度=21字节
// Sleep(20);
//接收服务器传回的数据
char szBuffer[MAXBYTE] = { 0 };
recv(sock, szBuffer, MAXBYTE, NULL);
//输出接收到的数据
//printf("Message form server: %s\n", szBuffer);
/* printf("Message form server:\n ");
for (int i = 0; i < 13; i++)
{
if ((unsigned char)szBuffer[i] < 16)
{
printf("0%x ", (unsigned char)szBuffer[i]);
}
else
{
printf("%x ", (unsigned char)szBuffer[i]);
}
std::cout << tipstr2[i] << std::endl;
}
GetLocalTime(&sy2);*/
//读出的放在数组里,以下按数组的索引号从0开始说明含义
// szBuffer[0]:0xD0,--固定
// szBuffer[1]:0X00,--固定
// szBuffer[2]:0X00,--固定
// szBuffer[3]:0XFF,--固定
// szBuffer[4]:0XFF,--固定
// szBuffer[5]:0X03,--固定
// szBuffer[6]:0X00,--固定
// szBuffer[7]:响应数据长L字节,如读<=16:0x04,2字:0x06,三个字0x08,依次类推
// szBuffer[8]:响应数据长高字节
// --------从szBuffer[9]开始计算长度-----
// szBuffer[9]:0x00,--结束代码,如不为0则异常
// szBuffer[10]:0x00,--结束代码,如不为0则异常
// szBuffer[11]:Mn~M(n+7)
// szBuffer[12]:M(n+8)~M(n+15)
// 接收完成后,第一步先看结束代码是否为0,如为0,进行下一步,否则丢弃数据了
// 第二步判断响应数据长是否等于2*字数,如相等,进行下一步
// 第三步从szBuffer[11]开始取几个字的数据,注意高低字节,
//如Mn= szBuffer[12]& 0x01,Mn(n+1)= szBuffer[12]& 0x02,M(n+15)= szBuffer[13]& 0x80,Mn(n+1)= szBuffer[12]& 0x02,
short end_code = 256 * (unsigned char)szBuffer[10] + (unsigned char)szBuffer[9];
if (end_code != 0)
{
return -1;
}
short response_len = 256 * (unsigned char)szBuffer[8] + (unsigned char)szBuffer[7];
if (response_len != (n * 2 + 2))
{
return -1;
}
k = 0;
unsigned u;
for (size_t i = 0; i <n; i++)
{
temp = 256 * (unsigned char)szBuffer[12 + i * 2] + (unsigned char)szBuffer[11 + i * 2];
u = temp;
for (size_t j = 0; j< 16; j++)
{
short_array[k] =( ((u & 1) == 0) ? 0 : 1);
u = u >> 1;
k++;
if (k>=len)
{
break;
}
}
}
/* unsigned short temp = 256 * (unsigned char)szBuffer[12] + (unsigned char)szBuffer[11];
bool b;
for (int i = 0; i < 16; i++)
{
b = (temp == 1) ? true : false;
std::cout << "第" << i + 1 << "位:" << b << std::endl;
temp = temp >> 1;
}*/
/* std::cout << std::endl;
std::cout << sy2.wSecond << ":" << sy2.wMilliseconds << std::endl;
std::cout << std::endl;*/
// delete[] str;
a++;
Sleep(1);
}
delete[] str;
return 0;
}
int SlmpProtocolClient::WriteMBit(short address, unsigned short short_value)
{
//SYSTEMTIME sys, sy2;
int a = 0;
char* str = new char[30];
while (a < 1)
{/*
GetLocalTime(&sys);
std::cout << sys.wSecond << ":" << sys.wMilliseconds << std::endl;*/
//50 00 00 FF FF 03 00 0C 00 10 00 01 04 00 00 64 00 00 A8 14 00
str[0] = 0x50;//本行开始的7行固定
str[1] = 0x00;
str[2] = 0x00;
str[3] = 0xFF;
str[4] = 0xFF;
str[5] = 0x03;
str[6] = 0x00;//本行及以上固定
str[7] = 0x0D;//长度L字节--------写三个字0x12,写2个字,0x10,写一个字,0X0E
str[8] = 0x00;//长度H字节--------
str[9] = 0x10;//监视定时器L
str[10] = 0x00;//监视定时器H
str[11] = 0x01;//CMD-批量写-L
str[12] = 0x14;//CMD-批量写-H
str[13] = 0x01;//子CMD-L
str[14] = 0x00;//子CMD-H
//str[15] = 0x64;//开始地址-L-----变化
//str[16] = 0x00;//开始地址-Middle-----变化
unsigned char hByte, lByte;
GetHighLowByte(address, hByte, lByte);
str[15] = lByte;//开始地址-L
str[16] = hByte;//开始地址-Middle
str[17] = 0x00;//开始地址-H-----变化
str[18] = 0x90;//表示M点
str[19] = 0x01;//写入长度-L-------变化
str[20] = 0x00;//写入长度-H-------变化
str[21] = ((short_value==0)?0x00:0x10);//写入Mn,M(n+1)-------变化
//str[22] = 0x00;//写入M(n+2),M(n+3)------变化
//"50 00 00 FF FF 03 00 0D 00 10 00 01 14 01 00 64 00 00 90 01 00 10
//send(sock, str, strlen(str) + sizeof(char), NULL);
send(sock, str, 22, NULL);//-------------注意长度,写3个字:len=27,2个字:len=25,1个字:len=23
// Sleep(20);
//接收服务器传回的数据
char szBuffer[MAXBYTE] = { 0 };
recv(sock, szBuffer, MAXBYTE, NULL);
//输出接收到的数据
//printf("Message form server: %s\n", szBuffer);
/* printf("Message form server:\n ");
for (size_t i = 0; i < 11; i++)
{
if ((unsigned char)szBuffer[i] < 16)
{
printf("0%x ", (unsigned char)szBuffer[i]);
}
else
{
printf("%x ", (unsigned char)szBuffer[i]);
}
std::cout << "--" << tipstr[i] << std::endl;
}
GetLocalTime(&sy2);
std::cout << std::endl;
std::cout << sy2.wSecond << ":" << sy2.wMilliseconds << std::endl;
std::cout << std::endl;*/
// PLC反馈: D0 00 00 FF FF 03 00 02 00 00 00 (00:14:55:188)
//输出接收到的数据
//printf("Message form server: %s\n", szBuffer);
if (0xD0 != (unsigned char)(szBuffer[0])) return 1;
if (0x02 != (unsigned char)szBuffer[7]) return 2;
if (0 != szBuffer[9]) return 3;
if (0 != szBuffer[10]) return 4;
a++;
Sleep(1);
}
delete[] str;
return 0;
}
void SlmpProtocolClient::GetHighLowByte(const short addrss, unsigned char & HByte, unsigned char & LByte)
{
LByte = addrss % 256;
HByte = (addrss - LByte) / 256;
}
边栏推荐
- What does the model number of asemi rectifier bridge kbpc1510 represent
- Line test - graphic reasoning - 3 - symmetric graphic class
- 2022 words for yourself
- Yarn开启ACL用户认证之后无法查看Yarn历史任务日志解决办法
- Matplotlib quick start
- CTF练习
- This time, let's clear up: synchronous, asynchronous, blocking, non blocking
- Leetcode interview question 02.07 Linked list intersection [double pointer]
- Some parameters of Haikang IPC
- Debezium series: support the use of variables in the Kill Command
猜你喜欢

ASP.NET Core入门五

数据库每日一题---第22天:最后一次登录

Two minutes, talk about some wrong understandings of MySQL index

行测-图形推理-2-黑白格类

Use JfreeChart to generate curves, histograms, pie charts, and distribution charts and display them to jsp-2

How to judge whether the input content is "number"

Line test - graphic reasoning -7- different graphic classes

Line test - graphic reasoning - 6 - similar graphic classes

Unity and webgl love each other

聊聊 Dart 的空安全 (null safety) 特性
随机推荐
Why is network i/o blocked?
行测-图形推理-8-图群类
LeetCode203. Remove linked list elements
How pyGame rotates pictures
IP network active evaluation system -- x-vision
What is ADC sampling rate (Hz) and how to calculate it
行測-圖形推理-4-字母類
Install mxnet GPU version
ADC采样率(HZ)是什么怎么计算
Redis集群安装
Debezium系列之:源码阅读之BinlogReader
Two minutes, talk about some wrong understandings of MySQL index
Unity与WebGL的相爱相杀
Unity technical notes (II) basic functions of scriptableobject
Debezium series: set role statement supporting mysql8
0-5VAC转4-20mA交流电流隔离变送器/转换模块
Yarn cannot view the historical task log of yarn after enabling ACL user authentication. Solution
Robot autonomous exploration series papers environment code
Use JfreeChart to generate curves, histograms, pie charts, and distribution charts and display them to jsp-2
What is fake sharing after filling the previous hole?