none
SerialPort通訊回傳值問題 RRS feed

  • 問題

  • 請教一下各位先進

     

    我用C#對應我手邊的裝置做Modbus RTU的通訊

    很奇怪的一點就是寫入是可以寫入

    我也可以明確的看到我寫入的資料改變它的數值

    但是我在下命令要他讀出時

    讀出的命令竟然跟我前一個下的命令是一樣的

    而不是我文件看到的資料格式與我想要的資料

     

    現在就變成了看起來可以通訊

    但卻是只能寫入不能讀出

    後來又測試了一下

    換了一個裝置測試也是回傳值與命令相同

    最詭異的是我裝置不插電竟然也是一樣  Orz

    我想一定是我程式有問題

    但不知道該怎麼抓

    拜託請大家給我個方向吧

    謝謝各位

     

    我的主程式

    Code Snippet

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

    namespace Modbus2PXR
    {
        public partial class Form1 : Form
        {
            public float factor;
            Crc16 CRC = new Crc16();
            byte[] inbyte;
            public Form1()
            {
                InitializeComponent();
                btnStopCommunicate.Visible = false;
            }


            private void btnSetSV_Click(object sender, EventArgs e)
            {
                string buf;

                CRC.check_outbyte((int)(numberOfStation.Value), 6, 1002, (int)(numberOfSV.Value));

                serialPort1.Write(CRC.outbyte, 0, CRC.outbyte.Length);

    // 可正常寫入

            }

     

            private void btnRead_Click(object sender, EventArgs e)
            {
                string buf;

                CRC.check_outbyte((int)(numberOfStation.Value), Convert.ToInt32(tbxCommand.Text), Convert.ToInt32(tbxAddress.Text), Convert.ToInt32(tbxCount.Text));
                serialPort1.Write(CRC.outbyte, 0, CRC.outbyte.Length);
                Thread.Sleep(50);
                buf = "";
                inbyte = new byte[serialPort1.BytesToRead];
                serialPort1.Read(inbyte, 0, inbyte.Length);
                for (int i = 0; i < inbyte.Length; i++)
                {
                    buf = buf + inbyte[i].ToString("X2") + " ";
                }
                tbxResponse.Text = buf;

    // 但下命令要讀出時,得到的讀出值卻是之前所下的命令


            }

     

     

    我的CRC16的類別判斷式,這是根據給的文件所寫的

    Code Snippet

        public class Crc16
        {
            public byte[] outbyte;
           
            public void check_outbyte(int station, int code, int address, int data1)
            {
                int CR, CH, CT;
                outbyte = new byte[8];
                outbyte[0] = (byte)(station);
                outbyte[1] = (byte)(code);
                outbyte[2] = (byte)(address / 256);
                outbyte[3] = (byte)(address % 256);
                outbyte[4] = (byte)(data1 / 256);
                outbyte[5] = (byte)(data1 % 256);
                CR = 0xFFFF;
                for (int i = 0; i < 6; i++)
                {
                    CR = (int)(CR ^ outbyte[i]);
                    for (int j = 1; j < 9; j++)
                    {
                        CT = CR & 0x01;
                        if (CR < 0)
                        {
                            CH = 1;
                            CR = (int)(CR & 0x7FFF);
                        }
                        else
                        {
                            CH = 0;
                        }
                        CR = (int)(CR / 2);
                        if (CH == 1)
                        {
                            CR = (int)(CR | 0x4000);
                        }
                        if (CT == 1)
                        {
                            CR = (int)(CR ^ 0xA001);
                        }
                    }
                }

                outbyte[6] = (byte)(CR & 0xFF);
                outbyte[7] = (byte)(((CR & 0xFF00)/256) & 0xFF);

            }

     

     

    2008年9月3日 上午 02:03

所有回覆

  • 您好:

     

    Code Snippet

                string buf;

                buf = "";


                inbyte = new byte[serialPort1.BytesToRead];
                serialPort1.Read(inbyte, 0, inbyte.Length);
                for (int i = 0; i < inbyte.Length; i++)
                {
                    buf = buf + inbyte[i].ToString("X2") + " ";
                }

     

    上面這一段是不是應該考慮寫在SerialPort.DataReceived 事件裡面?

    2008年9月3日 上午 09:22
  • 感謝 藍星人的回覆

     

    我有試著將 SerialPort.DataRecived事件寫入

    但是對於這個事件的觸發我一點都不了解

    在找程式範本的過程中有發現了這樣的東西

    求藍星大大幫我指點一下

     

    Code Snippet

        public partial class Form1 : Form
        {
            static EventWaitHandle waitSignal = new AutoResetEvent(false);
            static int Wait_TimeOut = 20;       // 收回應碼等待時間

     

         .............略

     

     

            // 收到期望回傳值觸發
            private void COMPORT_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
            {
                //Console.WriteLine("Set");
                waitSignal.Set();
            }

     

    不知這樣所觸發的 waitSignal.Set() 可以觸發什麼

    對於 EventWaitHandle waitSignal = new AutoResetEvent(false)

    也是懵懵懂懂

    有看過一篇文章說 這類似像是設定紅綠燈一樣 目前是為紅燈

    但還是不甚了解

     

    2008年9月4日 上午 06:18
  • EventWaitHandle.Set Metohd在這裡的用意應該是先讓目前由SerialPort.DataReceived所觸發的事件先處理結束,然後再繼續等待下一個事件的觸發。

    2008年9月4日 上午 08:16
  • 如果說裝置斷電,還能讀到訊號,而且是送出的信號,有可能是RX和TX並連接到了,

    你可以試試把RX的線先移除,只留TX線,這樣只會有送出的訊號,不會接收到訊號,

    確定一下是否線路有問題.

    2008年9月4日 上午 09:53
  • 可能是你发出的命令中没有以换行符“\r”结束,我也遇到过类似问题。
    建议参考:http://blog.chinaunix.net/u/15586/showart_190735.html

    2009年8月2日 上午 09:10
  • 您好,我之前也問過類似的問題,您可以參考這篇的解答。

    http://social.msdn.microsoft.com/Forums/zh-TW/233/thread/3a3fe086-554c-44fa-89aa-09c209821cda    (感謝Bill Chung指導)

    另外再回傳資料的部分,您可以在網路上抓到一些應用小程式,可以回傳RS232封包。

    我這邊有測試用的程式,如果您願意留信箱的話我很樂意寄一份給您。

    首先除了您使用的RS232線之外,請再準備一條RS232的線,在此先將線做分別(連接儀器線稱為A)、(檢測線稱為B)。

    先將線A的 RxD 接上 B的 TxD,接著再將線A接上儀器,線B接上第二台PC。

    接著開啟接收程式,我用的是 串列埠偵錯助手V2.2 , 學長給的。

    開啟後可以選擇serial port 、鮑率等等,接著在你下命令的時候,將可以從線B中接收到是否有回傳資料,資料型態為ASCII或16進位。

    http://www.dotblogs.com.tw/billchung/archive/2009/04/12/7981.aspx

    置於你沒插電也有回傳值,上面有前輩說過了,應該是線路上的問題。

    下面是我之前寫的,可以請參考一下。

            private void button9_Click(object sender, EventArgs e)
            {
                if (serialPort1.IsOpen == true)
                {
                     int i;
                    int [] bytes = new int [20]; //宣告資料空間
                  
                    serialPort1.Write(new byte[] { 0x0E }, 0, 1); //下命令
                    richTextBox1.Text = "";
                    richTextBox1.Text += "成功的送出了訊息!!" + "\n";
                    for (i = 0; i <= 10; i++)
                    {
                        bytes[i] = serialPort1.ReadByte(); //讀取10筆資料
                    }
                    for (i = 0; i <= 10; i++)
                    {
                        richTextBox1.Text += "陣列數值為:" + bytes[i] + "\n"; //列出10筆資料
                    }
                    richTextBox1.Text += "\n";
                }
                else
                    MessageBox.Show("尚未開啟SerialPort", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

    最近才剛開始學C#,我用蠻簡單的方法可以讀的出來回傳byte。

    不知道能不能幫上板大的忙。

    2009年8月3日 下午 06:58