📄 krrcom.cpp
字号:
// KrrCom1.cpp: implementation of the CKrrCom class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "KrrCom.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CKrrCom::CKrrCom()
{
m_strComX = ""; //串口号
m_bConnected = FALSE; //连接判断
////////////////////////////////////////////////////////////////////////////////////////
m_dcb.BaudRate = 9600; //波特率
m_dcb.ByteSize = 8; //数据位
m_dcb.Parity = NOPARITY; //不允许奇偶校验
m_dcb.fNull = FALSE; //不丢弃收到的NULL字符,必须为FALSE,否则必错。
m_dcb.fParity = FALSE; //不允许奇偶校验
m_dcb.StopBits = ONESTOPBIT; //1位停止位
m_dcb.fBinary = TRUE; //二进制模式,不检验EOF,必须为TRUE,WINDOWS 32 不支持非二进制模式。
m_hCom = NULL;
//////////////////////////////////////////////////////////////////////////////////////////
m_nInBufferSize = 1024;
m_nOutBufferSize = 1024;
//////////////////////////////////////////////////////////////////////////////////////////
m_TimeOuts.ReadIntervalTimeout = 20; //两个字符之间的时间超时,0为不启用改种超时。适用于读
m_TimeOuts.ReadTotalTimeoutConstant = 100; //读操作总超时常数
m_TimeOuts.ReadTotalTimeoutMultiplier = 20; //读操作总超时系数
m_TimeOuts.WriteTotalTimeoutConstant = 100; //写操作总超时常数
m_TimeOuts.WriteTotalTimeoutMultiplier = 20; //写操作总超时系数
//读总超时=(读操作总超时系数×读取字节数)+读操作总超时常数。
//写操作同上。
m_evtRcv.ResetEvent();
m_bEnableEvent = FALSE;
m_pRcvDetectThread = NULL;
}
CKrrCom::~CKrrCom()
{
ExitDetectedThread();
}
void CKrrCom::SetBufferSize(UINT inBuffer, UINT outBuffer)
{
ASSERT ((inBuffer > 0) && (outBuffer > 0));
m_nInBufferSize = inBuffer;
m_nOutBufferSize = outBuffer;
}
BOOL CKrrCom::SetSetings(UINT nBaud, UINT nParity, UINT nDataBits, FLOAT fStopBits)
{
ASSERT (nBaud > 0);
ASSERT (nParity == 0); //不支持奇偶校验
ASSERT (nDataBits > 0);
ASSERT ((fStopBits ==1) || (fStopBits ==1.5) || (fStopBits ==2));
/////////////////////////////////////////////////////////////////////
m_dcb.BaudRate = nBaud; //波特率
m_dcb.ByteSize = (unsigned char) nDataBits; //数据位
UINT nStopBits = (UINT) fStopBits * 10;
switch ( nStopBits ){
case 10:
m_dcb.StopBits = ONESTOPBIT; //1位停止位
break;
case 15:
m_dcb.StopBits = ONE5STOPBITS; //1.5位停止位
break;
case 20:
m_dcb.StopBits = TWOSTOPBITS; //2位停止位
break;
}
return TRUE;
}
BOOL CKrrCom::SetTimeOuts(UINT nRIT, UINT nRTTC, UINT nRTTM, UINT nWTTC, UINT nWTTM)
{
ASSERT (nRIT >= 0);
ASSERT (nRTTC >= 0);
ASSERT (nRTTM >= 0);
ASSERT (nWTTC >= 0);
ASSERT (nWTTM >= 0);
m_TimeOuts.ReadIntervalTimeout = nRIT; //两个字符之间的时间超时,0为不启用改种超时。适用于读
m_TimeOuts.ReadTotalTimeoutConstant = nRTTC; //读操作总超时常数
m_TimeOuts.ReadTotalTimeoutMultiplier = nRTTM; //读操作总超时系数
m_TimeOuts.WriteTotalTimeoutConstant = nWTTC; //写操作总超时常数
m_TimeOuts.WriteTotalTimeoutMultiplier = nWTTM; //写操作总超时系数
//读总超时=(读操作总超时系数×读取字节数)+读操作总超时常数。
//写操作同上。
return TRUE;
}
BOOL CKrrCom::Open(CString strCom)
{
//只允许4个串口:
ASSERT ((strCom == "COM1:") || (strCom == "COM2:")
|| (strCom == "COM3:") || (strCom == "COM4:"));
if (m_bConnected)
return FALSE;
m_strComX = strCom;
m_hCom = CreateFile(m_strComX, //端口名字(COM1:,COM2...)
GENERIC_READ|GENERIC_WRITE, //读写权限
0, //共享设置(禁止)
NULL, //安全属性(默认)
OPEN_EXISTING, //打开已经存在的端口,而不是创建。
0, //非重叠模式
NULL); //指向模板文件的指针,不需要。
if (m_hCom == INVALID_HANDLE_VALUE){
m_hCom = NULL;
return FALSE;
}
//设置缓存区:
SetupComm (m_hCom, m_nInBufferSize, m_nOutBufferSize);
//设置超时
SetCommTimeouts (m_hCom, &m_TimeOuts);
//设置DCB
DCB dcb; //设备控制块(Device Control Block)
if (!GetCommState (m_hCom, &dcb)){
CloseHandle (m_hCom);
m_hCom = NULL;
return FALSE;
}
dcb.fBinary = m_dcb.fBinary;
dcb.BaudRate = m_dcb.BaudRate;
dcb.ByteSize = m_dcb.ByteSize;
dcb.fParity = m_dcb.fParity;
dcb.fNull = m_dcb.fNull;
dcb.StopBits = m_dcb.StopBits;
dcb.Parity = m_dcb.Parity;
if (!SetCommState (m_hCom, &dcb)){
CloseHandle (m_hCom);
m_hCom = NULL;
return FALSE;
}
//成功:
m_bConnected = TRUE;
return TRUE;
}
BOOL CKrrCom::Close()
{
if (!m_bConnected){
return FALSE;
}
m_bConnected = FALSE;
EnableRcvEvent (FALSE);
TRACE (_T("CloseHandle.\n"));
::CloseHandle(m_hCom);
return TRUE;
}
//获得输入缓存区的字节数
DWORD CKrrCom::GetInputBytes()
{
COMSTAT ComStat;
DWORD dwErrorFlags;
DWORD dwError;
if (!ClearCommError (m_hCom, &dwErrorFlags, &ComStat)){
dwError = GetLastError();
if (dwError){
m_dwError = dwError;
}
return 0;
}
return ComStat.cbInQue;
}
//获得输出缓存区的字节数
DWORD CKrrCom::GetOutputBytes()
{
COMSTAT ComStat;
DWORD dwErrorFlags;
DWORD dwError;
if (!ClearCommError (m_hCom, &dwErrorFlags, &ComStat)){
dwError = GetLastError();
if (dwError){
m_dwError = dwError;
}
return 0;
}
return ComStat.cbOutQue;
}
BOOL CKrrCom::Write(BYTE *buf, DWORD dwLength)
{
BOOL bState;
DWORD Length=dwLength;
DWORD WritedLength;
COMSTAT ComStat;
DWORD dwErrorFlags;
DWORD dwError;
//清除错误记录,以便开始新的通信。
if (!ClearCommError (m_hCom, &dwErrorFlags, &ComStat)){
dwError = GetLastError();
if (dwError){
m_dwError = dwError;
}
return FALSE;
}
bState = WriteFile (m_hCom, buf, Length, &WritedLength, 0);
//获取错误信息
if (!bState){
dwError = GetLastError();
if (dwError){
m_dwError = dwError;
}
return FALSE;
}
//长度判断
if (Length != WritedLength){
TRACE(_T( "Write Com Error:Length(%d)!=WritedLength(%d).\n" ), Length, WritedLength);
return FALSE;
}
return TRUE;
}
BOOL CKrrCom::Read(BYTE *buf, DWORD dwLength)
{
BOOL bState = FALSE;
DWORD Length = 0;
DWORD ReadedLength;
COMSTAT ComStat;
DWORD dwErrorFlags;
DWORD dwError;
//清除错误记录,以便开始新的通信。
if (!ClearCommError (m_hCom, &dwErrorFlags, &ComStat)){
dwError = GetLastError();
if (dwError){
m_dwError = dwError;
}
return FALSE;
}
Length = dwLength;
if (m_hCom == INVALID_HANDLE_VALUE){
TRACE (_T( "Read Com Error:INVALID_HANDLE_VALUE\n" ));
return FALSE;
}
//读串口
bState = ReadFile (m_hCom, buf, Length, &ReadedLength, 0);
if (!bState){
dwError = GetLastError();
if (dwError){
m_dwError = dwError;
}
return FALSE;
}
if (Length != ReadedLength){
TRACE (_T( "Read Com Error:Length(%d)!=ReadedLength(%d).\n" ), Length, ReadedLength);
return FALSE;
}
return TRUE;
}
DWORD CKrrCom::GetLastError()
{
return m_dwError;
}
void CKrrCom::ClearError()
{
m_dwError = 0;
}
BOOL CKrrCom::IsConnected()
{
return m_bConnected;
}
void CKrrCom::ExitDetectedThread()
{
TRACE (_T("ExitDetectedThread.\n"));
DWORD dwExitCode;
if (m_pRcvDetectThread == NULL){
return;
}
if (::GetExitCodeThread (m_pRcvDetectThread->m_hThread, &dwExitCode)
&&dwExitCode == STILL_ACTIVE){
m_pRcvDetectThread->ExitInstance();//No use.
delete m_pRcvDetectThread;
}
}
void CKrrCom::EnableRcvEvent(BOOL bRcvEvt)
{
static BOOL bStarted = FALSE;
if (!IsConnected()){
bStarted = FALSE;
return;
}
//////////////////////////////
if (bRcvEvt && (!bStarted)){
//启动一个接收检测线程。
bStarted = TRUE;
m_bEnableEvent = TRUE;
m_evtRcv.SetEvent();
m_pRcvDetectThread = AfxBeginThread (RcvEvtDetect, this);
}
else if (bRcvEvt){
m_bEnableEvent = TRUE;
m_evtRcv.SetEvent();
}
else if (!bRcvEvt){
//禁止检测字符接收。
m_bEnableEvent = FALSE;
m_evtRcv.ResetEvent();
}
}
void CKrrCom::OnComm()
{
}
UINT CKrrCom::RcvEvtDetect(LPVOID pParam)
{
CKrrCom* pCom = (CKrrCom*) pParam;
ASSERT (pCom);
ASSERT (pCom->IsConnected());
Start:
//等待程序允许
::WaitForSingleObject(pCom->m_evtRcv,INFINITE);
if (pCom->m_bEnableEvent == TRUE){
pCom->m_evtRcv.SetEvent();
}
//等待串口字符接收事件,只等待此时以后的事件,之前的不算。
if (!pCom->IsConnected()){
TRACE (_T("Exit RcvEvtDetect normally.\n"));
return 0;
}
//此代码计划用在嵌入式系统,所以不用重叠方式。
if (pCom->GetInputBytes() == 0){
goto Start;
}
//触发事件。
TRACE (_T("KrrComm.OnComm.\n"));
if (pCom->m_bEnableEvent == TRUE){
pCom->OnComm();
}
goto Start;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -