模擬三菱FX2N系列PLC的串列埠通訊(實測通過)

鄉村彩虹發表於2014-12-29

軟體開發背景:由於專案需要,上位機軟體與三菱FX2N系列PLC的串列埠交換資料時,但手頭上又沒有PLC硬體,所以開發了這樣一個工具來當PLC使用。

/*

功能:模擬PLC的資料通訊
作者:
日期:2013-05-01
說明:
 */


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;


using System.IO.Ports;
using System.Threading;


namespace CommAssist
{
    public partial class Form1 : Form
    {
        public delegate void Displaydelegate(byte[] InputBuf);
        Byte[] OutputBuf = new Byte[128];
        Byte[] CommRcvBuf = new Byte[128];
        int RcvCount = 0;
        bool bFlagRcvOK=false;
        bool RcvFlag = false;
        SerialPort Comm = new SerialPort("com7", 19200, Parity.None, 8, StopBits.One);     
        public Displaydelegate disp_delegate;


        public Form1()
        {
            disp_delegate = new Displaydelegate(DispUI);
            InitializeComponent();
            int mytemp;


            comboBox1.SelectedItem = "com7";
            Comm.DataReceived += new SerialDataReceivedEventHandler(Comm_DataReceived);


            string[] ports = SerialPort.GetPortNames();
            Array.Sort(ports);
            comboBox1.Items.AddRange(ports);
            comboBox1.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;
     }


        public void DispUI(byte[] InputBuf)
        {
            //textBox1.Text = Convert.ToString(InputBuf);
            int i;
            byte GetData;
            
            for (i = 0; i < InputBuf[0]; i++)
            {
                if (!bFlagRcvOK)
                {
                    GetData = InputBuf[1+i];
                    switch (RcvCount)
                    {
                        case 0: if (GetData == 0x05)
                            {
                                CommRcvBuf[RcvCount] = GetData;
                                RcvCount++;
                            }
                            else
                                RcvCount = 0;
                            break;


                        case 1: if (GetData == 0x30)
                            {
                                CommRcvBuf[RcvCount] = GetData;
                                RcvCount++;
                            }
                            else if (GetData == 0x05)
                            {
                                
                            }
                            else
                            {
                                RcvCount = 0;
                            }
                            break;


                        case 2: if (GetData == 0x31)
                            {
                                CommRcvBuf[RcvCount] = GetData;
                                RcvCount++;
                            }
                            else
                                RcvCount = 0;
                            break;
                        case 3: if (GetData == 0x46)
                            {
                                CommRcvBuf[RcvCount] = GetData;
                                RcvCount++;
                            }
                            else
                                RcvCount = 0;
                            break;
                        case 4: if (GetData == 0x46)
                            {
                                CommRcvBuf[RcvCount] = GetData;
                                RcvCount++;
                            }
                            else
                                RcvCount = 0;
                            break;
                        default:
                            RcvFlag = true;
                            break;
                    }


                    if (RcvFlag) // receive valid data
                    {
                        RcvFlag = false;
                        CommRcvBuf[RcvCount] = GetData;
                        RcvCount++;


                        if (RcvCount >= 17)
                        {
                            //MessageBox.Show("收到串列埠資料"); test
                            //BtnTest_Click();
                            this.BtnTest_Click(null,null);
                            bFlagRcvOK = false; // 錯誤溢位處理
                            RcvCount = 0;


                        }
                    }
                }
                else
                    break;
            }
            
            ASCIIEncoding encoding = new ASCIIEncoding();
            textBox1.Text= encoding.GetString(InputBuf);
            //return (constructedString); 
        }
        private void BtnTest_Click(object sender, EventArgs e)      // 返回主機
        {
            int i;            
            string buf;
            byte temp;
            Byte[] sum = new Byte[10];


            try
            {
                OutputBuf[0] = 0x02;            
                OutputBuf[1] = 0x30;
                OutputBuf[2] = 0x31;
                OutputBuf[3] = 0x46;
                OutputBuf[4] = 0x46;
                //-------------
                OutputBuf[5] = 0x30;
                OutputBuf[6] = 0x31;
                OutputBuf[7] = 0x30;
                OutputBuf[8] = 0x31;


                OutputBuf[9] = 0x30;
                OutputBuf[10] = 0x31;
                OutputBuf[11] = 0x30;
                OutputBuf[12] = 0x31;


                OutputBuf[13] = 0x30;
                OutputBuf[14] = 0x31;
                OutputBuf[15] = 0x30;
                OutputBuf[16] = 0x31;


                OutputBuf[17] = 0x30;
                OutputBuf[18] = 0x31;
                OutputBuf[19] = 0x30;
                OutputBuf[20] = 0x31;


                OutputBuf[21] = 0x03;
                sum[0] = 0;
                for (i = 0; i < 21; i++)
                    sum[0] +=OutputBuf[i+1];
                string str = BitConverter.ToString(sum);
                OutputBuf[22] = (byte)str[0];
                OutputBuf[23] = (byte)str[1];
                Comm.Write(OutputBuf,0,24);
            }
            catch (TimeoutException ex)         //異常處理
            {
                MessageBox.Show(ex.ToString());
            }
        }


        void Comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int count,i;
            Byte[] InputBuf = new Byte[128];


            System.Threading.Thread.Sleep(20);
            try
            {
                count = Comm.BytesToRead;
                Comm.Read(InputBuf,0,Comm.BytesToRead);
                for (i = 0; i < count; i++)
                {
                    InputBuf[count - i] = InputBuf[count - i-1];
                }
                InputBuf[0] = (byte)count;


                //InputBuf = UnicodeEncoding.Default.GetBytes(strRD);    
                //System.Threading.Thread.Sleep(50);
                this.Invoke(disp_delegate, InputBuf);
               
           }
            catch (TimeoutException ex)         //超時處理
            {
                MessageBox.Show(ex.ToString());
            }      


        }


        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)     //選擇串列埠的處理過程
        {
            bool b_OpenFlag = Comm.IsOpen;
            if (b_OpenFlag == true)
            {
                Comm.Close();
                Comm.PortName = comboBox1.SelectedItem.ToString();
                Comm.Open();
            }
            else
            {
                Comm.PortName = comboBox1.SelectedItem.ToString();
            }
         }


        private void OpenSerialPort_Click(object sender, EventArgs e)               //點選“開啟串列埠”按鈕的操作
        {
            if (OpenSerialPort.Text == "關閉串列埠")
            {
                Comm.Close();
                OpenSerialPort.Text = "開啟串列埠";
            }
            else
            {
                Comm.Open();
                OpenSerialPort.Text = "關閉串列埠";
            }
        }
    }
}

相關文章