⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 krrcom.cpp

📁 通过串口接收数据
💻 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 + -