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
[38913] Re:232로 장비를 제어하려 하는데요..
열씸! [cappuccino] 2091 읽음    2005-01-25 20:04
RS232c 관련 컴포넌트가 몇 가지 있는 걸로 압니다.
저의 경우는 귀찮아서 직접 코딩해서 사용했었구요.

기본적으로 모든 장치나 자원들은 다음과 같은 절차를 따릅니다.
1. 열기
2. 읽고쓰기(사용하기)
3. 닫기

우리가 흔히 접할수 있는 거의 모든 장치들은 위의 절차를 따르죠?
때때로, 바로 읽고 쓸수 있는 자원들은 OS가 이미 열어 두었고, 알아서 닫히기 때문이니
예외를 찾기 힘들 것입니다.

마찬가지로 232도 위와 같은 절차를 따르죠.
고로 계측장비로 부터 자료를 받아 오는데에는 Open() 함수와 Read() 함수만
(덤으로는 Close 정도) 구현해 주면 되는 것이죠.

다음은 com port 제어를 위해 작성한 commh.h 헤더화일의 내용입니다.

//---------------------------------------------------------------------------
#ifndef commH
#define commH
//---------------------------------------------------------------------------
#define USECOMM
#define STRICT
//---------------------------------------------------------------------------
#include <windows.h>
#include <commdlg.h>
#include <string.h>
#include <stdlib.h>
#include <mem.h>
#include <stdio.h>
//---------------------------------------------------------------------------
#define BUFFSIZE  1024
//---------------------------------------------------------------------------
extern COMMCONFIG cc;
extern COMMPROP cp;
extern COMMTIMEOUTS cto;
extern DWORD id;
extern HANDLE hComm, hThread;
extern bool bReading;
extern int comm_number;

extern void OpenPort(char *portname);
extern void ClosePort(void);
//---------------------------------------------------------------------------
DWORD ReadThread(LPDWORD lpdwParam1);
void locProcessCommError(DWORD dwError);
//---------------------------------------------------------------------------
#endif

보시다 시피 Open Close Read 가 존재하죠?

#include <vcl.h>
#include "Unit1.h"
#include "commh.h"
//---------------------------------------------------------------------------
COMMCONFIG cc;
COMMPROP cp;
COMMTIMEOUTS cto;
DWORD id;
HANDLE hComm, hThread;
char CommName[5];
bool bReading;
int count;
//---------------------------------------------------------------------------
void OpenPort(char *portname){
    strcpy(CommName, portname);
    hComm = CreateFile(CommName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (hComm == INVALID_HANDLE_VALUE){
        ShowMessage("Error opening COM port");
        return;
    }
    if (!SetCommState(hComm, &(cc.dcb))){
        CloseHandle(hComm);
        ShowMessage("Port configuration error");
        return;
    }
    cp.wPacketLength = sizeof(COMMPROP);
    GetCommProperties(hComm, &cp);
    bReading = TRUE;
    hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReadThread, NULL, 0, &id);
    if (hThread == INVALID_HANDLE_VALUE){
        ShowMessage("Error creating READ thread");
        CloseHandle(hComm);
        return;
    }
}
//---------------------------------------------------------------------------
void ClosePort(void){
    bReading = FALSE;
    ResumeThread(hThread);
    SetCommMask(hComm, 0L);
    while(GetExitCodeThread(hThread, &id)){
        if (id == STILL_ACTIVE) continue;
        else break;
    }
    CloseHandle(hThread);
    CloseHandle(hComm);
}
//---------------------------------------------------------------------------
DWORD ReadThread(LPDWORD lpdwParam1){
    BYTE inbuff[BUFFSIZE];
    DWORD nBytesRead;

    if (!(cp.dwProvCapabilities & PCF_INTTIMEOUTS)) return 1L;
    memset(&cto, 0, sizeof(cto));
    cto.ReadIntervalTimeout = MAXDWORD;
    SetCommTimeouts(hComm, &cto);

    while(bReading){
        if (!ReadFile(hComm, inbuff, 100, &nBytesRead, NULL)){
            locProcessCommError(GetLastError());
        }
        else{
            if (nBytesRead) Form1->ProcessBytes(inbuff, nBytesRead);
        }
    }
    PurgeComm(hComm, PURGE_RXCLEAR);
    return 0L;
}
//---------------------------------------------------------------------------
void locProcessCommError(DWORD dwError){
    LONG lrc;
    COMSTAT cs;
    ClearCommError(hComm, (LPDWORD)&lrc, &cs);
}
//---------------------------------------------------------------------------

인터넷에 돌아다니던 소스를 짜집기 한거라 그렇게 깔끔하진 않지만,
적당히 쓰실만 하실겁니다.

단 여기서, 원하는 컴포트를 사용하게끔 환경설정 하는 부분이 필요하죠.

    COMMCONFIG tcc;
    tcc = cc;
    tcc.dwSize = sizeof(COMMCONFIG);
    tcc.wVersion = 0x100; //WINDOW95_COMMCONFIG_VERSION
    if (!CommConfigDialog(ComboBox1->Text.c_str(), Handle, &tcc)) return;
    cc = tcc;

이 코드를 환경 설정 버튼의 Click 이벤트 핸들러에 등록하시면 환경설정이 되구요.

OpenPort(ComboBox1->Text.c_str()); 이런식으로 오픈 함수를 사용하시고 (콤보박스에 COM1 COM2 이런걸 넣어두셔야 하죠)

ClosePort(); 사용후는 닫아주시고...

void __fastcall TForm1::ProcessBytes(BYTE *inbuff, DWORD nBytesRead){
    char Temp[100];
    for(int i = 0; i < nBytesRead; i++){
        Temp[i] = (char)inbuff[i];
    }
    Temp[nBytesRead] = 0;        // 널문자로 끝나는 스트링으로 완성했습니다.
    Memo1->Lines->Add(Temp); // 이부분에서 다른 처리를 하시면 되겠죠.
    Edit1->Text = Temp;               // 가령 엑셀에서 부르기 쉽게 콤마나 텝으로 구분한 데이타로 만든다든지요.
}

아까 지나간 읽기 쓰레드에서
if (nBytesRead) Form1->ProcessBytes(inbuff, nBytesRead); 라고 한 부분이 위의 함수를
실행되게끔 해 주죠.

오래 전에 필요에 의해 대강 편집한 코드라 쓰기 편하지 않네요 ^^ 양해하시고...
어쨌든 콤마나 텝으로 정보를 구분해 저장하시면 엑셀에 부르실수 있으실테고
이미 열려 있는 엑셀에다 실행시간에 던지기 위해선 이곳에 올려진 여러 팁들을 참고 하시면 되겠네요.

+ -

관련 글 리스트
38905 232로 장비를 제어하려 하는데요.. 빌더 초짜 965 2005/01/25
38941     Re:232로 장비를 제어하려 하는데요.. 천승환 1214 2005/01/27
38938     Re:232로 장비를 제어하려 하는데요.. 이채호 1082 2005/01/27
38913     Re:232로 장비를 제어하려 하는데요.. 열씸! 2091 2005/01/25
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.