2013-04-15 10 views
5

पर एक टाइमआउट हैलो और इस क्वेरी पर विचार करने के लिए धन्यवाद: मैं एक वर्चुअल सीरियल पोर्ट पर एक एम्बेडेड सिस्टम पर एक पीसी से एक कमांड भेज रहा हूं जो echos आदेश को वापस करें जब एम्बेडेड सिस्टम ने आदेश पूरा कर लिया हो।सी # सीरियल पोर्ट पर एक गूंज की प्रतीक्षा करें, इसे जांचें, और प्रतीक्षा करें

मैं कमांड भेज सकता हूं और इको को देख सकता हूं, जब कमांड एम्बेडेड sytem द्वारा पूरा हो जाता है, लेकिन मुझे गूंज कमांड प्राप्त होने तक प्रोग्राम का इंतजार या देरी करने का उपयुक्त तरीका खोजने में परेशानी हो रही है, ताकि मैं आगे बढ़ सकते हैं और अगली कमांड भेज सकते हैं। मुझे लगता है कि यह एक प्रकार का "उच्च स्तर" प्रवाह नियंत्रण है जिसे मैं कार्यान्वित करने की कोशिश कर रहा हूं। कोड सी # में है। मैं प्रतिध्वनि के लिए इंतजार करना चाहता हूं और पीसी और एम्बेडेड सिस्टम के बीच संचार खो जाने पर भी समय-समय पर इंतजार करना चाहता हूं, ताकि कार्यक्रम स्थिर न हो। वहां कोई भी विज्ज बच्चे है जो ऐसा करने के लिए एक साफ तरीका सुझा सकता है? मैं सिर्फ एक महान सी # प्रोग्रामर नहीं हूं, बस सीख रहा हूं।

यह है कि मेरे पास है समारोह प्राप्त है:

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     // If the com port has been closed, do nothing 
     if (!comport.IsOpen) return; 

     // This method will be called when there is data waiting in the port's buffer 

     // Determain which mode (string or binary) the user is in 
     if (CurrentDataMode == DataMode.Text) 
     { 
      // Read all the data waiting in the buffer 
      string data = comport.ReadExisting(); 

      // Display the text to the user in the terminal 
      Log(LogMsgType.Incoming, data); 
     } 
     else 
     { 
      // Obtain the number of bytes waiting in the port's buffer 
      int bytes = comport.BytesToRead; 

      // Create a byte array buffer to hold the incoming data 
      byte[] buffer = new byte[bytes]; 

      // Read the data from the port and store it in our buffer 
      comport.Read(buffer, 0, bytes); 

      // Show the user the incoming data in hex format 
      Log(LogMsgType.Incoming, ByteArrayToHexString(buffer)); 
      } 
    } 

यह एक फोन का एक उदाहरण के लिए एक कमांड Transmitt के लिए है:

 text = "AR" + 50 + "\r";   //transmit a command to move 
    this.comport.Write(text); 

वर्तमान में मैं एक समय देरी [थ्रेड उपयोग कर रहा हूँ। नींद (TIMEGAP)] और यह मानते हुए कि संदेश निष्पादित किया गया है और एम्बेडेड सिस्टम से वापस गूंज ठीक है लेकिन मैं इसे जांच नहीं करता हूं और यह सुनिश्चित करने के लिए बहुत लंबा समय भी प्रतीक्षा करता हूं कि यह पूरा हो गया है:

 text = "AR" + 50 + "\r";   //transmit a command to move 
    this.comport.Write(text); 
    Thread.Sleep(TIMEGAP);    //Timegap = 10000ms 

मैं वास्तव में समय विलंब कॉल [थ्रेड स्लीप (टाइमजीएपी)] को एक फ़ंक्शन/विधि के साथ प्रतिस्थापित करना चाहता हूं जो सीरियल पोर्ट पर प्रतिक्रिया की निगरानी करता है, यह देखने के लिए जांच करता है कि यह एक भेजा गया है और फिर प्रोग्राम कोड को अगले कमांड पर जाने की अनुमति देता है, और यदि उपरोक्त उदाहरण में सही गूंज [AR50 \ r] उदाहरण 5 सेकंड के लिए कहने में प्राप्त नहीं होता है, तो प्रोग्राम एक त्रुटि रिपोर्ट करता है।

कोई सुझाव?

धन्यवाद!

+0

DataReceived घटना, एक पूरी लाइन के लिए सक्रिय नहीं होगा तो आप एक वैश्विक बफर में प्राप्त डेटा को श्रेणीबद्ध चाहिए। –

+0

एक बार जब आप थ्रेड स्लीप() का उपयोग करने पर विचार करना शुरू कर देते हैं तो आप DataReceived ईवेंट का उपयोग करने के अच्छे कारणों से बाहर हो गए हैं।प्रतिक्रिया प्राप्त करने के लिए बस SerialPort.Read() का उपयोग करें। लंबी देरी से निपटने के लिए जो आमतौर पर अगली समस्या हो सकती है। चट्टान और सख्त जगह। –

उत्तर

6

सबसे आसान तरीका DataReceived ईवेंट का उपयोग नहीं करना है, लेकिन ReadTimeout और Read विधि का उपयोग करके।

और चूंकि आप ASCII से निपट रहे हैं, तो आपको ReadLine विधि की जांच करनी चाहिए।

दोनों TimeoutException फेंक देंगे यदि ReadTimeout आने वाले डेटा के बिना समाप्त हो गया है।

यदि, हालांकि, एम्बेडेड सिस्टम अनचाहे संदेश भेज सकता है, तो आपको एक अन्य दृष्टिकोण की आवश्यकता होगी। फिर आप गूंज को वैश्विक स्ट्रिंग वेरिएबल में उम्मीद कर सकते हैं, और इको प्राप्त होने पर प्राप्त ईवेंट ManualResetEvent सेट कर सकता है। फिर आप टाइमआउट के साथ ManualResetEvent के लिए प्रतीक्षा कर सकते हैं। इसमें lock कथन का उपयोग करके थ्रेड सिंक्रनाइज़ेशन भी शामिल होगा।

हैं जीसी कोई मुद्दा नहीं है, मैं शायद कुछ इस तरह के साथ शुरू होगा:

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

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static string serialBuffer = ""; 
     static string expectedEcho = null; 
     static object expectedEchoLock = new object(); 
     static ManualResetEvent expectedEchoReceived = new ManualResetEvent(false); 
     static SerialPort port = new SerialPort("COM1", 19200, Parity.None, 8, StopBits.One); 

     static void Main(string[] args) 
     { 
      port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); 
     } 

     static void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
     { 
      while (port.BytesToRead > 0) 
      { 
       byte[] buffer = new byte[port.BytesToRead]; 
       int bytesRead = port.Read(buffer, 0, buffer.Length); 
       if (bytesRead <= 0) return; 
       serialBuffer += Encoding.UTF8.GetString(buffer, 0, bytesRead); 
       string[] lines = serialBuffer.Split('\r', '\n'); 
       // Don't process the last part, because it's not terminated yet 
       for (int i = 0; i < (lines.Length - 1); i++) 
       { 
        if (lines[i].Length > 0) 
         ProcessLine(lines[i]); 
       } 
       serialBuffer = lines[lines.Length - 1]; // keep last part 
      } 
     } 

     static void ProcessLine(string line) 
     { 
      bool unsolicitedMessageReceived = false; 
      lock (expectedEchoLock) 
      { 
       if (line == expectedEcho) 
       { 
        expectedEchoReceived.Set(); 
       } 
       else 
       { 
        unsolicitedMessageReceived = true; 
       } 
      } 
      if (unsolicitedMessageReceived) 
      { 
       // Process unsolicited/unexpected messages 
      } 
     } 

     /// <summary> 
     /// Send a command and wait for echo 
     /// </summary> 
     /// <param name="command">The command to send</param> 
     /// <returns>True when echo has been received, false on timeout.</returns> 
     static bool SendCommand(string command) 
     { 
      lock (expectedEchoLock) 
      { 
       expectedEchoReceived.Reset(); 
       expectedEcho = command; 
      } 
      port.Write(command); 
      return expectedEchoReceived.WaitOne(5000); // timeout after 5 seconds 
     } 
    } 
} 
+0

ट्रांसमिट कोड में मुझे लगता है कि वह WriteTimeout सेट करना चाहता है। और मुझे लगता है कि comport.Write() एक अवरुद्ध कॉल है और हुड के तहत मूल रूप से सफलता के ट्रांसमीटर को सूचित करेगा या टाइमआउट अपवाद फेंक देगा। – Richthofen

+0

लिखें केवल तभी ब्लॉक होगा जब आरटीएस/सीटीएस हैंडशेकिंग जैसे प्रवाह नियंत्रण का उपयोग किया जाता है। –

+0

धन्यवाद वाउटर, रिचथोफेन, मैं इसे एक दूंगा। ऐसा लगता है कि 'डॉक्टर ने क्या आदेश दिया', मुझे लगता है। – user2281033

संबंधित मुद्दे