알고리즘 과 괴랄맞은문제 ㅠ

wkdjjywkd의 이미지

안녕하십니까. 고수님들

도움을 얻고자 질문 올립니다.

큰 그림은 MFC로 실시간 로거를 만드는 것입니다.

통신은 일단은 rs232c 후에는 블루투스 입니다.

제가 MFC를 다뤄보질 않아서 일단 UI만 그려놓고 실시간으로 데이터가 들어오면 로깅을 할수 있게 만들고 테스트 완료 해 놓았습니다.

C로 데이터 처리하는 함수들을 작성해 놓았는데 다시 컨버팅 해야 될것 같습니다.

아직 경험이 없어 같이 쓰는방법을 모르겠습니다.ㅠㅜ 알려주심 감사하겠습니다.

현재 노트북 <-> rs232 <-> rs232 <-> 데스크탑 이런 구성이고

모듈은 ftdi사의 ft232h mini module 사용 중입니다.

기본적인 read write 블락단위로 읽고 쓰고 파일보내고 저장 잘 됩니다.

질문 입니다.
1.한가지 치명적인 문제가 있습니다.

이게 다음날 아침 노트북을 키면 데이터를 제대로 수신하지 못 합니다.

노트북 재시작해도 안되고.. 어느정도 시간이 지난후 노트북 대기모드(절전모드)가 되고 잠금해제를 하면 또 잘 됩니다;;;

모듈 점프선문제도 아닙니다. 접지두 문제 없구요. 데이터가 깨지것은 아닙니다.
덤프를 떠보면 이런식입니다.
정상:

RIFF.;..WAVEfmt............D ..........data 생략

비정상:

R%.P' .W.YUJV 생략 ................D.d.Q 생략

뭐가 문제인걸까요..

DWORD WINAPI ReadThread(LPVOID DevStatus)
{
	DWORD RxBytes;
	DWORD BytesReceived; 
	char RxBuffer[BUFSIZE]; //example value = 256
 
	FTPARMS* ftParms = (FTPARMS*) DevStatus;
 
	printf ("ReadThread Start!!");
	while(1){
 
		FT_GetQueueStatus(ftParms->ftHandle, &RxBytes);
 
		if(RxBytes > 0){
			flag = FALSE; 
			FT_Read(ftParms->ftHandle,RxBuffer,RxBytes,&BytesReceived );			
			CQ_Enqueue(ftParms->Queue, RxBuffer, BytesReceived);
			//ShowHex(RxBuffer, BytesReceived);			
 
 
		}
		/*else if (RxBytes < 0){
			flag = TRUE;
		}*/
	}
	if(fclose(ftParms->des) !=0){
		fprintf(stderr, "file close error!!");
		FT_Close(ftParms->ftHandle);
	}
 
	return 0;
}

통신하기 위해서 초기화는 일단 메인에서 다했습니다.

이거 왜 이런걸까요... 송신측 문제는 디버깅해봐도 아니거든요 ㅠㅠ

2.알고리즘 문제 입니다.
(현재 buadrate bps 1236000 입니다 모듈의 최고속도 입니다.)
문제가 많습니다... 시리얼통신도 처음이고..ㅠ

저는 송신측에서 시작과 끝을 알리고 싶지 않습니다. (임의로)

그런데 모듈 fd를 감시할수있는 요소를 위와 같고 if 로 read 할시에 ..

수신측에서 데이터를 다 쓰지도 못했는데 송신측이 끝나버리면 문제가 발생하겠죠?(일단 이게 젤 큰 문제 입니다.)

제 생각에는 운이좋아서 잘 저장하는 것 같습니다.

(1)이를 해결하려면 송신측에서 시작과 끝을 알릴수 밖에 없나요?

다음 문제 입니다.

큐 헤더

#define MAX_SIZE 4096
 
typedef char ElementType;
 
typedef struct tagNode
{
	ElementType buff[MAX_SIZE];
	DWORD recvLen;
}Node;
 
typedef struct tagCircularQueue
{
	int Capacity;
	int Front;
	int Rear;
 
	Node* Nodes;
}CircularQueue;

메인

#define BUFSIZE 4096
#define TEMPBUF 44
#define FALSE	0
#define TRUE	1 
 
int flag;
 
typedef struct{
	FT_STATUS ftStatus;
	FT_HANDLE ftHandle;
	CircularQueue* Queue;
	DWORD RecvLen;
	FILE *des;
}FTPARMS;           
	//FT_DEVICE_LIST_INFO_NODE *devInfo;
DWORD WINAPI ReadThread(LPVOID DevStatus);	
void ShowHex(char *RxBuffer, DWORD BytesReceived);	
 
int _tmain(int argc, _TCHAR* argv[])
{	
	FTPARMS ftParms;
	HANDLE hThread;
 
	flag = TRUE;
 
	ftParms.ftStatus = FT_Open(0, &ftParms.ftHandle);
 
	if( ftParms.ftStatus != FT_OK){
		printf("!!FT_OPEN Error!!\n");
		FT_Close(ftParms.ftHandle);
		return 1;
	}
 
	if((ftParms.des = fopen("newFile.wav", "wb"))==NULL)
	{
		fprintf(stderr, "Target file open error");
		fclose(ftParms.des);
		FT_Close(ftParms.ftHandle);
		return 2;
	}
	if(ftParms.ftStatus = FT_SetBaudRate(ftParms.ftHandle, 1236000) == FT_OK)
	{// Maximmum bps 1236000
		printf("FT_SetBaudRate succeed!!\n");
	}
	else{
		printf("FT_SetBaudRate failed!!\n");
		FT_Close(ftParms.ftHandle);
		return 3;
	}
	if(ftParms.ftStatus = FT_ResetDevice(ftParms.des) != FT_OK){
	}
	//memset(RxBuffer, 0, sizeof(RxBuffer));
 
	//포트 비우기
	FT_Purge(ftParms.ftHandle,FT_PURGE_RX);
 
	//큐 생성
	CQ_CreateQueue(&ftParms.Queue,30);
 
	hThread = CreateThread(NULL,0,ReadThread,(LPVOID)&ftParms,0,NULL);
 
	int index=0;
 
	while(1){
		//printf("test \n");
 
		if(CQ_IsEmpty(ftParms.Queue) == 0 /*&& flag == FALSE*/){ //fix!!
 
			index = CQ_Dequeue(ftParms.Queue);
			fwrite(ftParms.Queue->Nodes<ol>
</ol>
.buff, 1 ,
				ftParms.Queue->Nodes<ol>
</ol>
.recvLen, ftParms.des);
			printf("Front:%d   Rear:%d    \n",
				(ftParms.Queue)->Front,(ftParms.Queue)->Rear);
		}
		/*else if(CQ_IsEmpty(ftParms.Queue) != 0 && flag == TRUE){
			printf("Queue is emptpy!!\n");
			printf("file copy compelete\n");
 
			fclose(ftParms.des);
			FT_Close(ftParms.ftHandle);
			return 4;
		}*/
	}
 
 
	WaitForSingleObject(hThread, INFINITE);
	CQ_DestoryQueue(ftParms.Queue);
	fclose(ftParms.des);
	FT_Close(ftParms.ftHandle);
 
	return 0;
 
}

함수

void			CQ_CreateQueue(CircularQueue** Queue, int Capacity)
{
	/*큐를 자유저장소에 생성 */
	(*Queue) = (CircularQueue*)malloc(sizeof(CircularQueue));
 
	//입력된 Capacity +1 만큼 노드를 자유 저장소에 생성
 
	(*Queue)->Nodes = (Node*)malloc(sizeof(Node) * ( Capacity+1));
 
 
	(*Queue)->Capacity	= Capacity;
	(*Queue)->Front		= 0;
	(*Queue)->Rear		= 0;
 
 
}
 
void			CQ_Enqueue(CircularQueue* Queue, ElementType* RecvBuf, DWORD RecvLen){
	int Position = 0;
 
	if(Queue->Rear == Queue->Capacity +1){
		Queue->Rear = 0;
		Position = 0;
	}
	else{
		Position = Queue->Rear++;
	}
	// read buf의 데이터를 큐의 buf에 복사
	Queue->Nodes[Position].recvLen = RecvLen;
	memcpy(Queue->Nodes[Position].buff, RecvBuf,RecvLen);
}
 
ElementType		CQ_Dequeue(CircularQueue* Queue){
	int Position = Queue->Front;
 
	if(Queue->Front == Queue->Capacity){
		Queue->Front = 0;
	}
	else
		Queue->Front++;
	return Position;
 
}
 
int				CQ_IsFull(CircularQueue* Queue){
	if(Queue->Front < Queue->Rear){
		return (Queue->Rear - Queue->Front) == Queue->Capacity;
	}
	else
		return (Queue->Rear + 1 ) == Queue->Front;
}
 
int				CQ_IsEmpty(CircularQueue* Queue){
	return (Queue->Front == Queue->Rear);
}
 
int				CQ_GetSize(CircularQueue* Queue){
	if(Queue->Front <= Queue->Rear){
		return Queue->Rear - Queue->Front;
	}
	else 
		return Queue->Rear + (Queue->Capacity - Queue->Front) + 1;
}
 
 
void			CQ_DestoryQueue(CircularQueue* Queue){
	free(Queue->Nodes);
	free(Queue);
}

함수는 기본 환형큐 테스트는 했고 알맞게 고치는 중입니다.

그런데 환형큐를 쓴이유는 메모리자원을 절약하려고 했습니다. 설계당시에..

하지만 read에서 보시는 것과 같이

read와 enqueue가 같이되고.. 메인에서 dequeue를 하였는데 디버깅을 해보니 dequeue가 enqueue를 못따라갑니다. 흠.. 그러니까 메인에서 차례로 읽고 있는데 저장은 원을 한바꾸 더 돌아 저장을하니 문제가 됩니다.

그리고 큐 empty 함수로 while 돌 경우 버그가 있는 것 같습니다.. 아직 테스트해보지는 못했습니다.

걍 C++의 벡터를 써버릴까도 생각했지만.. 충분히 더 고민하면 해결할수 있을것 같습니다..

진짜 극단 적으로..; 파일로 일단 저장하고 그걸 읽어서 화면에 뿌리는게 더 쉽습니다..;

하지만 실시간 logger 만드는데.. 방향이 어긋난다고 생각합니다.

질문(2) 각각속도가 문제가 되기 때문에 데이터 처리를 따로 관리하기위해 큐를 사용 했습니다. 하지만 위와같은 문제가 있습니다.
이 부분을 어떻게 처리해야 될지 궁금합니다.

질문(3) 유닉스에서 네임드파이프같이 파일형태의 전송로에(FIFO)를 생각한다면 파일로 저장을 해놓고 읽어도 문제가 안되지 않습니까?

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.