基恩士PLC的通讯协议比较简单,通过自带的串口,接一根转USB插到电脑上即可,协议如下:
通讯开始需要建立通讯,代码为:serialPort1.Write(0x43,0x52,0x0d, 0, 3);之后可以进行对PLC内部元件的读写操作;
1、SET MR000
byte[] MR_000 = new byte[9] { 0x53, 0x54, 0x20,0x4d,0x52,0x30,0x30,0x30,0x0d };//指令含义 [S T 空格 M R 0 0 0 C]的ASC码 16进制
if (serialPort1.IsOpen == true)//如果串口确实被打开了 则执行发送命令
serialPort1.Write(MR_000, 0, 9);//发送数组MR[0]开始的9个字节 set MR000
else
MessageBox.Show("PLC没连接,请连接后再操作!", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
2、连写DM0~DM9
byte[] DM_0 = new byte[32];//装入设定值 DM0DM1方式
if ((((Convert.ToUInt16(textBox4.Text))<=9999)&& ((Convert.ToUInt16(textBox4.Text)) >= 100)) && (textBox5.Text != ""))//先判断有没有输入
{ //速度设置100~9999 位置不能设置空
//一次连写DM0~DM9 D0为定位方式0或1 D2D3是位置 D8D9速度 其余无意义
//格式:[W R S 空格 D M 0 0 0 . D 空格 5 空格 数据1 空格 数据2 空格 数据3 空格 数据4 空格 数据5 CR] 均要转化成ASC 16进制
DM_0[0] = 0x57;//W的ASC码
DM_0[1] = 0x52;//R的ASC码
DM_0[2] = 0x53;//S的ASC码
DM_0[3] = 0x20;//空格的ASC码
DM_0[4] = 0x44;//D的ASC码
DM_0[5] = 0x4D;//M的ASC码
DM_0[6] = 0x30;//0的ASC码
DM_0[7] = 0x30;//0的ASC码
DM_0[8] = 0x30;//0的ASC码
DM_0[9] = 0x2E;//.的ASC码
DM_0[10] = 0x44;//D的ASC码
DM_0[11] = 0x20;//空格的ASC码
DM_0[12] = 0x35;//5的ASC码
DM_0[13] = 0x20;//空格的ASC码
//写数据1 DM0 定位方式 DM1没用到写什么都可以 .D代表无符号32位数据 相对定位写0 绝对定位写1 合起来就是 0/1
DM_0[14] = 0x31;//1的ASC码 只允许绝对定位
DM_0[15] = 0x20;//空格的ASC码
//写数据2 DM2 DM3 目标位置cm转化为um 无符号32位 限制目标范围0~20cm,范围000000~200000um 要根据实际来取值,相当于软限位
Pul = (UInt32)(10000*Convert.ToDouble(textBox5.Text));//取出输入的位置 注意是无符号
if (Pul <= 200000)//输入小于20cm正常处理
{
if (Pul / 100000 == 0)//提取最高位 并转换为ASC 说明值小于100000 第一位为0
{
DM_0[16] = 0x30;//0的ASC码
Pul1 = Pul;
}
if (Pul / 100000 == 1)//提取最高位 并转换为ASC 说明值100000~199999 第一位为1
{
DM_0[16] = 0x31;//1的ASC码
Pul1 = Pul - 100000;
}
if (Pul / 100000 == 2)//提取最高位 并转换为ASC 说明值200000 第一位为2
{
DM_0[16] = 0x32;
Pul1 = Pul - 200000;
}
if (Pul1 / 10000 == 0)//提取第二位 并转换为ASC 说明值小于10000 第2位为0
{
DM_0[17] = 0x30;
Pul2 = Pul1;
}
if (Pul1 / 10000 == 1)//提取第二位 并转换为ASC 说明值10000~19999 第2位为1
{
DM_0[17] = 0x31;
Pul2 = Pul1 - 10000;
}
if (Pul1 / 10000 == 2)//提取第二位 并转换为ASC 说明值20000~29999 第2位为2
{
DM_0[17] = 0x32;
Pul2 = Pul1 - 20000;
}
if (Pul1 / 10000 == 3)//提取第二位 并转换为ASC 说明值30000~39999 第2位为3
{
DM_0[17] = 0x33;
Pul2 = Pul1 - 30000;
}
if (Pul1 / 10000 == 4)//提取第二位 并转换为ASC 说明值40000~49999 第2位为4
{
DM_0[17] = 0x34;
Pul2 = Pul1 - 40000;
}
if (Pul1 / 10000 == 5)//提取第二位 并转换为ASC 说明值50000~59999 第2位为5
{
DM_0[17] = 0x35;
Pul2 = Pul1 - 50000;
}
if (Pul1 / 10000 == 6)//提取第二位 并转换为ASC 说明值60000~69999 第2位为6
{
DM_0[17] = 0x36;
Pul2 = Pul1 - 60000;
}
if (Pul1 / 10000 == 7)//提取第二位 并转换为ASC 说明值70000~79999 第2位为7
{
DM_0[17] = 0x37;
Pul2 = Pul1 - 70000;
}
if (Pul1 / 10000 == 8)//提取第二位 并转换为ASC 说明值80000~89999 第2位为8
{
DM_0[17] = 0x38;
Pul2 = Pul1 - 80000;
}
if (Pul1 / 10000 == 9)//提取第二位 并转换为ASC 说明值90000~99999 第2位为9
{
DM_0[17] = 0x39;
Pul2 = Pul1 - 90000;
}
if (Pul2 / 1000 == 0)//提取第3位 并转换为ASC 说明值小于1000 第3位为0
{
DM_0[18] = 0x30;
Pul3 = Pul2;
}
if (Pul2 / 1000 == 1)//提取第3位 并转换为ASC 说明值1000~1999 第3位为1
{
DM_0[18] = 0x31;
Pul3 = Pul2 - 1000;
}
if (Pul2 / 1000 == 2)//提取第3位 并转换为ASC 说明值2000~2999 第3位为2
{
DM_0[18] = 0x32;
Pul3 = Pul2 - 2000;
}
if (Pul2 / 1000 == 3)//提取第3位 并转换为ASC 说明值3000~3999 第3位为3
{
DM_0[18] = 0x33;
Pul3 = Pul2 - 3000;
}
if (Pul2 / 1000 == 4)//提取第3位 并转换为ASC 说明值4000~4999 第3位为4
{
DM_0[18] = 0x34;
Pul3 = Pul2 - 4000;
}
if (Pul2 / 1000 == 5)//提取第3位 并转换为ASC 说明值5000~5999 第3位为5
{
DM_0[18] = 0x35;
Pul3 = Pul2 - 5000;
}
if (Pul2 / 1000 == 6)//提取第3位 并转换为ASC 说明值6000~6999 第3位为6
{
DM_0[18] = 0x36;
Pul3 = Pul2 - 6000;
}
if (Pul2 / 1000 == 7)//提取第3位 并转换为ASC 说明值7000~7999 第3位为7
{
DM_0[18] = 0x37;
Pul3 = Pul2 - 7000;
}
if (Pul2 / 1000 == 8)//提取第3位 并转换为ASC 说明值8000~8999 第3位为8
{
DM_0[18] = 0x38;
Pul3 = Pul2 - 8000;
}
if (Pul2 / 1000 == 9)//提取第3位 并转换为ASC 说明值9000~9999 第3位为9
{
DM_0[18] = 0x39;
Pul3 = Pul2 - 9000;
}
if (Pul3 / 100 == 0)//提取第4位 并转换为ASC 说明值小于100 第4位为0
{
DM_0[19] = 0x30;
Pul4 = Pul3;
}
if (Pul3 / 100 == 1)//提取第4位 并转换为ASC 说明值100~199 第4位为1
{
DM_0[19] = 0x31;
Pul4 = Pul3 - 100;
}
if (Pul3 / 100 == 2)//提取第4位 并转换为ASC 说明值200~299 第4位为2
{
DM_0[19] = 0x32;
Pul4 = Pul3 - 200;
}
if (Pul3 / 100 == 3)//提取第4位 并转换为ASC 说明值300~399 第4位为3
{
DM_0[19] = 0x33;
Pul4 = Pul3 - 300;
}
if (Pul3 / 100 == 4)//提取第4位 并转换为ASC 说明值400~499 第4位为4
{
DM_0[19] = 0x34;
Pul4 = Pul3 - 400;
}
if (Pul3 / 100 == 5)//提取第4位 并转换为ASC 说明值500~599 第4位为5
{
DM_0[19] = 0x35;
Pul4 = Pul3 - 500;
}
if (Pul3 / 100 == 6)//提取第4位 并转换为ASC 说明值600~699 第4位为6
{
DM_0[19] = 0x36;
Pul4 = Pul3 - 600;
}
if (Pul3 / 100 == 7)//提取第4位 并转换为ASC 说明值700~799 第4位为7
{
DM_0[19] = 0x37;
Pul4 = Pul3 - 700;
}
if (Pul3 / 100 == 8)//提取第4位 并转换为ASC 说明值800~899 第4位为8
{
DM_0[19] = 0x38;
Pul4 = Pul3 - 800;
}
if (Pul3 / 100 == 9)//提取第4位 并转换为ASC 说明值900~999 第4位为1
{
DM_0[19] = 0x39;
Pul4 = Pul3 - 900;
}
if (Pul4 / 10 == 0)//提取第5位 并转换为ASC 说明值小于10 第5位为0
{
DM_0[20] = 0x30;
Pul5 = Pul4;
}
if (Pul4 / 10 == 1)//提取第5位 并转换为ASC 说明值10~19 第5位为1
{
DM_0[20] = 0x31;
Pul5 = Pul4 - 10;
}
if (Pul4 / 10 == 2)//提取第5位 并转换为ASC 说明值20~29 第5位为2
{
DM_0[20] = 0x32;
Pul5 = Pul4 - 20;
}
if (Pul4 / 10 == 3)//提取第5位 并转换为ASC 说明值30~39 第5位为3
{
DM_0[20] = 0x33;
Pul5 = Pul4 - 30;
}
if (Pul4 / 10 == 4)//提取第5位 并转换为ASC 说明值40~49 第5位为4
{
DM_0[20] = 0x34;
Pul5 = Pul4 - 40;
}
if (Pul4 / 10 == 5)//提取第5位 并转换为ASC 说明值50~59 第5位为5
{
DM_0[20] = 0x35;
Pul5 = Pul4 - 50;
}
if (Pul4 / 10 == 6)//提取第5位 并转换为ASC 说明值60~69 第5位为6
{
DM_0[20] = 0x36;
Pul5 = Pul4 - 60;
}
if (Pul4 / 10 == 7)//提取第5位 并转换为ASC 说明值70~79 第5位为7
{
DM_0[20] = 0x37;
Pul5 = Pul4 - 70;
}
if (Pul4 / 10 == 8)//提取第5位 并转换为ASC 说明值80~89 第5位为8
{
DM_0[20] = 0x38;
Pul5 = Pul4 - 80;
}
if (Pul4 / 10 == 9)//提取第5位 并转换为ASC 说明值90~99 第5位为9
{
DM_0[20] = 0x39;
Pul5 = Pul4 - 90;
}
if (Pul5 == 0)//提取第6位 并转换为ASC 最后1位 0~9
{
DM_0[21] = 0x30;//
}
if (Pul5 == 1)//
{
DM_0[21] = 0x31;//
}
if (Pul5 == 2)//
{
DM_0[21] = 0x32;//
}
if (Pul5 == 3)//
{
DM_0[21] = 0x33;//
}
if (Pul5 == 4)//
{
DM_0[21] = 0x34;//
}
if (Pul5 == 5)//
{
DM_0[21] = 0x35;//
}
if (Pul5 == 6)//
{
DM_0[21] = 0x36;//
}
if (Pul5 == 7)//
{
DM_0[21] = 0x37;//
}
if (Pul5 == 8)//
{
DM_0[21] = 0x38;//
}
if (Pul5 == 9)//
{
DM_0[21] = 0x39;//
}
}
else//设置数据超过20cm越限了 当作5cm处理 050000
{
DM_0[16] = 0x30; DM_0[17] = 0x35; DM_0[18] = 0x30; DM_0[19] = 0x30; DM_0[20] = 0x30; DM_0[21] = 0x30;
MessageBox.Show("位置越限,只移动到5cm处!", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
DM_0[22] = 0x20;//空格的ASC码
//写数据3 DM4DM5 数据无意义 写0
DM_0[23] = 0x30;
DM_0[24] = 0x20;//空格的ASC码
//写数据4 DM6DM7 数据无意义 写0
DM_0[25] = 0x30;
DM_0[26] = 0x20;//空格的ASC码
//写数据5 速度 DM8DM9 限制输入0100~9999
Sud = Convert.ToUInt16(textBox4.Text);//取出输入的速度
if (Sud / 1000 == 0)//提取第1位
{
DM_0[27] = 0x30;//0的ASC码
Sud1 = Sud;
}
if (Sud / 1000 == 1)
{
DM_0[27] = 0x31;//
Sud1 = (ushort)(Sud - 1000);
}
if (Sud / 1000 == 2)
{
DM_0[27] = 0x32;//
Sud1 = (ushort)(Sud - 2000);
}
if (Sud / 1000 == 3)
{
DM_0[27] = 0x33;//
Sud1 = (ushort)(Sud - 3000);
}
if (Sud / 1000 == 4)
{
DM_0[27] = 0x34;//
Sud1 = (ushort)(Sud - 4000);
}
if (Sud / 1000 == 5)
{
DM_0[27] = 0x35;//
Sud1 = (ushort)(Sud - 5000);
}
if (Sud / 1000 == 6)
{
DM_0[27] = 0x36;//
Sud1 = (ushort)(Sud - 6000);
}
if (Sud / 1000 == 7)
{
DM_0[27] = 0x37;//
Sud1 = (ushort)(Sud - 7000);
}
if (Sud / 1000 == 8)
{
DM_0[27] = 0x38;//
Sud1 = (ushort)(Sud - 8000);
}
if (Sud / 1000 == 9)
{
DM_0[27] = 0x39;//
Sud1 = (ushort)(Sud - 9000);
}
if (Sud1 / 100 == 0)//提取第2位
{
DM_0[28] = 0x30;//0的ASC码
Sud2 = Sud1;
}
if (Sud1 / 100 == 1)
{
DM_0[28] = 0x31;//
Sud2 = (ushort)(Sud1 - 100);
}
if (Sud1 / 100 == 2)
{
DM_0[28] = 0x32;//
Sud2 = (ushort)(Sud1 - 200);
}
if (Sud1 / 100 == 3)
{
DM_0[28] = 0x33;//
Sud2 = (ushort)(Sud1 - 300);
}
if (Sud1 / 100 == 4)
{
DM_0[28] = 0x34;//
Sud2 = (ushort)(Sud1 - 400);
}
if (Sud1 / 100 == 5)
{
DM_0[28] = 0x35;//
Sud2 = (ushort)(Sud1 - 500);
}
if (Sud1 / 100 == 6)
{
DM_0[28] = 0x36;//
Sud2 = (ushort)(Sud1 - 600);
}
if (Sud1 / 100 == 7)
{
DM_0[28] = 0x37;//
Sud2 = (ushort)(Sud1 - 700);
}
if (Sud1 / 100 == 8)
{
DM_0[28] = 0x38;//
Sud2 = (ushort)(Sud1 - 800);
}
if (Sud1 / 100 == 9)
{
DM_0[28] = 0x39;//
Sud2 = (ushort)(Sud1 - 900);
}
if (Sud2 / 10 == 0)//提取第3位
{
DM_0[29] = 0x30;
Sud3 = Sud2;
}
if (Sud1 / 10 == 1)
{
DM_0[29] = 0x31;//
Sud3 = (ushort)(Sud2 - 10);
}
if (Sud1 / 10 == 2)
{
DM_0[29] = 0x32;//
Sud3 = (ushort)(Sud2 - 20);
}
if (Sud1 / 10 == 3)
{
DM_0[29] = 0x33;//
Sud3 = (ushort)(Sud2 - 30);
}
if (Sud1 / 10 == 4)
{
DM_0[29] = 0x34;//
Sud3 = (ushort)(Sud2 - 40);
}
if (Sud1 / 10 == 5)
{
DM_0[29] = 0x35;//
Sud3 = (ushort)(Sud2 - 50);
}
if (Sud1 / 10 == 6)
{
DM_0[29] = 0x36;//
Sud3 = (ushort)(Sud2 - 60);
}
if (Sud1 / 10 == 7)
{
DM_0[29] = 0x37;//
Sud3 = (ushort)(Sud2 - 70);
}
if (Sud1 / 10 == 8)
{
DM_0[29] = 0x38;//
Sud3 = (ushort)(Sud2 - 80);
}
if (Sud1 / 10 == 9)
{
DM_0[29] = 0x39;//
Sud3 = (ushort)(Sud2 - 90);
}
if (Sud3 == 0)//提取第4位 最后1位
{
DM_0[30] = 0x30;
}
if (Sud3 == 1)
{
DM_0[30] = 0x31;
}
if (Sud3 == 2)
{
DM_0[30] = 0x32;
}
if (Sud3 == 3)
{
DM_0[30] = 0x33;
}
if (Sud3 == 4)
{
DM_0[30] = 0x34;
}
if (Sud3 == 5)
{
DM_0[30] = 0x35;
}
if (Sud3 == 6)
{
DM_0[30] = 0x36;
}
if (Sud3 == 7)
{
DM_0[30] = 0x37;
}
if (Sud3 == 8)
{
DM_0[30] = 0x38;
}
if (Sud3 == 9)
{
DM_0[30] = 0x39;
}
DM_0[31] = 0x0D;
}
else
MessageBox.Show("请输入正确参数!", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
if (serialPort1.IsOpen == true)//如果串口确实被打开了 则执行发送命令
serialPort1.Write(DM_0, 0, 32);//发送数组
3、读输入R0~R7
private void timer2_Tick(object sender, EventArgs e)//800ms 读输入R0~R07的状态 与光电开关有关 读8个 返回17字节
{
//格式均为[R D S 空格 软元件类型 软元件编号 数据格式 空格 读取个数 C] 读R 数据格式可以省略,此时表示位
byte[] R_000 = new byte[] { 0x52,0x44,0x53,0x20,0x52,0x30,0x30,0x30,0x20,0x38,0x0d}; if (serialPort1.IsOpen == true)
serialPort1.Write(R_000, 0, 11);
System.Threading.Thread.Sleep(50);//单位ms
}
4、读MR000~MR006
private void timer4_Tick(object sender, EventArgs e)//2400ms 读MR000~MR06的状态 与轴控制 状态有关 读7个 返回15字节
{
byte[] M_000 = new byte[] { 0x52, 0x44, 0x53, 0x20, 0x4D, 0x52, 0x30, 0x30, 0x30, 0x20, 0x37, 0x0d };
if (serialPort1.IsOpen == true)
serialPort1.Write(M_000, 0, 12);
System.Threading.Thread.Sleep(50);//单位ms
}
5、读DM50~DM55
private void timer7_Tick(object sender, EventArgs e)//4800ms 读DM50~DM55 轴实时位置 脉冲 无符号 读3个32位数 返回34字节
{
byte[] DM_50 = new byte[] { 0x52, 0x44, 0x53, 0x20, 0x44, 0x4D, 0x35, 0x30, 0x2E, 0x44, 0x20, 0x33, 0x0d };
if (serialPort1.IsOpen == true)
serialPort1.Write(DM_50, 0, 13);
System.Threading.Thread.Sleep(50);//单位ms
}
看完小伙伴们有没有学会呢?有什么问题都可以问我。