1. 程式人生 > >C# SerialPort 讀寫三菱FX系列PLC

C# SerialPort 讀寫三菱FX系列PLC

1:串列埠初始化  

com = new SerialPort("COM3", 9600, Parity.Even, 7, StopBits.One);

2:開啟關閉串列埠

if (com.IsOpen)

 {com.Close();}

com.Open();

if (com.IsOpen)

{ com.Close();}

3:C# ASCII轉字元及字元轉ASCII

public static string Chr(int asciiCode)
        {
            if (asciiCode >= 0 && asciiCode <= 255)
            {
                System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();
                byte[] byteArray = new byte[] { (byte)asciiCode };
                string strCharacter = asciiEncoding.GetString(byteArray);
                return (strCharacter);
            }
            else
            {
                throw new Exception("ASCII Code is not valid.");
            }

        }

public static int Asc(string character)
        {
            if (character.Length == 1)
            {
                System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();
                int intAsciiCode = (int)asciiEncoding.GetBytes(character)[0];
                return (intAsciiCode);
            }
            else
            {
                throw new Exception("Character is not valid.");
            }

        }

4:寫入串列埠的命令字串的和校驗

/// <summary>
        /// 和校驗
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public string SumCheck(string data)
        {
            int sum = 0;
            for (int i = 0; i < data.Length; i++)
            {
                sum += Asc(data.Substring(i, 1));
            }

            string res = sum.ToString("X");
            res = res.Substring(res.Length - 2, 2);

            return res;

        }

 5:寫入PLC

private void btnWrite_Click(object sender, EventArgs e)

        { 

            string[] write = new string[] { "2","2"}; //將準備寫入PLC的值
            //將要寫入的值轉換成16進位制數,補齊兩個位元組,注意高低位元組需要交換
            string sWriteData = "";
            for (int i = 0; i < write.Length; i++)
            {
                int val = Convert.ToInt32(write[i].Length>0?write[i]:"0");
                string s = val.ToString("X");
                while (s.Length<4)
                {
                    s = "0" + s;
                }
                sWriteData += s.Substring(2,2)+s.Substring(0,2);
            }

            MessageBox.Show(sWriteData);
            //寫入命令,1表示寫入,1194表示D202這個地址的16進位制,04表示D202,D203為4個BYTE,1194=(202*2)+4096的16進位制數,至於用它表示D202的起始位置,三菱故意要這麼麻煩了.
            sWriteData = "1119404" + sWriteData + Chr(3);
            //chr(2)和chr(3)是構成命令的標誌字元,然後加上校驗和,命令組織完成
            sWriteData = Chr(2) + sWriteData + SumCheck(sWriteData);

            MessageBox.Show(sWriteData);
            //寫入串列埠
            com.Write(sWriteData);
            //byte[] data = Encoding.ASCII.GetBytes(sWriteData); 
            //com.Write(data,0,data.Length);

        }

6:讀PLC

 private void btnRead_Click(object sender, EventArgs e)
        {
            
            this.txtRead0.Clear();
            string sReadData = "";

            //在讀PLC中的資料之前,需要先發個指令給它,讓它將資料傳送到串列埠,下面的字串中,chr(2),chr(3)為PLC命令的格式標誌,0119404中,0表示讀,1194表示D202的起始地址,04表示讀D202,D203兩個字,共4個位元組,66為0119404和chr(3)的校驗和,向串列埠寫入"讀"命令,其實和向plc地址中寫入資料是一樣的,只是沒有資料,用0表示讀

            string sReadCmd = Chr(2) + "0119404" + Chr(3) + "66";
            com.Write(sReadCmd);
            //等待1秒鐘
            System.Threading.Thread.Sleep(1000);
            // 從串列埠讀資料
            byte[] data = new byte[1024];
            com.Read(data, 0, 1024);

           //如果首位為2,則表示資料有效.這裡有個問題,在第二次讀,第2位才為'2',第三次又是首位為2,需要再測試
            if (data[0]==2)
            {
                string sReceiveData = System.Text.Encoding.ASCII.GetString(data);
                //MessageBox.Show(sReceiveData);
               //解析命令,將讀到的字元解析成數字,注意高低位的轉換
                for (int i = 1; i < 8; i += 4)
                {
                    string sLow = sReceiveData.Substring(i,2);
                    string sHigh = sReceiveData.Substring(i + 2, 2);
                    //int res = Convert.ToInt32(sHigh)+ Convert.ToInt32(sLow);
                    int res = Convert.ToInt32(sHigh,16) + Convert.ToInt32(sLow,16);

                    this.txtRead0.Text += res.ToString() + ",";
                }               
                
            }