三菱协议以及C#实现

发布于:2024-12-19 ⋅ 阅读:(15) ⋅ 点赞:(0)

三菱

三菱的是422的只能用编程口通讯,只能用编程口协议。

波特率:9600数据位位数:7位停止位位数:1位数据校验方式: 偶校验

* D0: 1000 2000 3000 频率
* M0: 电机正转 true 、false
* M1:电机反转 true 、false

报文基本格式

FX PLC的数据注意包括`D寄存器(每个寄存器二字节长)、M(位地址)、S(位地址)、T(位地址)、C(位地址)、X(位地址)、Y(位地址)`​​

数据帧的基本格式如下

> 需要注意的是,除了控制码之外的其他数据帧,都需要将其转换位对应的ASCII编码值进行发送
> 如:1 => 0x31 或者 30 => 0x33 0x30 123 => 0x31 0x32 0x33

和校验

发送的报文最后两位为和校验,和校验计算反射为`命令码 + 元件地址 + 数据 + 0x03`​​,计算结果取后两位转换ascii码

计算: https://www.23bei.com/tool/8.html

C#代码实现

public partial class Form1 : Form
{ 
    public Form1()
    {
        InitializeComponent();
        this.serialPort1.Open();
    }

    /// <summary>
    /// 写入
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void button1_Click(object sender, EventArgs e)
    {
        // D123区写入258数据
        // 123*2+0x1000 --> 10F6 --> 16进制ascii值 成
        // 258 --> 16进制0102 --> 小端0201 --> 16进制ascii值 30h 32h 30h 31h
        // 请求帧字节数组
        // 31h + 31h + 30h + 46h +30h + 32h +30h + 31h + 03
        // 16进制ascii值: 02 | 31h | 31h 30h 46h 36h 30h 32h 30h 32h 30h 31h | 03 | 
        byte[] bs = new byte[] {02,49,49,48,70,54,48,50,48,50,48,49,03,51,54 };

        this.serialPort1.Write(Encoding.ASCII.GetString(bs));
    }

    /// <summary>
    /// 读取
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void button2_Click(object sender, EventArgs e)
    {
        byte[] bs = new byte[] {02,48,49,48,70,54,48,52,03,55,52};
        this.serialPort1.Write(Encoding.ASCII.GetString(bs));
    }


    /// <summary>
    /// 置位
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void button3_Click(object sender, EventArgs e)
    {
        // 置位
        byte[] bs = new byte[] {02,55,48,49,48,56,03,48,51};
        this.serialPort1.Write(Encoding.ASCII.GetString(bs));
    }

    /// <summary>
    /// 复位
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void button4_Click(object sender, EventArgs e)
    {
        // 复位
        byte[] bs = new byte[] { 02, 56, 48, 49, 48, 56, 03, 56, 52 };
        this.serialPort1.Write(Encoding.ASCII.GetString(bs));
    }

    /// <summary>
    /// 接收接口消息
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        // 读取响应
        byte[] data = new byte[this.serialPort1.BytesToRead];
        this.serialPort1.Read(data, 0, data.Length);
        Console.WriteLine(BitConverter.ToString(data)); // 06
        if (data.Length == 1 )
        {
            if (data[0] == 6)
            {
                MessageBox.Show("写入成功");
            }
            else
            {
                MessageBox.Show("写入失败");
            }
        } 
        else // 读取操作
        {
            MessageBox.Show(GetResult(data)+"");
        }
    }

    private uint GetResult(byte[] data)
    {
        byte[] array = new byte[(data.Length - 4)/2]; // 响应帧里面数据的长度
        for (int i = 0;i< array.Length; i++)  // 0 1 2 3
        {
            byte[] bs = new byte[2]
            {
                data[i*2+1],
                data[i*2+2],
            };
            array[i] = Convert.ToByte(Encoding.ASCII.GetString(bs), 16);
        }
        var value = BitConverter.ToUInt16(array, 0);
        return value;
    }


}