当前位置:网站首页>三菱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;
}
边栏推荐
- php 获取图片信息的方法
- Debezium系列之: 支持在 KILL 命令中使用变量
- Gbu1510-asemi power supply special 15A rectifier bridge gbu1510
- Yarn开启ACL用户认证之后无法查看Yarn历史任务日志解决办法
- Redis cluster installation
- Online interview, how to better express yourself? In this way, the passing rate will be increased by 50%~
- 不夸张地说,这是我见过最通俗易懂的,pytest入门基础教程
- Form组件常用校验规则-2(持续更新中~)
- Failed to initialize rosdep after installing ROS
- 微生物健康网,如何恢复微生物群落
猜你喜欢

消息队列与快递柜之间妙不可言的关系

Robot autonomous exploration DSVP: code parsing

「开源摘星计划」Loki实现Harbor日志的高效管理

微生物健康網,如何恢複微生物群落

Line test - graphic reasoning - 1 - Chinese character class

Leetcode206. Reverse linked list

知识点滴 - PCB制造工艺流程

It's no exaggeration to say that this is the most user-friendly basic tutorial of pytest I've ever seen

Signal feature extraction +lstm to realize gear reducer fault diagnosis -matlab code

There is another problem just online... Warm
随机推荐
Basic knowledge of binary tree
Pyqt GUI interface and logic separation
【测试面试题】页面很卡的原因分析及解决方案
Unity technical notes (I) inspector extension
Online interview, how to better express yourself? In this way, the passing rate will be increased by 50%~
Unity and webgl love each other
Digital transformation: five steps to promote enterprise progress
消费品企业敏捷创新转型案例
IP network active evaluation system -- x-vision
Microbial Health Network, How to restore Microbial Communities
筑起云端 “免疫”屏障,让你的数据有备无患
ASEMI整流桥KBPC1510的型号数字代表什么
php 记录完整对接腾讯云直播以及im直播群聊 所遇到的坑
Unity technical notes (II) basic functions of scriptableobject
苹果在iOS 16中通过'虚拟卡'安全功能进一步进军金融领域
php 获取图片信息的方法
LeetCode707. Design linked list
微服务架构开源框架详情介绍
详解全志V853上的ARM A7和RISC-V E907之间的通信方式
微服务远程Debug,Nocalhost + Rainbond微服务开发第二弹