#pragma once
class CComPortDriver
{
public:
CComPortDriver();
~CComPortDriver();
public:
BOOL Open(const int port_no, DWORD &err);
BOOL Close(DWORD &err);
BOOL SetDtr();
BOOL ClearDtr();
BOOL SetRts();
BOOL ClearRts();
BOOL GetStatus(DWORD &status);
BOOL IsOpen();
int GetPortNumber();
protected:
int m_PortNumber;
BOOL m_IsOpen;
HANDLE m_hCom;
};
#include "stdafx.h"
#include "ComPortDriver.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CComPortDriver::CComPortDriver()
{
m_PortNumber = 0;
m_IsOpen = FALSE;
m_hCom = NULL;
}
CComPortDriver::~CComPortDriver()
{
DWORD err;
if (m_IsOpen)
{
Close(err);
}
}
BOOL CComPortDriver::Open(const int port_no, DWORD &dwError)
{
DCB dcb;
dwError = ERROR_SUCCESS;
BOOL fSuccess;
CString port = "", str;
HANDLE hCom;
if ((port_no < 1) || (port_no > 100))
{
return FALSE;
}
if (m_IsOpen)
{
return FALSE;
}
ASSERT (m_hCom == NULL);
port.Format("\\\\.\\COM%d", port_no);
hCom = CreateFile(port,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (hCom == INVALID_HANDLE_VALUE)
{
dwError = GetLastError();
return FALSE;
}
fSuccess = GetCommState(hCom, &dcb);
if (!fSuccess)
{
dwError = GetLastError();
return FALSE;
}
dcb.fOutxCtsFlow = TRUE;
dcb.fOutxDsrFlow = TRUE;
dcb.fDsrSensitivity = TRUE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.BaudRate = 9600;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
fSuccess = SetCommState(hCom, &dcb);
if (!fSuccess)
{
dwError = GetLastError();
return FALSE;
}
if (!PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT ))
{
dwError = GetLastError();
return FALSE;
}
BOOL result;
COMMTIMEOUTS ctmo;
ctmo.ReadIntervalTimeout=1000;
ctmo.ReadTotalTimeoutMultiplier=0;
ctmo.ReadTotalTimeoutConstant= 10000;
ctmo.WriteTotalTimeoutMultiplier=0;
ctmo.WriteTotalTimeoutConstant = 10000;
result = SetCommTimeouts(hCom, &ctmo);
if (!result)
{
dwError = GetLastError();
return FALSE;
}
m_IsOpen = TRUE;
m_hCom = hCom;
m_PortNumber = port_no;
return TRUE;
}
BOOL CComPortDriver::Close(DWORD &dwError)
{
dwError = ERROR_SUCCESS;
if (m_IsOpen && m_hCom)
{
if (!CloseHandle(m_hCom))
{
dwError = GetLastError();
return FALSE;
}
m_IsOpen = FALSE;
m_hCom = NULL;
return TRUE;
}
return FALSE;
}
BOOL CComPortDriver::SetDtr()
{
if (m_IsOpen)
{
ASSERT (m_hCom);
DWORD status = SETDTR;
return EscapeCommFunction(m_hCom, status);
}
return FALSE;
}
BOOL CComPortDriver::ClearDtr()
{
if (m_IsOpen)
{
ASSERT (m_hCom);
DWORD status = CLRDTR;
return EscapeCommFunction(m_hCom, status);
}
return FALSE;
}
BOOL CComPortDriver::SetRts()
{
if (m_IsOpen)
{
ASSERT (m_hCom);
DWORD status = SETRTS;
return EscapeCommFunction(m_hCom, status);
}
return FALSE;
}
BOOL CComPortDriver::ClearRts()
{
if (m_IsOpen)
{
ASSERT (m_hCom);
DWORD status = CLRRTS;
return EscapeCommFunction(m_hCom, status);
}
return FALSE;
}
BOOL CComPortDriver::GetStatus(DWORD &status)
{
if (m_IsOpen)
{
ASSERT (m_hCom);
return GetCommModemStatus(m_hCom, &status);
}
return FALSE;
}
BOOL CComPortDriver::IsOpen()
{
return m_IsOpen;
}
int CComPortDriver::GetPortNumber()
{
return m_PortNumber;
}
We did something very similar in one of projects.
The output can be easily driven using DTR or RTS pins which are basically modem control outputs.
Clearly, port is not used for communications but as a simple output(s). But if you need something really simple, like an LED output, bare bones PCs don't have much else to hook it to.
A slightly non-trivial thing is that you need to use a function called EscapeCommFunction after you open the port.
The other non-trivial thing is that you need to set DTR_CONTROL_ENABLE and/or RTS_CONTROL_ENABLE bits in your DCB structure.
If you want the code (works great), let me know.
Works through USB adapters as well.
You can even use it as an input as well (and read CTS and DSR pins).
One word of caution is check what type of output you will be driving (LED should be fine) as serial port will NOT be able to source a lot of current. With a simple additional circuit it can also be used as a voltage free relay.