国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

linux 下 C++ 與三菱PLC 通過MC Qna3E 二進(jìn)制 協(xié)議進(jìn)行交互

這篇具有很好參考價(jià)值的文章主要介紹了linux 下 C++ 與三菱PLC 通過MC Qna3E 二進(jìn)制 協(xié)議進(jìn)行交互。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

西門子plc 有snap7庫 進(jìn)行交互,并且支持c++ 而且跨平臺(tái)。但是三菱系列PLC并沒有現(xiàn)成的開源項(xiàng)目,沒辦法只能自己拼接,我這里實(shí)現(xiàn)了MC 協(xié)議 Qna3E 幀,并使用二進(jìn)制進(jìn)行交互。

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>

#include <mutex>
#include <string>
using namespace std;

namespace MelsecMC
{
    class PlcSocket
    {
    private:
        bool is_open;
        int global_socket_fd; // 用于發(fā)送/接受數(shù)據(jù)
        mutex m;

    public:
        PlcSocket();
        ~PlcSocket();

        // 初始化socket
        bool initSocket(string ip, int port, int milSecond);
        // 關(guān)閉socket
        bool closeSocket();
        // 發(fā)送數(shù)據(jù)
        bool write(unsigned char *buffer, int len);
        // 接收數(shù)據(jù)
        bool read(unsigned char *buffer, int len);
    };
}
#include "socket.h"
#include <chrono>
#include <thread>

namespace MelsecMC
{
    PlcSocket::PlcSocket()
    {
        global_socket_fd = -1;
    }

    PlcSocket::~PlcSocket()
    {
    }

    bool PlcSocket::initSocket(string ip, int port, int milSecond)
    {
        // create
        int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (socket_fd == -1)
        {
            cout << "socket 創(chuàng)建失敗:" << endl;
            return false;
        }

        struct sockaddr_in addr;
        addr.sin_family = PF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr(ip.c_str());

        // connect
        int res = connect(socket_fd, (struct sockaddr *)&addr, sizeof(addr));
        if (res == -1)
        {
            cout << "connect 鏈接失敗:" << endl;
            return false;
        }
        cout << "connect 鏈接成功:" << endl;

        // 設(shè)置timeout
        setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)20, sizeof(int));
        setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)20, sizeof(int));

        cout << "setsockopt 成功:" << endl;
        global_socket_fd = socket_fd;

        return true;
    }
    bool PlcSocket::write(unsigned char *buffer, int len)
    {
        m.lock();
        long result = send(global_socket_fd, buffer, len, 0);
        m.unlock();
        if (result < 0)
        {
            return false;
        }
        return true;
    }
    bool PlcSocket::read(unsigned char *buffer, int len)
    {
        m.lock();
        long result = recv(global_socket_fd, buffer, len, 0);
        m.unlock();
        if (result < 0)
        {
            cout << "recv失敗:" << endl;
            return false;
        }
        return true;
    }
    bool PlcSocket::closeSocket()
    {
        close(global_socket_fd);
        return true;
    }
}
/***
MC協(xié)議的通訊方式有很多種:4C、3C、2C、1C、4E、3E、1E幀格式 數(shù)據(jù)格式分為二進(jìn)制格式和ASCII碼格式
本代碼采用 3E + 二進(jìn)制格式
https://www.jianshu.com/p/ca7f1609c8c1
***/
#pragma once
#include <sys/sem.h>
#include <sys/shm.h>
#include <iostream>
#include <memory>
#include "socket.h"

namespace MelsecMC
{
    class MelsecMcClient : public std::enable_shared_from_this<MelsecMcClient>
    {
    public:
        using Ptr = std::shared_ptr<MelsecMcClient>;

        explicit MelsecMcClient();
        ~MelsecMcClient();
   
        bool connectTo(const string & ip, int port);
	    bool disconnect();

        bool readInt32(std::string area,int start,int &value);
        bool writeInt32(std::string area,int start,int value);

        bool readShort(std::string area,int start,short &value);
        bool writeShort(std::string area,int start,short value);

    private:
        PlcSocket socket;
        unsigned char head[7] = {0x50,0x00,0x00,0xFF,0xFF,0x03,0x00};
    
    private:
        unsigned char decodeArea(std::string area);
    };
}
#include "client.h"
#include <sstream>
#include <iomanip>
namespace MelsecMC
{
    MelsecMcClient::MelsecMcClient()
    {
    }

    MelsecMcClient::~MelsecMcClient()
    {
        disconnect();
    }

    bool MelsecMcClient::connectTo(const string &ip, int port)
    {
        return socket.initSocket(ip, port, 2000);
    }

    bool MelsecMcClient::disconnect()
    {
        return socket.closeSocket();
    }

    bool MelsecMcClient::writeInt32(std::string area,int start,int value)
    {
        unsigned char cmd[25] = {0};
        // 頭
        memcpy(cmd, head, 7);

        //50 00 00 FF FF 03 00   10 00   0A 00   01 14  00 00    64 00 00   A8  02 00  01 00 00 00 寫1
        //請求數(shù)據(jù)物理長度
        cmd[7] = 0x10;
        cmd[8] = 0x00;

        // CPU監(jiān)視定時(shí)器 表示等待PLC響應(yīng)的timeout時(shí)間
        cmd[9] = 0x0A;
        cmd[10] = 0x00;

        //寫命令 跟讀的差別是:讀是0104,寫是0114 ;就是04和14的差別
        cmd[11] = 0x01;
        cmd[12] = 0x14;

        //(子命令) : 值是0表示按字讀寫入1個(gè)字=16位),如果值是1就按位寫入
        cmd[13] = 0x00;
        cmd[14] = 0x00;

        //(首地址):地址因?yàn)榭缍缺容^大,所以用了3個(gè)字節(jié);值640000  返過來是000064,十進(jìn)制就是100
        cmd[17] = start / 255 / 255 % 255;
        cmd[16] = start / 255 % 255;
        cmd[15] = start % 255;

        //(軟元件 讀取的區(qū)域) : 表示讀取PLC寄存器的類型: 這里的A8表示D點(diǎn);其他常見的有: 90-M點(diǎn);9C-X點(diǎn);9D-Y點(diǎn);B0-ZR外部存儲(chǔ)卡
        unsigned char areaHex = decodeArea(area);
        if (areaHex == 0x00)
        {
            std::cout << "不存在的地址 " << area << std::endl;
            return false;
        }
        cmd[18] = areaHex;

        //寫入長度 00 02  =10進(jìn)制2個(gè)字 =32位 = 4個(gè)字節(jié) =1個(gè)int
        cmd[19] = 0x02;
        cmd[20] = 0x00;

        //寫入int值
        cmd[24] = (value >> 24) & 0xFF;
        cmd[23] = (value >> 16) & 0xFF;  
        cmd[22] = (value >> 8) & 0xFF;
        cmd[21] = value & 0xFF;

        if (!socket.write(cmd, sizeof(cmd)))
        {
            return false;
        }

        // 讀取數(shù)據(jù)
        unsigned char recv[512] = {0};
        if (!socket.read(recv, sizeof(recv)))
        {
            return false;
        }
        if (recv[0] != 0xD0 && recv[1] != 0x00)
        {
            std::cout << "數(shù)據(jù)格式不正確" << std::endl;
            return false;
        }

        return true;
    }

    bool MelsecMcClient::readInt32(std::string area, int start, int &value)
    {
        unsigned char cmd[21] = {0};
        // 頭
        memcpy(cmd, head, 7);

        //請求數(shù)據(jù)長度 也要反過來,值是000C,也就是12;表示后面的報(bào)文內(nèi)容的長度是12
        cmd[7] = 0x0C;
        cmd[8] = 0x00;

        // CPU監(jiān)視定時(shí)器 表示等待PLC響應(yīng)的timeout時(shí)間
        cmd[9] = 0x0A;
        cmd[10] = 0x00;

        // 批量讀命令 值是0401(所有值都要反過來看);表示批量讀??;如果是1401就是隨機(jī)寫取;
        cmd[11] = 0x01;
        cmd[12] = 0x04;

        //(子命令) : 值是0表示按字讀取(1個(gè)字=16位),如果值是1就按位讀取
        cmd[13] = 0x00;
        cmd[14] = 0x00;

        //(首地址):地址因?yàn)榭缍缺容^大,所以用了3個(gè)字節(jié);值640000  返過來是000064,十進(jìn)制就是100
        cmd[17] = start / 255 / 255 % 255;
        cmd[16] = start / 255 % 255;
        cmd[15] = start % 255;

        //(軟元件 讀取的區(qū)域) : 表示讀取PLC寄存器的類型: 這里的A8表示D點(diǎn);其他常見的有: 90-M點(diǎn);9C-X點(diǎn);9D-Y點(diǎn);B0-ZR外部存儲(chǔ)卡
        unsigned char areaHex = decodeArea(area);
        if (areaHex == 0x00)
        {
            std::cout << "不存在的地址 " << area << std::endl;
            return false;
        }
        cmd[18] = areaHex;

        // 讀取長度 00 02  =10進(jìn)制2個(gè)字 =32位 = 4個(gè)字節(jié) =1個(gè)int
        cmd[19] = 0x02;
        cmd[20] = 0x00;

        // 發(fā)送數(shù)據(jù)
        if (!socket.write(cmd, sizeof(cmd)))
        {
            return false;
        }

        // 讀取數(shù)據(jù)
        unsigned char recv[512] = {0};
        if (!socket.read(recv, sizeof(recv)))
        {
            return false;
        }

        // 解析數(shù)據(jù)
        // D0 00 00 FF FF 03 00 06 00 00 00 BB 02 96 49
        // D0 00 (響應(yīng)) :表示反饋信息,固定D0 00
        // 00 (網(wǎng)絡(luò)編號 ): 與上同
        // FF (PLC編號) : 與上同
        // FF 03 (請求目標(biāo)模塊IO編號) : 與上同
        // 00 (請求目標(biāo)模塊站編號): 與上同
        // 06 00  應(yīng)答數(shù)據(jù)物理長度
        if (recv[0] != 0xD0 && recv[7] != 0x06)
        {
            std::cout << "數(shù)據(jù)格式不正確" << std::endl;
            return false;
        }
        value = recv[14] << 24 | recv[13] << 16 | recv[12] << 8 | recv[11];
        std::cout << "value " << value << std::endl;
        return true;
    }

    bool MelsecMcClient::readShort(std::string area,int start,short &value){
        unsigned char cmd[21] = {0};
        memcpy(cmd, head, 7);

        cmd[7] = 0x0C;
        cmd[8] = 0x00;

        cmd[9] = 0x0A;
        cmd[10] = 0x00;

        cmd[11] = 0x01;
        cmd[12] = 0x04;

        cmd[13] = 0x00;
        cmd[14] = 0x00;

        cmd[17] = start / 255 / 255 % 255;
        cmd[16] = start / 255 % 255;
        cmd[15] = start % 255;

        unsigned char areaHex = decodeArea(area);
        if (areaHex == 0x00)
        {
            std::cout << "不存在的地址 " << area << std::endl;
            return false;
        }
        cmd[18] = areaHex;

        cmd[19] = 0x01;
        cmd[20] = 0x00;

        if (!socket.write(cmd, sizeof(cmd)))
        {
            return false;
        }

        unsigned char recv[512] = {0};
        if (!socket.read(recv, sizeof(recv)))
        {
            return false;
        }

        if (recv[0] != 0xD0 && recv[7] != 0x04)
        {
            std::cout << "數(shù)據(jù)格式不正確" << std::endl;
            return false;
        }
        value = recv[12] << 8 | recv[11];
        std::cout << "value " << value << std::endl;
        return true;
    }
    
    bool MelsecMcClient::writeShort(std::string area,int start,short value){
        unsigned char cmd[23] = {0};
        memcpy(cmd, head, 7);

        cmd[7] = 0x0E;
        cmd[8] = 0x00;

        cmd[9] = 0x0A;
        cmd[10] = 0x00;

        cmd[11] = 0x01;
        cmd[12] = 0x14;

        cmd[13] = 0x00;
        cmd[14] = 0x00;

        cmd[17] = start / 255 / 255 % 255;
        cmd[16] = start / 255 % 255;
        cmd[15] = start % 255;

        unsigned char areaHex = decodeArea(area);
        if (areaHex == 0x00)
        {
            std::cout << "不存在的地址 " << area << std::endl;
            return false;
        }
        cmd[18] = areaHex;

        cmd[19] = 0x01;
        cmd[20] = 0x00;

        //寫入short值 
        cmd[22] = (value >> 8) & 0xFF;
        cmd[21] = value & 0xFF;

        if (!socket.write(cmd, sizeof(cmd)))
        {
            return false;
        }

        unsigned char recv[512] = {0};
        if (!socket.read(recv, sizeof(recv)))
        {
            return false;
        }
        if (recv[0] != 0xD0 && recv[1] != 0x00)
        {
            std::cout << "數(shù)據(jù)格式不正確" << std::endl;
            return false;
        }

        return true;
    }

    unsigned char MelsecMcClient::decodeArea(std::string area)
    {
        if (area == "D")
        {
            return 0xA8;
        }
        else if (area == "M")
        {
            return 0x90;
        }
        else if (area == "X")
        {
            return 0x9C;
        }
        else if (area == "Y")
        {
            return 0x9D;
        }
        else if (area == "ZR")
        {
            return 0xB0;
        }
        else
        {
            return 0x00;
        }
    }
}
#include "client.h"

using namespace MelsecMC;

int main(int argc, char **argv)
{
    MelsecMcClient::Ptr client = std::make_shared<MelsecMcClient>();
    client->connectTo("10.10.14.60",6000);

    //int value;
    //melsecMcNet->readInt32("D",100,value);

    //client->writeInt32("D",101,122234);
    //client->writeShort("D",102,223);
    short value;
    client->readShort("D",102,value);
    return 0;
}

可利用 這個(gè)工具進(jìn)行測試:

linux 下 C++ 與三菱PLC 通過MC Qna3E 二進(jìn)制 協(xié)議進(jìn)行交互,C++,c++,linux,交互,三菱 plc,MC Qna3E

?協(xié)議參考:

https://www.jianshu.com/p/ca7f1609c8c1文章來源地址http://www.zghlxwxcb.cn/news/detail-696984.html

到了這里,關(guān)于linux 下 C++ 與三菱PLC 通過MC Qna3E 二進(jìn)制 協(xié)議進(jìn)行交互的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 三菱PLC通過三菱FX1N-232BD模塊與威綸通觸摸屏設(shè)置

    三菱PLC通過三菱FX1N-232BD模塊與威綸通觸摸屏設(shè)置

    1.PLC編程設(shè)置,通過GX Developer編程軟件設(shè)置PLC參數(shù)如圖1 所示 注意紅色框設(shè)置選擇的參數(shù)設(shè)置,綠色框參數(shù)設(shè)置配置要和威綸通EasyBuilder Pro的參數(shù)一直即可。 注意:PLC參數(shù)設(shè)置完成后,下載到PLC中,然后PLC需要斷電,在啟動(dòng)設(shè)置的參數(shù)才能生效。 2.維綸觸摸屏編程軟件EasyBu

    2024年02月12日
    瀏覽(73)
  • python實(shí)現(xiàn)MC協(xié)議(SLMP 3E幀)的TCP服務(wù)端

    python實(shí)現(xiàn)MC協(xié)議(SLMP 3E幀)的TCP服務(wù)端

    python實(shí)現(xiàn)MC協(xié)議(SLMP 3E幀)的TCP服務(wù)端是一件稍微麻煩點(diǎn)的事情。它不像modbusTCP那樣,可以使用現(xiàn)成的pymodbus模塊去實(shí)現(xiàn)。但是,我們可以根據(jù)協(xié)議幀進(jìn)行組包,自己去實(shí)現(xiàn)幀的格式,而這一切可以基于socket模塊。本文為第一篇。 參考文檔:三菱PLC之SLMP協(xié)議報(bào)文說明 - 知乎

    2024年02月06日
    瀏覽(12)
  • 三菱PLC 流水燈控制

    三菱PLC 流水燈控制

    方式一思路:每一秒讓計(jì)數(shù)器 C0 的值加一,然后將 C0 對應(yīng)的值賦值給輸出燈 Y10 - Y15。 方式二思路:每一秒讓寄存器 D0 的值向左移1位,然后使用組合位元件將 D0 的低八位值傳送給輸出燈 Y10 - Y17。 ? ?后面有更好的思路再來增加。

    2024年02月16日
    瀏覽(35)
  • 上位機(jī)開發(fā)之三菱PLC通信

    上位機(jī)開發(fā)之三菱PLC通信

    三菱MC協(xié)議是開發(fā)三菱系列PLC必須掌握的一種通信協(xié)議,其目的是讓外部設(shè)備,可以通過串行通信模塊C24或以太網(wǎng)接口模塊E71,實(shí)現(xiàn)對可編程控制器CPU的數(shù)據(jù)訪問。 MC協(xié)議是Melsec協(xié)議的簡稱。 外部設(shè)備通過C24/E71訪問可編程控制器CPU時(shí),可以選擇不同的通信幀及數(shù)據(jù)格式來實(shí)現(xiàn)

    2023年04月08日
    瀏覽(26)
  • 三菱plc數(shù)據(jù)寄存器D

    三菱plc數(shù)據(jù)寄存器D

    在輸入和輸出處理、模擬控制和位置控制期間,需要許多數(shù)據(jù)寄存器來存儲(chǔ)數(shù)據(jù)和參數(shù)。數(shù)據(jù)寄存器為16位,最高位為符號位。兩個(gè)數(shù)據(jù)寄存器可以組合存儲(chǔ)32位數(shù)據(jù),最高位仍然是符號位。 ? 數(shù)據(jù)寄存器分為以下幾類: 通用數(shù)據(jù)寄存器D0 ~ D199有200個(gè)點(diǎn)。 斷電/鎖存寄存器D20

    2024年02月08日
    瀏覽(28)
  • 【2023】JAVA和PLC實(shí)現(xiàn)通訊讀取寫入數(shù)據(jù),以三菱PLC舉例

    【2023】JAVA和PLC實(shí)現(xiàn)通訊讀取寫入數(shù)據(jù),以三菱PLC舉例

    進(jìn)行PLC連接需要了解兩個(gè)概念: 長連接和短連接 。為了更好的說明當(dāng)前的通信情況,我把所有的通信拆分為四個(gè)部分,連接,發(fā),收,斷開。 短連接:連接,發(fā),收,斷開,連接,發(fā),收,斷開,連接,發(fā),收,斷開,連接,發(fā),收,斷開…無限循環(huán) 長連接:連接,發(fā),收

    2024年02月12日
    瀏覽(13)
  • 【工控老馬】三菱Q系列PLC調(diào)試及三菱觸摸屏報(bào)警使用說明詳解

    【工控老馬】三菱Q系列PLC調(diào)試及三菱觸摸屏報(bào)警使用說明詳解

    一 程序段注解 第1步 編輯菜單→文檔創(chuàng)建→聲明編輯 第2步 在左側(cè)空白處雙擊→彈出行間聲明輸入彈窗→輸入申明內(nèi)容 第3步 顯示如圖,轉(zhuǎn)換+全部編譯 二 插入比較指令 第1步 編輯菜單→梯形圖編輯模式→寫入模式 第2步 在需要插入指令的地方雙擊→輸入指令內(nèi)容 第3步 顯示

    2024年02月05日
    瀏覽(23)
  • C# 三菱PLC上位機(jī)開發(fā)環(huán)境搭建

    C# 三菱PLC上位機(jī)開發(fā)環(huán)境搭建

    一、安裝軟件 用到兩個(gè)三菱的軟件: 1. MX Component(下載地址?也可以直接在官網(wǎng)上搜索,注意MX后面有空格) 用于連接PLC 2. GX Works2(下載地址?用GX Works3也行) 這個(gè)軟件主要是電氣做PLC編程,我們用來作為仿真,省去開發(fā)時(shí)擺弄真實(shí)PLC 序列號:117-570766844 二、配置軟件 MX

    2023年04月18日
    瀏覽(22)
  • 三菱plc學(xué)習(xí)入門(創(chuàng)建屬于自己的FB模塊)

    三菱plc學(xué)習(xí)入門(創(chuàng)建屬于自己的FB模塊)

    ? ? ? ? 在現(xiàn)實(shí)生活中,往往會(huì)需要修改一些屬于方便自己的庫,1,自己創(chuàng)建的庫方便自己使用與查看2,提高自己編程能力,3,保護(hù)自己的程序不被外人修改!??!下面就讓我來操作一下 導(dǎo)入需要庫 ? ?選擇需要的庫 FB設(shè)置塊口令 ? ? ? ? 當(dāng)我們需要完成一個(gè)功能,并且

    2024年01月19日
    瀏覽(22)
  • C++:通過ofstream寫入二進(jìn)制文件內(nèi)容

    C++:通過ifstream讀取二進(jìn)制文件內(nèi)容_c++ ifstream 二進(jìn)制讀取-CSDN博客 介紹了讀取二進(jìn)制文件的方法。 本文介紹一下寫入二進(jìn)制數(shù)據(jù)到文件的方法: 1.通過write

    2024年01月19日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包