2017-03-23 113 views
1

마이크로 프로세서와 C# 양식 응용 프로그램 간의 직렬 통신을 시도하고 있습니다.C# SerialPort 수신 포트

마이크로 프로세서에서 오는 데이터는 2 초 또는 5 초 또는 10 초가 될 수 있습니다. 내 말은 특정 시간이 없다는 것을 의미하며, 포트를 청취하고 데이터를 얻고 싶다면 2 초 후에 데이터를 기다려야합니다.

나는 이것을 serialport.readline();로 시도했다. 그러나 양식은 readline 블로킹 중에 멈추었 기 때문에 backgroundworker와 작업을 시도했는데 readline 명령어가 전체 프로그램을 차단하기 때문에 backgroundworker가 사용 중일 때 양식을 닫을 수 없습니다.

내가 말하는 모든 것은, 데이터를 가져 오는 동안 포트를 듣는 것에 대한 단서를 제공하십시오. 시간은 구체적이지 않습니다.

이 시간 내 주셔서 감사

+0

는 당신이 우리를 보여줄 수있는 어떤 코드 샘플을 가지고 있습니까? –

+0

새로 추가하는 중 stackoverflow – oakar

+0

양식 닫기 이벤트에서 아마도 직렬 포트에서'Close()'호출을 시도 할 수 있습니다. 'BackgroundWorker'를 사용하는 경우 읽기 호출을 차단 해제해야합니까? – nicholas

답변

1

당신은 데이터 비동기를 얻기 위해 SerialPort.DataReceived Event을 사용할 수 있습니다 (죄송합니다 영어 것이 잘되지 않습니다). SerialPort 클래스의 인스턴스를 만든 후에는 SerialPort에 이벤트 처리기를 추가 할 수 있습니다. 데이터를 수신하면 이벤트 핸들러가 호출됩니다.

mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); 

핸들러 내부에서 입력 버퍼에서 데이터를 읽고 원하는 것을 수행 할 수 있습니다.

private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
{ 
    SerialPort sp = (SerialPort)sender; 
    string indata = sp.ReadExisting(); 
    //Do what ever you want with the data 
} 

이것은 응용 프로그램을 실행하지 않고 불규칙한 시간 간격으로 데이터를 가져 오는 매우 일반적인 해결책입니다.

+0

하지만 난 하나의 데이터를 예를 들어, 내가 직렬 포트에 400 데이터를 얻을 때 데이터와 데이터 startswith 사이의 공간을 얻을 "!" 그리고 "\ n"로 끝나기 때문에 배열을 사용하고 배열처럼 쓸 수 없다고 쓴다면. – oakar

+0

예를 게시 할 수 있습니까? – Fruchtzwerg

+0

@oakar는 공백으로 문자열을 나눠서 400 요소의 문자열 []을 얻습니다. –

1

DataReceived 이벤트를 사용할 수 있습니다. 새 데이터가 포트에 도착할 때마다 해고 될 것입니다. 이처럼에 등록해야합니다 :

SerialPort port = new SerialPort(/*your specification*/); 
port.DataReceived += Port_DataReceived; 

이벤트 처리기에서 당신은 다음 지금 방금 포트를 열 필요가 들어오는 데이터

private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    SerialPort port = sender as SerialPort; 

    if (port != null) 
    { 
     var incoming_message = port.ReadExisting(); 
    } 
} 

을 읽을 것이며, 자동으로 수신합니다. 노트! 들어오는 데이터는 주 스레드와 다른 스레드에 도착합니다.

var incoming_message = port.ReadLine(); 

아니면 시도 할 수 있습니다 : 데이터가 당신이 ReadLine 방법을 사용하여 시도 할 수 \n과 끝 부분에 표시되어있는 경우는 표시 양식의 컨트롤을 사용하려는 경우 그래서 당신은 BeginInvoke

를 사용할 필요가 ReadTo

var incoming_message = port.ReadTo("\n"); 

편집 :

시간이 오래 걸리는 경우 일괄 적으로 읽어야합니다. while 루프에서 처리하려고 할 수도 있습니다.

private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    SerialPort port = sender as SerialPort; 

    string message = ""; 
    if (port != null) 
    { 

     while(port.BytesToRead > 0) 
     { 
      message += port.ReadExisting(); 
      System.Threading.Thread.Sleep(500); // give the device time to send data 
     } 
    } 
} 

편집 2 :

당신이 데이터가 이벤트 핸들러의 List<string> 외부를 선언하고이 완전히 읽을 때 문자열을 추가 저장합니다.

List<string> dataStorage = new List<string>(); 


private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    SerialPort port = sender as SerialPort; 

    string message = ""; 
    if (port != null) 
    { 

     while(port.BytesToRead > 0) 
     { 
      message += port.ReadExisting(); 
      System.Threading.Thread.Sleep(500); // give the device time to send data 
     } 
     // add now the entire read string to the list 
     dataStorage(message); 
    } 
} 

이벤트 핸들러는 A 또는 B 그냥 하나의 목록에서 전체 수신 된 메시지를 수집 보내 여부를 알 수 없기 때문에

. 당신은 너무 나중에 해당 메시지를 꺼내 배열에 400 개 항목을 얻을 수 Split을 사용할 수 있습니다, 당신은 당신의 명령을 보내도록하는 순서를 알고

string [] A_array_data = dataStorage[0].Split(" "); 
+0

내가 이것을 사용했지만 Read.existing()은 직렬 포트에 A를 쓸 때 예를 들어 전체 데이터를 기다리지 않고 데이터와 데이터 사이에 공백이있는 400 개의 데이터를 시작합니다 "!" 그리고 "\ n"로 끝나기 때문에 배열을 사용하고 배열과 같이 쓰면 relaible (나는 split을 사용)이되지 않습니다. – oakar

+0

@oakar 장치가 400 바이트를 전송하는 데 얼마나 오래 걸리나요? 그게 바이트 야? 또는 400 자? –

+0

'ReadLine()'시도해 보셨습니까? –