C++与PLC通过Modbus TCP协议进行PLC内部寄存器的值的读取/写入总结

一、对PLC中一个DT值(16位)进行读取、赋值(正、负整数)

(本文中所有数据验证基于松下PLC)

(PLC一个DT最大支持十进制有符号整数±32768,无符号整数66536)

(PLC一个DT最大支持十进制正整数0 - 32767,负整数(-1) -(-32768))

思路:

  1. 采用ModbudTCP协议(或者其他协议)
  2. 其中每个DT值对应协议中的两个8位的十六进制,如00 0A
  3. 两个8位的十六进制最大能够传送正/负整数32768,以内的十进制转换成的两个8位的十六进制数。
  4. 读取负数的处理:负数的读取目前已经有了现有的代码,其中16位整数的读取无论是正数还是负数都可以通过现有的代码进行读取判断其正负值。
  5. 对PLC寄存器16位负数的赋值

         5.1、保证负数在 -32768内

         5.2、将要传送的负数 += 65536

         5.3、将得到的值转换为十六进制

二、上位机对PLC中一个DT值(32位)进行读取、赋值(正、负整数)

思路:

  1. 采用ModbudTCP协议(或者其他协议)
  2. 其中每个DT值对应协议中的4个8位的十六进制,如00 0A 00 0B
  3. 读取PLC的32位DT值:

步骤:3.1、将PLC中的DT值设置为有符号或者无符号的32位

           3.2、和读取16进制一样,以每个8位的十六进制位单位去解析PLC传上来的值

         (其中低十六位不判断正负。高十六位才判断正负)

          3.3、将解析后的十进制数值,按照以下公式进行计算

           寄存器(0007H) * 10000H + 寄存器(0006H) = 数据1*100H + 数据2 + 数据3*1000000H +    数据4*10000H

( 数据1:寄存器06H(高8位)、  数据2:寄存器06H(低8位)  、

    数据3:寄存器07H(高8位)、  数据4:寄存器07H(低8位)      )

4、写入PLC中32位寄存机的值

步骤:4.1、正值写入

          4.2、整个思路分为两个部分,高十六位 与 低十六位

         4.3、得要要传送的值后,先对其进行判断,是否大于65535。

如果不大于,则直接转换为十六进制,得到的十六进制位地十六位,高十六位直接为00 00;

如果大于再对其进行解析,用这个值除以65536得到商的值的十六进制就是高十六位的最终结果,然后在用需要传的值与 65536取余数(%)的到的余数的值的十六进制就是低十六位的值。

例:str = "00 00 00 00 00 CF 01 10 13 88 00 02 04 86 A0 00 01"; //输出32位的值100000

 其中02为:为起始地址寄存器的数量为2,     04为字节数为4

86 A0 00 01:为十进制100000,  86 A0位低十六位;   00 01为高十六位

(86A0的十进制为34464    00 01的十进制为 1 * 65536 = 65536;     相加为 34464 + 65536 = 100000)

5、负32位的值的写入

步骤:

(

方向1:00 00   ff ff    PCL显示为 -65536       

00 01   ff ff    PCL显示为 -65535;        

00 02   ff ff    PCL显示为 -65534;

方向2:00 00  ff fe PCL显示为 -131072(-65536的两倍);

00 01  ff fe PCL显示为 -131071(-65535的两倍);

00 02  ff fe PCL显示为 -131070(-65534的两倍);

方向3:00 00  ff fd PCL显示为 -196608(-65536的三倍);

)

由以上规律可知:直接将C++的代码放在下面,欢迎大家提出好的建议,以下是我自己的一个规律理解:

int TemporaryVariable = ui->spinBox->value();
    if(TemporaryVariable >= 0)   //正值传送
    {
        if(TemporaryVariable > 65535)
        {
            THEKERNEL->k3_PLC1WriteData[0] = TemporaryVariable % 65536;  //低十六位 取余
            THEKERNEL->k3_PLC1WriteData[1] = TemporaryVariable / 65536;  //高十六位 取商
        }
        else
        {
            THEKERNEL->k3_PLC1WriteData[0] = TemporaryVariable; //(低十六位)
            THEKERNEL->k3_PLC1WriteData[1] = 0;  //(高十六位)
        }
    }
    else  //负值传送
    {
        int TestValue = 0;
        TestValue = abs(TemporaryVariable);   //负数传值运算
        if((TestValue / 65536) > 0)
        {
            if((TestValue % 65536) == 0)
            {
                THEKERNEL->k3_PLC1WriteData[0] = 0;
                THEKERNEL->k3_PLC1WriteData[1] = 65536 - (TestValue / 65536);  //高位
            }
            else
            {
                THEKERNEL->k3_PLC1WriteData[0] = 65536 - (TestValue % 65536);
                THEKERNEL->k3_PLC1WriteData[1] = 65535 - (TestValue / 65536);  //高位
            }
        }
        else
        {

            THEKERNEL->k3_PLC1WriteData[0] = 65536 - TestValue;
            THEKERNEL->k3_PLC1WriteData[1] = 65535;
        }
    }
//其中:ui->spinBox->value()为界面要传送至PLC的值
//THEKERNEL->k3_PLC1WriteData[0]:传值至PLC的中间变量容器
//THEKERNEL->k3_PLC1WriteData[0]:低十六位
//THEKERNEL->k3_PLC1WriteData[1]:高十六位

三、ASCII码的传值与读取

  1. 将ASCII码写入到PLC寄存器中。其方式与16位整数一样,直接给出例子

str = "00 00 00 00 00 CF 01 10 13 88 00 01 02 4e 4d";

 //DT5000 显示ASCII(16位)的字符:  N M    (十六进制 4e = n(ASCII); 4d = m)

以上例子是将PLC中寄存器DT5000中传入ASCII码,

  1. 读取PLC传来的16进制ASCII码

   将读出来的十六进制进过程序转换为ASCII码即可

  • 8
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
回答: 在使用C++编程语言进行西门子PLCModbus TCP通信时,可以使用libmodbus库来实现。首先需要创建一个libmodbus的上下文对象,可以使用modbus_new_tcp函数来创建一个TCP连接的上下文对象,需要传入PLC的IP地址和端口号作为参数。如果创建上下文对象失败,可以通过判断返回是否为NULL来进行错误处理。\[1\] 接下来,可以使用modbus_connect函数来建立与PLC的连接,需要传入之前创建的上下文对象作为参数。如果连接失败,可以通过modbus_strerror函数获取错误信息进行处理,并释放之前创建的上下文对象。\[2\] 在进行PLCModbus TCP通信时,可以使用博途软件进行配置和组态。首先需要配置从站模块和主站模块的引脚参数,具体的引脚配置可以参考官方的资料。对于主站模块的引脚参数配置,可以使用博途软件创建相应型号的PLC,并进行常规的配置和程序编。\[3\] 以上是关于使用C++进行西门子PLCModbus TCP通信的简要介绍。具体的实现过程和代码可以根据实际需求和具体情况进行调整和编。 #### 引用[.reference_title] - *1* *2* [C++ modbus TCP 协议PLC通信](https://blog.csdn.net/lisuyulisuyulisuyu/article/details/118333613)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [西门子1500PLCmodbus TCP协议通信](https://blog.csdn.net/Yaphtes666/article/details/102948478)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值