找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2835|回复: 12

三菱FX通讯口协议2—上位机开发

 火.. [复制链接]
  • 打卡等级:即来则安
  • 打卡总天数:27
  • 打卡月天数:6
  • 打卡总奖励:7736
  • 最近打卡:2025-12-20 00:35:11

3317

主题

285

回帖

2万

积分

管理员

积分
23881
发表于 2021-1-30 21:00:20 | 显示全部楼层 |阅读模式
一、前面学习了三菱FX通讯口协议的内容,这次根据此协议,编写上位机软件读取PLC软原件X、Y、D的值;
二、上位机界面如下:


三、代码编写:
1、新建一个SerialPort_Parameters.cs类,放串口的参数:
class SerialPort_Parameters    {        public string portName { get; set; }        public int baduRate { get; set; }        public int dataBits { get; set; }        public Parity parity { get; set; }        public StopBits stopBits { get; set; }    }}
2、建立一个读取PLC的类FX_Serial_Communication.cs:
namespace 三菱FX通讯口协议{        class FX_Serial_Communication    {        SerialPort sp = new SerialPort();        string str_Received="";        int num_Byte = 0;        /// <summary>        /// 读X寄存器        /// </summary>        /// <param name="str_X"></param>        /// <returns></returns>        public string Read_X(string str_X){            string[] message_X = Str_Read_X(str_X);            byte[] byte_Message_X = new byte[message_X.Length];            for(int i=0;i< message_X.Length;i++)            {                byte_Message_X = Convert.ToByte(message_X,16);            }            sp.Write(byte_Message_X, 0, message_X.Length);            num_Byte = 0;            str_Received = "";            sp.DataReceived += new SerialDataReceivedEventHandler(Sp_DataReceived);            Thread.Sleep(20);            string x_L = str_Received.Substring(3, 2);            string x_H = str_Received.Substring(6, 2);            string x_Bin_H = Convert.ToString(Convert.ToInt32(x_H, 16), 2).PadLeft(4, '0');            string x_Bin_L = Convert.ToString(Convert.ToInt32(x_L,16),2).PadLeft(4,'0');            string x_Bin = x_Bin_H + x_Bin_L;            if(x_Bin.Substring(7-Convert.ToInt16(str_X.Substring(str_X.Length-1,1)),1)=="1")            {                return "True";            }            else            {                return "False";            }                    }        /// <summary>        /// 读Y寄存器        /// </summary>        /// <param name="str_Y"></param>        /// <returns></returns>        public string Read_Y(string str_Y){            //Open_Serial(sp_para);            string[] message_Y = Str_Read_Y(str_Y);            byte[] byte_Message_Y = new byte[message_Y.Length];            for (int i = 0; i < message_Y.Length; i++)            {                byte_Message_Y = Convert.ToByte(message_Y, 16);            }            sp.Write(byte_Message_Y, 0, message_Y.Length);            num_Byte = 0;            str_Received = "";            sp.DataReceived += new SerialDataReceivedEventHandler(Sp_DataReceived);            Thread.Sleep(20);            string y_L = str_Received.Substring(3, 2);            string y_H = str_Received.Substring(6, 2);            string y_Bin_H = Convert.ToString(Convert.ToInt32(y_H, 16), 2).PadLeft(4, '0');            string y_Bin_L = Convert.ToString(Convert.ToInt32(y_L, 16), 2).PadLeft(4, '0');            string y_Bin = y_Bin_H + y_Bin_L;            if (y_Bin.Substring(7 - Convert.ToInt16(str_Y.Substring(str_Y.Length - 1, 1)), 1) == "1")            {                return "True";            }            else            {                return "False";            }        }        /// <summary>        /// 读D寄存器(32位整数)        /// </summary>        /// <param name="str_D"></param>        /// <returns></returns>        public string Read_BaseD(string str_D){            //Open_Serial(sp_para);            string[] message_Y = Str_Read_BaseD(str_D);            byte[] byte_Message_Y = new byte[message_Y.Length];            for (int i = 0; i < message_Y.Length; i++)            {                byte_Message_Y = Convert.ToByte(message_Y, 16);            }            sp.Write(byte_Message_Y, 0, message_Y.Length);            num_Byte = 0;            str_Received = "";            sp.DataReceived += new SerialDataReceivedEventHandler(Sp_DataReceived);            Thread.Sleep(100);            return str_Received;        }        /// <summary>        /// 数据接收        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void Sp_DataReceived(object sender, SerialDataReceivedEventArgs e){            //str_Received = "";            byte[] byte_Received = new byte[2048];////定义一个接收的数组宁可大不可小            while (sp.BytesToRead > 0) ////如果接收缓冲区还有数据就一直接收直到没有数据            {                int a = sp.ReadByte();//读取当前接收缓冲区的字节数数量                byte_Received[num_Byte] = Convert.ToByte(a);/////读取过来到字节数组中                string ss = Convert.ToString(byte_Received[num_Byte], 16).ToUpper();///转换成16进制并且以大写形式给到SS中                str_Received = str_Received + ss.PadLeft(2, '0') + " "; ///每个字节保持两个字符                               num_Byte++;/////接着接收下一个字节            }        }        /// <summary>        /// 打开串口        /// </summary>        /// <param name="sp_para"></param>        public void Open_Serial(SerialPort_Parameters sp_para){                        sp.PortName = sp_para.portName;            sp.BaudRate = sp_para.baduRate;            sp.DataBits = sp_para.dataBits;            sp.Parity = sp_para.parity;            sp.StopBits = sp_para.stopBits;            if(!sp.IsOpen)            {                sp.Open();            }            else            {                sp.Close();                sp.Open();            }        }        /// <summary>        /// 读PLC软元件X时,发送报文处理        /// </summary>        /// <param name="str_X">软元件X,格式:X1</param>        /// <returns></returns>        public static string[] Str_Read_X(string str_X)        {            string[] str_Read_X = new string[11];            int x = Convert.ToInt16(str_X.Substring(1));            int x_Device10 = 0;            if (x >= 0 && x < 8)            {                x_Device10 = 0 + 128;            }            else if (x >= 10 && x < 18)            {                x_Device10 = 1 + 128;            }            else if (x >= 20 && x < 28)            {                x_Device10 = 2 + 128;            }            else if (x >= 30 && x < 38)            {                x_Device10 = 3 + 128;            }            else if (x >= 40 && x < 48)            {                x_Device10 = 4 + 128;            }            else if (x >= 50 && x < 58)            {                x_Device10 = 5 + 128;            }            string x_Device16 = x_Device10.ToString("X4");            char[] values = x_Device16.ToCharArray();            string[] hexOutput = new string[values.Length];            for (int i = 0; i < values.Length; i++)            {                // Get the integral value of the character.                int value = Convert.ToInt32(values);                // Convert the decimal value to a hexadecimal value in string form.                hexOutput = String.Format("{0:X}", value);            }            str_Read_X[0] = "02";            str_Read_X[1] = "30";            str_Read_X[2] = hexOutput[0];            str_Read_X[3] = hexOutput[1];            str_Read_X[4] = hexOutput[2];            str_Read_X[5] = hexOutput[3];            str_Read_X[6] = "30";            str_Read_X[7] = "31";            str_Read_X[8] = "03";            int sum = 0;            for (int i = 1; i < 9; i++)            {                sum += int.Parse(str_Read_X, System.Globalization.NumberStyles.HexNumber);            }            string sum_16 = sum.ToString("X4");            char[] sum_char = sum_16.ToCharArray();            string[] sum_Hex = new string[sum_char.Length];            for (int i = 0; i < sum_char.Length; i++)            {                int value = Convert.ToInt32(sum_char);                sum_Hex = String.Format("{0:X}", value);            }            str_Read_X[9] = sum_Hex[2];            str_Read_X[10] = sum_Hex[3];            return str_Read_X;        }        /// <summary>        /// 读PLC软元件Y时,发送报文处理        /// </summary>        /// <param name="str_X">软元件Y,格式:Y1</param>        /// <returns></returns>        public static string[] Str_Read_Y(string str_Y)        {            string[] str_Read_Y = new string[11];            int y = Convert.ToInt16(str_Y.Substring(1));            int y_Device10 = 0;            if (y >= 0 && y < 8)            {                y_Device10 = 0 + 160;            }            else if (y >= 10 && y < 18)            {                y_Device10 = 1 + 160;            }            else if (y >= 20 && y < 28)            {                y_Device10 = 2 + 160;            }            else if (y >= 30 && y < 38)            {                y_Device10 = 3 + 160;            }            else if (y >= 40 && y < 48)            {                y_Device10 = 4 + 160;            }            else if (y >= 50 && y < 58)            {                y_Device10 = 5 + 160;            }            string y_Device16 = y_Device10.ToString("X4");            char[] values = y_Device16.ToCharArray();            string[] hexOutput = new string[values.Length];            for (int i = 0; i < values.Length; i++)            {                // Get the integral value of the character.                int value = Convert.ToInt32(values);                // Convert the decimal value to a hexadecimal value in string form.                hexOutput = String.Format("{0:X}", value);            }            str_Read_Y[0] = "02";            str_Read_Y[1] = "30";            str_Read_Y[2] = hexOutput[0];            str_Read_Y[3] = hexOutput[1];            str_Read_Y[4] = hexOutput[2];            str_Read_Y[5] = hexOutput[3];            str_Read_Y[6] = "30";            str_Read_Y[7] = "31";            str_Read_Y[8] = "03";            int sum = 0;            for (int i = 1; i < 9; i++)            {                sum += int.Parse(str_Read_Y, System.Globalization.NumberStyles.HexNumber);            }            string sum_16 = sum.ToString("X4");            char[] sum_char = sum_16.ToCharArray();            string[] sum_Hex = new string[sum_char.Length];            for (int i = 0; i < sum_char.Length; i++)            {                int value = Convert.ToInt32(sum_char);                sum_Hex = String.Format("{0:X}", value);            }            str_Read_Y[9] = sum_Hex[2];            str_Read_Y[10] = sum_Hex[3];            return str_Read_Y;        }        /// <summary>        /// 读PLC基础数据寄存器D(32位)时,发送报文处理        /// </summary>        /// <param name="str_D">基础数据寄存器D(32位),格式:D0表示D0-D1</param>        /// <returns></returns>        public static string[] Str_Read_BaseD(string str_D)        {                        string[] str_Read_D = new string[11];            int D = Convert.ToInt16(str_D.Substring(1));            int D_Device10 = D*2 + 4096;            string D_Device16 = D_Device10.ToString("X4");            char[] values = D_Device16.ToCharArray();            string[] hexOutput = new string[values.Length];            for (int i = 0; i < values.Length; i++)            {                // Get the integral value of the character.                int value = Convert.ToInt32(values);                // Convert the decimal value to a hexadecimal value in string form.                hexOutput = String.Format("{0:X}", value);            }            str_Read_D[0] = "02";            str_Read_D[1] = "30";            str_Read_D[2] = hexOutput[0];            str_Read_D[3] = hexOutput[1];            str_Read_D[4] = hexOutput[2];            str_Read_D[5] = hexOutput[3];            str_Read_D[6] = "30";            str_Read_D[7] = "34";            str_Read_D[8] = "03";            int sum = 0;            for (int i = 1; i < 9; i++)            {                sum += int.Parse(str_Read_D, System.Globalization.NumberStyles.HexNumber);            }            string sum_16 = sum.ToString("X4");            char[] sum_char = sum_16.ToCharArray();            string[] sum_Hex = new string[sum_char.Length];            for (int i = 0; i < sum_char.Length; i++)            {                int value = Convert.ToInt32(sum_char);                sum_Hex = String.Format("{0:X}", value);            }            str_Read_D[9] = sum_Hex[2];            str_Read_D[10] = sum_Hex[3];            return str_Read_D;        }    }}
3、UI层代码如下:
public partial class Form1 : Form    {        FX_Serial_Communication fx_Serial_Comm = new FX_Serial_Communication();        public Form1()        {            InitializeComponent();        }        private void btn_Read_Click(object sender, EventArgs e)        {                       if(cmb_Device.Text=="D")            {                txtBox_Recive.Text = fx_Serial_Comm.Read_BaseD("D"+txtBox_Address.Text);            }            else if(cmb_Device.Text == "X")            {                txtBox_Recive.Text = fx_Serial_Comm.Read_X("X" + txtBox_Address.Text);            }            else if(cmb_Device.Text == "Y")            {                txtBox_Recive.Text = fx_Serial_Comm.Read_Y("Y" + txtBox_Address.Text);            }                    }        private void btn_Conn_Click(object sender, EventArgs e)        {            SerialPort_Parameters sp_Para = new SerialPort_Parameters();            sp_Para.portName = cmb_COM.Text;            sp_Para.baduRate = 9600;            sp_Para.dataBits = 7;            sp_Para.parity = Parity.Even;            sp_Para.stopBits = StopBits.One;            fx_Serial_Comm.Open_Serial(sp_Para);        }    }
四,完整代码较长,如需要完整代码可先关注并留言,然后私信我发送“三菱”即可自动回复,如果能帮助到你,感谢你的关注订阅,可以第一时间接收后续更新。

工控课堂 www.gkket.com

0

主题

121

回帖

288

积分

注册会员

积分
288
发表于 2021-1-30 21:00:20 | 显示全部楼层
论坛有你更精彩!
工控课堂 www.gkket.com

0

主题

113

回帖

365

积分

注册会员

积分
365
发表于 2021-1-30 21:44:49 | 显示全部楼层
真是难得给力的帖子啊。
工控课堂 www.gkket.com

0

主题

88

回帖

131

积分

新手上路

积分
131
发表于 2025-11-16 03:33:29 | 显示全部楼层
赞同 + 10086,完全说出了我的想法!
工控课堂 www.gkket.com

0

主题

100

回帖

151

积分

新手上路

积分
151
发表于 2025-11-16 03:56:03 | 显示全部楼层
蹲个后续,楼主记得更新呀,在线等挺急的~
工控课堂 www.gkket.com

0

主题

83

回帖

112

积分

新手上路

积分
112
发表于 2025-11-16 04:29:31 | 显示全部楼层
浅评一下:内容优质,值得推荐~
工控课堂 www.gkket.com

0

主题

103

回帖

158

积分

新手上路

积分
158
发表于 2025-11-16 05:54:11 | 显示全部楼层
救命!这波发言太秀了,直接原地封神~
疯狂认同!楼主说出了我不敢说的话
工控课堂 www.gkket.com

0

主题

306

回帖

1037

积分

中级会员

积分
1037
发表于 2025-11-16 06:00:07 | 显示全部楼层
这逻辑绝了,分析得太到位了吧
工控课堂 www.gkket.com

0

主题

57

回帖

86

积分

新手上路

积分
86
发表于 2025-11-16 10:33:08 | 显示全部楼层
楼主太会说了,字字句句都在理~
工控课堂 www.gkket.com

0

主题

68

回帖

93

积分

新手上路

积分
93
发表于 2025-11-16 10:33:47 | 显示全部楼层
内容太顶了!疯狂点赞,已默默收藏~
工控课堂 www.gkket.com
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|手机版|免责声明|本站介绍|工控课堂 ( 沪ICP备20008691号-1 )

GMT+8, 2025-12-22 14:14 , Processed in 0.122249 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表