|
지니오기 님이 쓰신 글 :
: 제브라 프린터기로 바코드를 출력하려고하는데
:
: com1 시리얼 포트나 LPT 포트를 사용하여 연결이 되어야 하는데
:
: 연결하여 포트를 열고 닫는 방법을 잘 모르겠네요.
:
: 빌더 처음하는거라 아무것도 모르니 잘좀 알려주세요.
자료실의 rs-232test라는 프로그램을 보시면 통신포트를 열고 문자를 보내고 받는 부분이
나와있습니다
//---------------------------------------------------------------------------
#include <vcl.h>
#include <stdio.h>
#pragma hdrstop
#include "frmMain.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormMain *FormMain;
int count1;
//---------------------------------------------------------------------------
// 통신 설정 옵션인 TCommParam 을 설정한다
void __fastcall TFormMain::SetCommParam(void)
{
CommParam.PortNo = cbCOM->ItemIndex + 1;
CommParam.BaudRate = rdSpeed->Items->Strings[rdSpeed->ItemIndex].ToInt();
CommParam.ByteSize = 8;
switch(rdStopbit->ItemIndex)
{
case 0:
CommParam.StopBits = STOPBIT_1;
break;
case 1:
CommParam.StopBits = STOPBIT_15;
break;
case 2:
CommParam.StopBits = STOPBIT_2;
break;
}
switch(rdParity->ItemIndex)
{
case 0:
CommParam.Parity = PARITY_NONE;
break;
case 1:
CommParam.Parity = PARITY_EVEN;
break;
case 2:
CommParam.Parity = PARITY_ODD;
break;
}
}
//---------------------------------------------------------------------------
// 수신된 Data의 값들을 16진수로 보여준다
void __fastcall TFormMain::ShowRcvData(int iLen, BYTE *bData)
{
BYTE TempBuff[5000];
AnsiString RcvData;
// RcvData = "RcvData Lenth = " + IntToStr(iLen) + "\n";
for(int i=0; i<iLen; i++)
// for(int i=0; i<1; i++)
{
sprintf(TempBuff, "%02X", bData[i]);
RcvData = RcvData + " [" + (char *)TempBuff + "]";
// Edit1->Text=count1; // (char *)TempBuff ;
}
ShowMessage(RcvData);
}
//---------------------------------------------------------------------------
// 쓰레드에 의해 Data가 수신되면 SendMessage에 의해 호출된다. 즉 수신버퍼에
// TMessage의 WParam의 길이만큼 Data가 수신된 후 호출된다
void __fastcall TFormMain::UMEvnRxChar(TMessage &Message)
{
int iLen;
BYTE RcvBuff[1280];
if(RadioGroupRecvType->ItemIndex == 1) return;
iLen = RS232C->ReadData(Message.WParam, RcvBuff);
count1++;
if (iLen>30) return;
ShowRcvData(iLen, RcvBuff);
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::ClearEdit(void)
{
EditCode->Text = "";
EditLength->Text = "";
EditData->Text = "";
}
//---------------------------------------------------------------------------
// 송신할 데이타를 TDataType 구조체에 넣어준다
void __fastcall TFormMain::MakeSendData(void)
{
if(TxBuff.Data)
{
delete []TxBuff.Data;
}
ZeroMemory(&TxBuff, sizeof(TDataType));
TxBuff.Code = (BYTE)EditCode->Text.ToInt();
TxBuff.Len = (short int)EditLength->Text.ToInt();
TxBuff.Data = (BYTE *)new BYTE[TxBuff.Len+2];
strcpy(TxBuff.Data, EditData->Text.c_str());
}
//---------------------------------------------------------------------------
__fastcall TFormMain::TFormMain(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::FormCreate(TObject *Sender)
{
TxBuff.Data = NULL;
// ClearEdit();
cbCOM->ItemIndex = 0;
EditLength->Text = EditData->Text.Length();
RS232C = new TRS232C();
RS232C->SetHWND(Handle);
btnSetup->Click();
count1=0;
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::FormDestroy(TObject *Sender)
{
if(TxBuff.Data)
{
delete []TxBuff.Data;
}
delete RS232C;
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::btnSetupClick(TObject *Sender)
{
DWORD dwDtr, dwRts;
switch(RadioGroupDtr->ItemIndex)
{
case 0:
dwDtr = DTR_DISABLE;
break;
case 1:
dwDtr = DTR_ENABLE;
break;
case 2:
dwDtr = DTR_HANDSHAKE;
break;
}
switch(RadioGroupDtr->ItemIndex)
{
case 0:
dwRts = RTS_DISABLE;
break;
case 1:
dwRts = RTS_ENABLE;
break;
case 2:
dwRts = RTS_HANDSHAKE;
break;
case 3:
dwRts = RTS_TOGGLE;
break;
}
SetCommParam();
RS232C->SetDtrControl(dwDtr);
RS232C->SetRtsControl(dwRts);
if(!RS232C->Open(&CommParam)) ShowMessage("Open Failed!");
RS232C->ClearTxBuffer();
RS232C->ClearRxBuffer();
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::btnSendClick(TObject *Sender)
{
if(!RS232C->IsOpened())
{
ShowMessage("Open Failed!");
return;
}
RS232C->ClearTxBuffer();
MakeSendData();
if(!RS232C->WriteData(3, (BYTE *)&TxBuff))
{
ShowMessage("Header Send Error");
}
if(!RS232C->WriteData(TxBuff.Len, TxBuff.Data))
{
ShowMessage("Body Send Error");
}
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::btnExitClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::EditDataExit(TObject *Sender)
{
EditLength->Text = EditData->Text.Length();
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::FormActivate(TObject *Sender)
{
EditCode->SetFocus();
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::btnRcvClick(TObject *Sender)
{
int iLen;
BYTE bRcvBuff[128];
iLen = RS232C->ReadData(10, bRcvBuff);
if(!iLen) ShowMessage("TimeOut");
else ShowRcvData(iLen, bRcvBuff);
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::RadioGroupRecvTypeClick(TObject *Sender)
{
btnRcv->Enabled = (RadioGroupRecvType->ItemIndex == 1);
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::Button1Click(TObject *Sender)
{
Edit1->Text=count1;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include <vcl.h>
#include <stdio.h>
#pragma hdrstop
#include "uRs232c.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// 데이타가 수신되었는지 여부를 확인하는 Thread 처리 함수
// Event발생시 사용자가 정의한 MessageMap에 선언된 함수를 호출한다
void __fastcall TRS232CRxThread::Execute()
{
DWORD dwEventMask;
DWORD dwErrorFlags;
COMSTAT CommStatus;
while(!Terminated)
{
dwEventMask = 0;
//--- 통신 버퍼의 이벤트를 기다린다
WaitCommEvent(myRs232c->hmyPort, &dwEventMask, &myRs232c->evnRead);
if(!dwEventMask) continue;
EnterCriticalSection(&myRs232c->myCriticalSection);
if(myRs232c->hmyWnd)
{
if(dwEventMask & EV_RXCHAR)
{
//------------ 수신버퍼에 데이터 문자가 수신 되었을 경우
ClearCommError(myRs232c->hmyPort, &dwErrorFlags, &CommStatus);
SendMessage(myRs232c->hmyWnd, UM_EVN_RXCHAR, CommStatus.cbInQue, 0);
}
if(dwEventMask & EV_RXFLAG) SendMessage(myRs232c->hmyWnd, UM_EVN_RXFLAG, 0, 0);
if(dwEventMask & EV_TXEMPTY) SendMessage(myRs232c->hmyWnd, UM_EVN_TXEMPTY, 0, 0);
if(dwEventMask & EV_CTS) SendMessage(myRs232c->hmyWnd, UM_EVN_CTS, 0, 0);
if(dwEventMask & EV_DSR) SendMessage(myRs232c->hmyWnd, UM_EVN_DSR, 0, 0);
if(dwEventMask & EV_RLSD) SendMessage(myRs232c->hmyWnd, UM_EVN_RLSD, 0, 0);
if(dwEventMask & EV_BREAK) SendMessage(myRs232c->hmyWnd, UM_EVN_BREAK, 0, 0);
if(dwEventMask & EV_ERR) SendMessage(myRs232c->hmyWnd, UM_EVN_ERR, 0, 0);
if(dwEventMask & EV_RING) SendMessage(myRs232c->hmyWnd, UM_EVN_RING, 0, 0);
if(dwEventMask & EV_RX80FULL) SendMessage(myRs232c->hmyWnd, UM_EVN_RX80FULL, 0, 0);
}
LeaveCriticalSection(&myRs232c->myCriticalSection);
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 생성자
__fastcall TRS232C::TRS232C()
{
myRxThread = NULL;
hmyWnd = NULL;
hmyPort = NULL;
dwmyTimeOut = (DWORD)COMM_TIMEOUT;
dwmyEventMask = EV_RXCHAR;
imyTxBuffSize = TX_BUFF_LEN;
imyRxBuffSize = RX_BUFF_LEN;
evnRead.hEvent = NULL;
evnWrite.hEvent = NULL;
SetDefaultDCB();
InitializeCriticalSection(&myCriticalSection);
}
//---------------------------------------------------------------------------
__fastcall TRS232C::~TRS232C()
{
if(hmyPort) Close();
DeleteCriticalSection(&myCriticalSection);
}
//---------------------------------------------------------------------------
void __fastcall TRS232C::SetDefaultDCB(void)
{
myDCB.DCBlength = sizeof(DCB); /* sizeof(DCB) */
myDCB.BaudRate = CBR_9600; /* Baudrate at which running */
myDCB.fBinary = true; /* Binary Mode (skip EOF check) */
myDCB.fParity = true; /* Enable parity checking */
myDCB.fOutxCtsFlow = false; /* CTS handshaking on output */
myDCB.fOutxDsrFlow = false; /* DSR handshaking on output */
myDCB.fDtrControl = DTR_DISABLE; /* DTR Flow control */
myDCB.fDsrSensitivity = false; /* DSR Sensitivity */
myDCB.fTXContinueOnXoff = false; /* Continue TX when Xoff sent */
myDCB.fOutX = false; /* Enable output X-ON/X-OFF */
myDCB.fInX = false; /* Enable input X-ON/X-OFF */
myDCB.fErrorChar = false; /* Enable Err Replacement */
myDCB.fNull = false; /* Enable Null stripping */
myDCB.fRtsControl = RTS_DISABLE; /* Rts Flow control */
myDCB.fAbortOnError = false; /* Abort all reads and writes on Error */
// myDCB.fDummy2 = NULL; /* Reserved */
myDCB.wReserved = 0; /* Not currently used */
myDCB.XonLim = 0; /* Transmit X-ON threshold */
myDCB.XoffLim = 0; /* Transmit X-OFF threshold */
myDCB.ByteSize = 8; /* Number of bits/byte, 4-8 */
myDCB.Parity = NOPARITY; /* 0-4=None,Odd,Even,Mark,Space */
myDCB.StopBits = ONESTOPBIT; /* 0,1,2 = 1, 1.5, 2 */
myDCB.XonChar = 0x00; /* Tx and Rx X-ON character */
myDCB.XoffChar = 0x00; /* Tx and Rx X-OFF character */
myDCB.ErrorChar = 0x00; /* Error replacement char */
myDCB.EofChar = 0x00; /* End of Input character */
myDCB.EvtChar = 0x00; /* Received Event character */
// myDCB.wReserved1 = 0; /* Fill for now. */
}
//---------------------------------------------------------------------------
void __fastcall TRS232C::SetDCB(DCB *mDCB)
{
myDCB.DCBlength = mDCB->DCBlength; /* sizeof(DCB) */
myDCB.BaudRate = mDCB->BaudRate; /* Baudrate at which running */
myDCB.fBinary = mDCB->fBinary; /* Binary Mode (skip EOF check) */
myDCB.fParity = mDCB->fParity; /* Enable parity checking */
myDCB.fOutxCtsFlow = mDCB->fOutxCtsFlow; /* CTS handshaking on output */
myDCB.fOutxDsrFlow = mDCB->fOutxDsrFlow; /* DSR handshaking on output */
myDCB.fDtrControl = mDCB->fDtrControl; /* DTR Flow control */
myDCB.fDsrSensitivity = mDCB->fDsrSensitivity; /* DSR Sensitivity */
myDCB.fTXContinueOnXoff = mDCB->fTXContinueOnXoff; /* Continue TX when Xoff sent */
myDCB.fOutX = mDCB->fOutX; /* Enable output X-ON/X-OFF */
myDCB.fInX = mDCB->fInX; /* Enable input X-ON/X-OFF */
myDCB.fErrorChar = mDCB->fErrorChar; /* Enable Err Replacement */
myDCB.fNull = mDCB->fNull; /* Enable Null stripping */
myDCB.fRtsControl = mDCB->fRtsControl; /* Rts Flow control */
myDCB.fAbortOnError = mDCB->fAbortOnError; /* Abort all reads and writes on Error */
// myDCB.fDummy2 = NULL; /* Reserved */
myDCB.wReserved = mDCB->wReserved; /* Not currently used */
myDCB.XonLim = mDCB->XonLim; /* Transmit X-ON threshold */
myDCB.XoffLim = mDCB->XoffLim; /* Transmit X-OFF threshold */
myDCB.ByteSize = mDCB->ByteSize; /* Number of bits/byte, 4-8 */
myDCB.Parity = mDCB->Parity; /* 0-4=None,Odd,Even,Mark,Space */
myDCB.StopBits = mDCB->StopBits; /* 0,1,2 = 1, 1.5, 2 */
myDCB.XonChar = mDCB->XonChar; /* Tx and Rx X-ON character */
myDCB.XoffChar = mDCB->XoffChar; /* Tx and Rx X-OFF character */
myDCB.ErrorChar = mDCB->ErrorChar; /* Error replacement char */
myDCB.EofChar = mDCB->EofChar; /* End of Input character */
myDCB.EvtChar = mDCB->EvtChar; /* Received Event character */
// myDCB.wReserved1 = 0; /* Fill for now. */
}
//---------------------------------------------------------------------------
// 데이타 송수신 Event처리 Overlap을 생성한다
bool __fastcall TRS232C::CreateEventLap(void)
{
evnRead.Offset = 0;
evnRead.OffsetHigh = 0;
evnWrite.Offset = 0;
evnWrite.OffsetHigh = 0;
evnRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if(!evnRead.hEvent) return(false);
evnWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if(!evnWrite.hEvent)
{
CloseHandle(evnRead.hEvent);
evnRead.hEvent = NULL;
return(false);
}
return(true);
}
//---------------------------------------------------------------------------
// 수신 쓰레드에 의해 호출될 윈도우 Handle을 지정한다
void __fastcall TRS232C::SetHWND(HWND hWnd)
{
hmyWnd = hWnd;
}
//---------------------------------------------------------------------------
// 데이터 수신시 Timeout값을 지정한다. 단위는 Millisecond
void __fastcall TRS232C::SetTimeOut(DWORD dwTime)
{
dwmyTimeOut =1; // dwTime;
}
//---------------------------------------------------------------------------
// 통신에 사용될 송수신 버퍼의 크기를 지정한다
void __fastcall TRS232C::SetCommBuffSize(int iTxBuffSize, int iRxBuffSize)
{
imyTxBuffSize = iTxBuffSize;
imyRxBuffSize = iRxBuffSize;
}
//---------------------------------------------------------------------------
// 쓰레드에 의해 호출될 수신 이벤트 Mask값을 지정한다
// 지정값은 winbase.h에 define되어진 Events값을 조합하여(OR 연산 사용) 사용한다
// 기본적으로 EV_RXCHAR값은 생성자에서 지정해 놓았다
void __fastcall TRS232C::SetEventMask(DWORD dwEventMask)
{
dwmyEventMask = dwEventMask;
}
//---------------------------------------------------------------------------
// DTR콘트롤 사용여부 지정(기본적으로 생성자에서 DTR_DISABLE로 설정하였음)
void __fastcall TRS232C::SetDtrControl(DWORD dwDtrControl)
{
myDCB.fDtrControl = dwDtrControl;
}
//---------------------------------------------------------------------------
// RTS콘트롤 사용여부 지정(기본적으로 생성자에서 RTS_DISABLE로 설정하였음)
void __fastcall TRS232C::SetRtsControl(DWORD dwRtsControl)
{
myDCB.fRtsControl = dwRtsControl;
}
//---------------------------------------------------------------------------
// 수신 쓰레드를 생성한다. 자동으로 수행하기 위해 CreateSuspended값을 false로 함)
void __fastcall TRS232C::CreateRxThread(void)
{
myRxThread = new TRS232CRxThread(this, false);
}
//---------------------------------------------------------------------------
// 수신 쓰레드를 소멸시킨다
void __fastcall TRS232C::DestroyRxThread(void)
{
if(myRxThread)
{
delete myRxThread;
myRxThread = NULL;
}
}
//---------------------------------------------------------------------------
// TCommParam에 따른 Port를 Open한다
bool __fastcall TRS232C::Open(TCommParam *CommParam)
{
char DeviceName[10];
if(IsOpened()) Close();
//-- Device Name 생성
sprintf(DeviceName, "COM%d", CommParam->PortNo);
//-- Event Overlap 생성
if(!CreateEventLap()) return(false);
//-- Port Handle 얻기
hmyPort = CreateFile( DeviceName,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
NULL );
if(hmyPort == INVALID_HANDLE_VALUE)
{
hmyPort = 0;
return(false);
}
//-- Event Mask 지정
if(!SetCommMask(hmyPort, dwmyEventMask))
{
Close();
return(false);
}
//-- 통신 버퍼 사이지 지정
if(!SetupComm(hmyPort, (DWORD)imyRxBuffSize,(DWORD)imyTxBuffSize))
{
Close();
return(false);
}
// ------------- vc6
// timeouts.ReadIntervalTimeout = 0xFFFFFFFF;
// timeouts.ReadTotalTimeoutMultiplier = 0;
// timeouts.ReadTotalTimeoutConstant = 0;
// timeouts.WriteTotalTimeoutMultiplier = 2*CBR_9600 / dwBaud;
// timeouts.WriteTotalTimeoutConstant = 0;
// SetCommTimeouts( m_hComm, &timeouts);
//-- 통신 Timeout값 지정
COMMTIMEOUTS TimeOuts;
TimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
TimeOuts.ReadTotalTimeoutMultiplier = 0;
TimeOuts.ReadTotalTimeoutConstant = 0; // dwmyTimeOut;
TimeOuts.WriteTotalTimeoutMultiplier= 2*CBR_9600 / 9600; // dwBaud; // 0;
TimeOuts.WriteTotalTimeoutConstant = 0;
if(!SetCommTimeouts(hmyPort, &TimeOuts))
{
Close();
return(false);
}
//-- 통신 속도등의 DCD값 지정
myDCB.BaudRate = (DWORD)CommParam->BaudRate;
myDCB.ByteSize = CommParam->ByteSize;
myDCB.StopBits = CommParam->StopBits;
myDCB.Parity = CommParam->Parity;
if(!SetCommState(hmyPort, &myDCB))
{
Close();
return(false);
}
//-- 송/수신 버퍼 Purge
PurgeComm(hmyPort, PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
//-- 수신 쓰레드 생성
CreateRxThread();
return(true);
}
//---------------------------------------------------------------------------
// 열려진 통신 Port를 Close 한다(수신 쓰레드 포함)
void __fastcall TRS232C::Close(void)
{
DestroyRxThread();
PurgeComm(hmyPort, PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
if(evnRead.hEvent != NULL) { CloseHandle(evnRead.hEvent); evnRead.hEvent = NULL; }
if(evnWrite.hEvent != NULL) { CloseHandle(evnWrite.hEvent); evnWrite.hEvent = NULL; }
if(hmyPort != NULL) { CloseHandle(hmyPort); hmyPort = NULL; }
}
//---------------------------------------------------------------------------
// 통신 Port가 Open되었는지를 확인한다
bool __fastcall TRS232C::IsOpened(void)
{
return((hmyPort != NULL));
}
//---------------------------------------------------------------------------
// 수신 버퍼에 저장된 값을 iCount만큼 lpRxBuff에 읽어온다
// Return값은 수신 버퍼에서 읽어온 값을 Return
int __fastcall TRS232C::ReadData(int iCount, BYTE *lpRxBuff)
{
DWORD dwResultCount;
if(!IsOpened()) return(0);
if(!ReadFile(hmyPort, lpRxBuff, iCount, &dwResultCount, &evnRead))
{
if(GetLastError() == ERROR_IO_PENDING)
{
while(!GetOverlappedResult(hmyPort, &evnRead, &dwResultCount, FALSE))
{
if(GetLastError() == ERROR_IO_INCOMPLETE) continue;
else
{
break;
}
}
}
}
return((int)dwResultCount);
}
//---------------------------------------------------------------------------
// 통신 버퍼에 iCount만큼 lpTxBuff의 내용을 송신한다
// 올바로 송신하면 true를 Return
bool __fastcall TRS232C::WriteData(int iCount, BYTE *lpTxBuff)
{
DWORD dwWrittenCount;
DWORD dwErrorFlags;
bool isWritten;
if(!hmyPort) return(false);
if (!WriteFile(hmyPort, lpTxBuff, (DWORD)iCount, &dwWrittenCount, &evnWrite))
{
dwErrorFlags = GetLastError();
if(dwErrorFlags == ERROR_IO_PENDING)
{
while(!GetOverlappedResult(hmyPort, &evnWrite, &dwWrittenCount, FALSE))
{
if(GetLastError() == ERROR_IO_INCOMPLETE) continue;
else
{
break;
}
}
}
}
isWritten = (dwWrittenCount == (DWORD)iCount);
return(isWritten);
}
//---------------------------------------------------------------------------
// 통신 Port의 Handle값을 Return한다
HANDLE __fastcall TRS232C::GetCommHandle(void)
{
return(hmyPort);
}
//---------------------------------------------------------------------------
// 수신 버퍼 Clear
void __fastcall TRS232C::ClearRxBuffer(void)
{
if(hmyPort) PurgeComm(hmyPort, PURGE_RXCLEAR);
}
//---------------------------------------------------------------------------
// 통신 버퍼 Clear
void __fastcall TRS232C::ClearTxBuffer(void)
{
if(hmyPort) PurgeComm(hmyPort, PURGE_TXCLEAR);
}
//---------------------------------------------------------------------------
|