C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[74436] Re:Re:Re:Re:Re:Re:통신문제 고수님들 도와주세요 ㅜㅜ
[] 3924 읽음    2017-06-23 10:34
답변 정말 감사드립니다.
이제서야 확인 했어요 ㅜㅜ

아직 초보라 조금 어려운데
참고해서 해결해보도록 할게요


송신영 님이 쓰신 글 :
: 시리얼 통신 수신 처리 부의 여러 가지 방법 중에
: 간단한 방식 하나만 참고 하시라고 올려드립니다.
: 주석 잘 읽어 보시면 조금 도움이 될겁니다.
: (온도 컨트롤러와 통신할 때 사용한 소스입니다.)
:
: 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 입니다.
: : : : : :
: : : : : : 데스크탑에서는 잘 되는데 노트북에서 저런현상이 나오는게 원인을 잘 모르겠네요 ㅜㅜ
: : : : : :
: : : : : : 고수님들의 조언 부탁드립니다.
: : : : : :
: : : : : :

+ -

관련 글 리스트
74413 통신문제 고수님들 도와주세요 ㅜㅜ 이지형 3617 2017/06/14
74417     Re:통신문제 고수님들 도와주세요 ㅜㅜ 라스코니 3701 2017/06/14
74419         Re:Re:통신문제 고수님들 도와주세요 ㅜㅜ 3697 2017/06/14
74414     Re:통신문제 고수님들 도와주세요 ㅜㅜ Intotheblue 3704 2017/06/14
74415         Re:Re:통신문제 고수님들 도와주세요 ㅜㅜ 3500 2017/06/14
74416             Re:Re:Re:통신문제 고수님들 도와주세요 ㅜㅜ Intotheblue 3557 2017/06/14
74418                 Re:Re:Re:Re:통신문제 고수님들 도와주세요 ㅜㅜ 3672 2017/06/14
74421                     Re:Re:Re:Re:Re:통신문제 고수님들 도와주세요 ㅜㅜ 라스코니 3674 2017/06/14
74420                     Re:Re:Re:Re:Re:통신문제 고수님들 도와주세요 ㅜㅜ 송신영 4333 2017/06/14
74436                         Re:Re:Re:Re:Re:Re:통신문제 고수님들 도와주세요 ㅜㅜ 3924 2017/06/23
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.