답변 정말 감사드립니다.
이제서야 확인 했어요 ㅜㅜ
아직 초보라 조금 어려운데
참고해서 해결해보도록 할게요
송신영 님이 쓰신 글 :
: 시리얼 통신 수신 처리 부의 여러 가지 방법 중에
: 간단한 방식 하나만 참고 하시라고 올려드립니다.
: 주석 잘 읽어 보시면 조금 도움이 될겁니다.
: (온도 컨트롤러와 통신할 때 사용한 소스입니다.)
:
: STX 12345 ETX
: STX 12345 ETX STX 12345 ETX
: STX 12345 ETX STX 123
: STX 123
: 2345 ETX
: 2345 ETX STX 123
: 2345 ETX STX 12345 ETX
:
: 시리얼 통신에서는 위와같이 이런 저런 모든 경우를 처리할 수 있는 코드를 작성해야합니다.
: 중간에 끈겨서 들어왔다고 무조건 버리면 안되고 차곡차곡 모아서 프로토콜과 맞는 상태가
: 될 때 까지 계속 비교해 봐야 합니다.
:
:
: //---------------------------------------------------------------------------
: // *.h 파일
: // 수신 버퍼는 데이터가 여러번 잘린 상태로 들어올 수 있으니 멤버 변수나 글로벌로 잡아
: AnsiString m_sTEMP_RECEIVE_BUFFER ; 야함.
:
: // *.cpp 파일.
: //---------------------------------------------------------------------------
: void __fastcall TfmMain::ComPortRxChar(TObject *Sender, int Count)
: {
: String szStrTemp;
:
: char cBCC;
: char cCalBCC;
: int nSTXIndex;
: int nETXIndex;
: int nStrLen;
:
: ComPort->ReadStr(szStrTemp, Count);
:
: AnsiString sReadBuffer = szStrTemp;
:
: try {
: // 수신 데이터 처리 하는 도중 다음 데이터가 들어올 경우를 대비하여 크리티컬섹션으로 잡고 작업을 진행 해야 함.
: EnterCriticalSection(&m_SyncTempComPort);
:
: m_sTEMP_RECEIVE_BUFFER = m_sTEMP_RECEIVE_BUFFER + szStrTemp;
:
: while(1) {
: // STX 시작 위치 찾기 (1부터 시작)
: nSTXIndex = m_sTEMP_RECEIVE_BUFFER.AnsiPos(sSTX);
:
: if(nSTXIndex > 0) {
:
: // STX 앞부분 잘라내기 (STX앞부분은 이전에 처리된 값이거나 쓰래기 값이기 때문에 삭제한다. )
: if(nSTXIndex > 1) {
: szStrTemp = m_sTEMP_RECEIVE_BUFFER.SubString(nSTXIndex, m_sTEMP_RECEIVE_BUFFER.Length());
: m_sTEMP_RECEIVE_BUFFER = szStrTemp;
: szStrTemp = "";
: }
:
: // ETX 위치 찾기 (1부터 시작)
: nETXIndex = m_sTEMP_RECEIVE_BUFFER.AnsiPos(sETX);
:
: // 데이터 크기 구하기
: // BCC 값은 0x00 즉 문자로 보면 NULL일 경우도 있다.
: // 그러므로 일반 char 배열로 받으면 처리가 곤란해 진다.
: // 그래서 수신 버퍼를 AnsiString 으로 사용하면 NULL 문자도 .Length()에
: // 포함되기 때문에 효과적이다.
: nStrLen = m_sTEMP_RECEIVE_BUFFER.Length();
:
: if(nETXIndex > 1 && (nStrLen >= (nETXIndex+1))) { // ETX 위치 유효한지 확인, BCC 수신 확인.
: AnsiString sCommand; // STX - ETX 까지 (BCC를 다시 계산하여 수신된 BCC와 비교하기 위해)
: AnsiString sFullMessage; // STX - BCC 까지
:
: // 수신한 데이터에서 STX-ETX까지(완전한 문장 하나)의 데이터만 일단 복사.
: sCommand = m_sTEMP_RECEIVE_BUFFER.SubString(1, nETXIndex);
:
: sFullMessage = m_sTEMP_RECEIVE_BUFFER.SubString(1, nETXIndex+1);
:
: // BCC 얻어온다.
: cBCC = m_sTEMP_RECEIVE_BUFFER.c_str()[nETXIndex];
:
:
: // 위에서 얻어온 데이터까지 수신 버퍼에서 삭제한다.
: if(m_sTEMP_RECEIVE_BUFFER.Length() == nETXIndex +1){
: // BCC 뒤에 더이상 값이 없을 경우 변수 초기화.
: m_sTEMP_RECEIVE_BUFFER = "";
: }
: else {
: // BCC 뒤에 값이 더 있을 경우 뒷부분만 남기고 앞부분 삭제.
: szStrTemp = m_sTEMP_RECEIVE_BUFFER.SubString(nETXIndex+2,
: (m_sTEMP_RECEIVE_BUFFER.Length()-(nETXIndex+1)));
: m_sTEMP_RECEIVE_BUFFER = "";
: m_sTEMP_RECEIVE_BUFFER = szStrTemp;
: szStrTemp = "";
: }
:
: // 수신한 데이터의 BCC를 계산한다.
: cCalBCC = MakeBCC(sCommand, false, true); // BCC 계산에서 STX제외. ETX는 포함
:
:
: // 수신한 BCC와 계산한 BCC확인하여 동일하지 않은 경우 노이즈를 탄것이니 그냥 무시하고 다음을 기다린다.
: if(cCalBCC != cBCC){
: // TODO: BCC 오류 발생 시 사용자게에 알려주는 코드를 삽입한다. (현재는 그냥 무시)
: }
: else if(sCommand.Length() > 0) {
:
: // 수신 데이터 처리 루틴.....
:
: }
: }
: else {
: break;
: }
: }
: else {
: // STX가 없을 경우 현재까지 받은 모든 데이터는 필요 없는 데이터 이니 수신 버퍼 초기화.
: m_sTEMP_RECEIVE_BUFFER = "";
: break;
: }
: }
: }
: __finally {
: LeaveCriticalSection(&m_SyncTempComPort);
: }
:
: }
:
:
:
:
: 님이 쓰신 글 :
: : 아아 무슨 말씀이신지는 이해 됬어요!
: :
: : rxchar 에서 rx버퍼에 데이터를 받을때
: :
: : rx_buf[rx_pt++] = ch;
: : if (ch==_STX)
: : {
: : rx_buf[0] = ch;
: : rx_pt = 1;
: : }
: : else if (ch==_ETX)
: : {
: : rx_buf[rx_pt++] = '\0';
: : rx_pt = 0;
: : break;
: : }
: : 이렇게 stx가 들어오면 0에 넣고 1부터 데이터를 받게 했는데
: : 한번 어긋나고 나서 정상적인 데이터가 들어오기까지 상당히 시간이 걸리네요
: : 초보인데 혼자 하느라 넘 어렵네요ㅜㅜ
: :
: : 답변 감사드립니다!
: :
: :
: : Intotheblue 님이 쓰신 글 :
: : : 그런식으로 처리하며 안된다고요.
: : :
: : : stx 1 2 3 4 etx
: : : 이런게 항상 들어오는게 아니라는 말입니다.
: : :
: : : stx 1 2
: : : 3 4 etx
: : :
: : : 이런식으로 두번으로 나눠서 수신될경우
: : : 두번째 수신 내용에는 님 글처럼 버퍼 0 에 stx 가 없으니 다음으로 넘어가질 않죠
: : :
: : : 님이 쓰신 글 :
: : : : 답변 감사드립니다.
: : : :
: : : : 음 제가 잘 이해가 안되는데요 ㅜㅜ
: : : :
: : : : 버퍼0에 stx가 들어오는걸 확인하고 다음으로 넘어가는데
: : : :
: : : : 정작 stx가 들어오질 안아서 다음으로 넘어가질 않고 있어요.. 그래서 계속 쳌섬에서 걸리기도 하고
: : : :
: : : :
: : : :
: : : : Intotheblue 님이 쓰신 글 :
: : : : :
: : : : : 통신에서는
: : : : : 모든 데이터가 함께 들어온다고 생각해서는 안됩니다.
: : : : :
: : : : : 따라서 수신 버터의 내용을 또다른 버퍼에 넣고 ..
: : : : : 원하는 부분만 짤라서 써야 하고..
: : : : : (stx ~ etx 까지 내용만 추출)
: : : : :
: : : : : 간혹 일부 데이터가 안오거나 ..
: : : : : 노이즈 등의 영향으로 변조된 데이터가 들어 오는 경우도 있기 때문에..
: : : : :
: : : : : 이런 경우에 대한 처리도 들어가야 합니다.
: : : : :
: : : : : 이지형 님이 쓰신 글 :
: : : : : : 안녕하세요 이제 막 C빌더 배우고 있는 신생아 입니다.
: : : : : :
: : : : : : C빌더6을 사용하고 Cport264 입니다.
: : : : : :
: : : : : : 제가 마이컴에서 rs232로 데이터를 받아서 스트링 그리드로 데이터 표시하는 프로그램을 만들고 있는데
: : : : : :
: : : : : : 통신쪽에 문제가 생겨서 질문드려요
: : : : : :
: : : : : : 마이컴에서 200ms 마다 송신을 하는데 버퍼 맨앞에 stx 보내고'1' 'D' 'A' 'T' 문자열 보내고 그다음 데이터를 보내서
: : : : : :
: : : : : : 앞에 stx와1 D A T를 확인하고 그다음 버퍼부터 데이터를 스트링 그리드에 표시하게 했는데요
: : : : : :
: : : : : : 문제는 데스크탑 PC에서는 몇시간동안 해도 잘 되는데
: : : : : :
: : : : : : 노트북에서 해보니 짧게는 1분 길어도 2~3분만에 스트링 그리드에 표시가 안되더라구요
: : : : : :
: : : : : : 그래서 데이터 표시가 안될때 rx 버퍼를 확인해보니 수신이 되긴 하는데
: : : : : :
: : : : : : 버퍼 맨앞에 stx가 아니더라구요..맨앞이 'D' 일때도 있고 '1' 일때도 있고..
: : : : : :
: : : : : : 포트를 끊었다가 다시 하면 또 되다가 2~3분 후에 똑같은 현상이 나옵니다
: : : : : :
: : : : : : C빌더에서는 rx char 에서 버퍼에 데이터 받고
: : : : : :
: : : : : : 타이머를 이용하여 프로세싱 하게 했고 타이머 인터발은 1 입니다.
: : : : : :
: : : : : : 데스크탑에서는 잘 되는데 노트북에서 저런현상이 나오는게 원인을 잘 모르겠네요 ㅜㅜ
: : : : : :
: : : : : : 고수님들의 조언 부탁드립니다.
: : : : : :
: : : : : :