알고리즘 과 괴랄맞은문제 ㅠ
안녕하십니까. 고수님들
도움을 얻고자 질문 올립니다.
큰 그림은 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)를 생각한다면 파일로 저장을 해놓고 읽어도 문제가 안되지 않습니까?
댓글 달기