西门子s7协议

 S7Comm(S7 Communication)是西门子专有的协议,是西门子S7通讯协议簇里的一种。
 S7通信协议是西门子S7系列PLC内部集成的一种通信协议,是S7系列PLC的精髓所在。 它是一种运行在传输层之上的(会话层/表示层/应用层)、经过特殊优化的通信协议,其信息传输可以基于MPI网络、PROFIBUS网络或者以太网
 S7在TCP连接上后还需要进行两次握手
 S7协议的TCP/IP实现依赖于面向块的ISO传输服务。S7协议被封装在TPKT和ISO-COTP协议中,这使得PDU(协议数据单元)能够通过TCP传送。

  s7协议
   1需要通过socket三次握手,不用写握手过程
   目前提供设备型号s71200 cpu:1212c
   电压是24vDC

  建立连接过程

 TcpClient client = new TcpClient();
 client.Connect("ip地址",端口号);//连接PLC网络地址

 // 2第一次请求连接 发送请求帧为
 // 总共22字节
 byte[] bs1 = new byte[]
 {
     0x03,//1字节版本号 默认是03
     0x00,//保留值默认为0
     0x00,0x16,//2字节 报文的总长度
     0x11,// 1字节 从该字节往后字节个数 十进制是17
     0xE0,//PDU 类型
     0x00,0x00,//DST引用 默认值
     0x00,0x01,//src引用
     0x00,//采用默认值
     0xc1,// 上位机参数
     0x02,// 参数长度
     0x10,0x00,//0x10代表双边通信 0x00机架号和插槽号
     0xC2,//plc参数
     0x02,//长度
     0x03,0x01,//0x01和0x00共同控制机架号和插槽
     0xC0,
     0x01,
     0x0A,//TPDU长度

 };
 client.GetStream().Write(bs1,0,bs1.Length);
 //第二次请求连接 发送请求帧为
 bs1 = new byte[]
 {
     0x03,//版本号
     0x00,//保留值默认为0
     0x00,0x19,//整个报文的长度
     0x02,//COTP当前字节后的字节数
     0xF0,//PUD类型
     0x80,//最高十进制128
     0x32,//协议ID,固定值
     0x01,//工作类型 0x01主站发送请求
     0x00,0x00,
     0x00,0x00,
     0x00,0x08,//参数长度
     0x00,0x00,//数据长度
     0xF0,//功能码
     0x00,//保留值
     0x00,0x03,//允许操作最大工作队列
     0x00,0x03,
     0x03,0xc0//允许处理最大字节数

 };
 client.GetStream().Write(bs1,0,bs1.Length);
 MessageBox.Show("连接成功");

读取过程

  读取数据必须知道:
  1 plc存储那个区里面
  0x83 M存储之间
  0x84 DB块
  0x81 I存储空间
  0x82 Q输出存储空间

  2数据存储在那个地址上 00 03 20

  3读取数据的长度
   03 00 00 1F 02 F0 80 30 01 0 00 00 01 00 0E 00 00 04 01 012 0A 10 02 00 02 00 00 83 00 03 20

先连接进行socket三次握手在判断是否连接成功 在进行读取显示label

 Socket socket;
//连接按钮事件
 private void button1_Click(object sender, EventArgs e)
 {
     //socket三次握手
      socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     socket.Connect("ip地址", 端口号);
     if (socket.Connected)//连接成功
     {
         StartReceive();//接收数据
     }
     //两次连接请求
     //第一次连接请求
     byte[]bs=new byte[]
     {
         0x03,// 1字节版本号 默认是03
         0x00,// 1字节 保留值 默认0
         0x00, 0x16,//2字节 报文的总长度
         0x11,//1字节从该字节往后字节个数 十进制是17
         0xE0,//PDU 类型
         0x00,0x00,// DST引用 默认值
         0x00,0x01,//src引用
         0x00,//采用默认值
         0xc1,// 上位机参数
         0x02,// 参数长度
         0x10,0x00, // 0x10 代表双边通信  0x00机架号和插槽号
         0xC2, // plc参数
         0x02 ,// 长度
         0x03,0x01,// 0x01和0x00 共同控制机架号和插槽
         0xC0,
         0x01,
         0x0A //TPDU长度
     };
     socket.Send(bs);//第一次发送
     bs = new byte[]
             {
         0x03,///1字节版本号 默认是03
         0x00,// 1字节 保留值 默认0
         0x00, 0x19,//2字节 报文的总长度
         0x02,//当前字节后的字节数
         0xF0,//PDU类型 数据传输
         0x80,//最高是十进制128 
         0x32,//协议ID,固定值
         0x01,//工作类型 0x01 主站发送请求
         0x00,0x00,
         0x00,0x00,
         0x00,0x08,//参数长度
         0x00,0x00,//数据长度
         0xF0,//功能码
         0x00,//Reserved保留值
         0x00,0x03,// 允许操作最大工作队列
         0x00,0x03,
         0x03,0xc0 //运行处理最大字节数组
      };
     socket.Send(bs);//第二次发送
     MessageBox.Show("连接成功");
 }
 //读取
 private void button2_Click(object sender, EventArgs e)
 {
     //发送请求帧  请求M14数据 地址从14开始 读取一个数据
     byte[] data = new byte[]
     {
         //TPKT:版本号 预留号 总字节长度
         0x03,//版本号
         0x00,//预留号
       0x00,0x1F,//总长度
         //COTP块:
         0x02,//往下的长度
         0xF0,//PDU类型  数据传输
         0x80,//目标引用

         //s7-header s7头
         0x32,//协议id默认
         0x01,//主站开始发请求
         0x00,0x00,//预留位置
         0x03,0x7d,//随机生成的数字 每次在基础之上递增
         0x00,0x0e,//参数长度
         0x00,0x00,//数据长度
         //s7-参数部分
         0x04,//功能码 读取功能
         0x01,//如果涉及多读的时候 设置为1
         0x12,//结构标识 一般默认12
         0x0a,//往后的字节长度
         0x10,//寻址模式
         0x02,//读取的数据类型 02是字节类型
         0x00,0x01,//读取长度
         0x00,0x00,//读取不是DB区
         0x83,//0x83M存储区 ,0x84DB块
         0x00,0x00,0x70//开始数据的地址
         //例如 M3000,实际地址是30000*8=2400000 把转成三个字节 转成16进制3a980 对应三个地址,0x03,0xA9 0x80
         //例如数据DB块的数据,DB21234.4000,其中DB号是21234 转成16进制0x52F2,DB区改为0x52,02 F2
         //4000*8=32000,转成16进制7d00转成三个字节变成 0x00,0x7d,0x00
     };
     socket.Send(data);
   
 }
 void StartReceive()
 {
     Task.Run(() =>
     {
         byte[] bs1 = new byte[1024];
         while (true)
         {
            int count= socket.Receive(bs1);
             if (count == 0)
             {
                 break;
             }
             //前两次弹出的是连接的响应
             //读取的响应 FF(读取成功的标志) 04(读取数据的类型) 00 08(数据的长度) 0C(数据)
           MessageBox.Show(BitConverter.ToString(bs1, 0, count));
             label1.Invoke((Action)(() =>
             {
                 label1.Text = bs1[25].ToString();
             }));
            
         }
     });
 }

写入数据 如写M14地址1个字节 M2000地址4字节

byte[] value = BitConverter.GetBytes(int.Parse(textBox1.Text));
//写入M14地址 写一个字节36
//写入M2000地址 写入4个字节
//生成写的报文
byte[] bs = new byte[]
{
    //会话层
    0x03,//版本号
    0x00,//预留号
    0x00,0x24,//M14地1个字节址  报文总长度36
    0x00,0x27,//M2000地址  4个字节报文长度为39
    //COPT 表示层
    0x02,//长度
    0xF0,//PDU类型  数据传输
    0x80,//目标引用

    //s7-header
    0x32,//协议id
    0x01,//主站开始请求
    
    0x00,0x00,//预留部分
    0x03,0x7d,//随机生成
    0x00,0x0E,//参数长度
 // 0x00,0x05,//参数数据长度 M14
    0x00,0x08,//参数数据长度
    //s7-参数
    0x05,//功能码 05代表写, 04代表读取
    0x01,//通信项数 可以支持多写
    0x12,//变量指定
    0x0A,//后面长度
    0x10,
    0x02,//传输的数据类型 字节
   // 0x00,0x01,M14  //操作数据的长度
   0x00,0x04,//写入M2000
    0x00,0x00,//M区 不是DB区
    0x83,//M区
    //0x00,0x00,0x70,//开始写入M14地址
      0x00,0x3E,0x80,//2000写入地址
    0x00,
    0x04,//字节类型
   // 0x00,0x08,  M14// 写入数据的长度 8位一个
    0x00,0x20,//M2000 写入数据的长度 8位一个 4*8=32 16进制20
  //  byte.Parse(this.textBox1.Text),//写入数据
  value[3],value[2],value[1],value[0]//写入M2000写入4个
};
tcp.Send(bs);
type = RequestType.Write;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值