vc 串口通信代码

#include "StdAfx.h"
#include "comm.h"
#include "publib.h"
#include <process.h>

CommModule::CommModule()
{
	m_hCOM = NULL;
	m_bLog = FALSE;
	m_hThread = NULL;
	m_hStopEvt = NULL;
	m_data_cb = NULL;
}

CommModule::~CommModule()
{

}

HANDLE CommModule::Init_Port(const char *port)
{
	COMSTAT	comstat;
    DWORD	errors;

	CString s = CString(port);

	m_flowCtrl = COMM_FC_HW;
	m_baud = 115200;

	//	20120131 by foil - open com port fail
	int count = 1;
	while (count <= 50)	//	try 50 times
	{
		m_hCOM = CreateFile(s,
			GENERIC_READ|GENERIC_WRITE, 
			0, 
			NULL, 
			OPEN_EXISTING, 
			FILE_ATTRIBUTE_NORMAL, 
			NULL
			);
	
		if(m_hCOM == INVALID_HANDLE_VALUE )
		{
			DebugOut(_T("try %d: Failed to open %s, err = %d\n"), count, (LPCTSTR)s, GetLastError());
			Sleep(100);
			count ++;
		}
		else
			break;
	}

	if(m_hCOM == INVALID_HANDLE_VALUE )
	{
	//	if(m_bLog)
		DebugOut(_T("eventually Failed to open %s, err = %d\n"), (LPCTSTR)s, GetLastError());
		m_hCOM = NULL;
		return NULL;
	}
	else
		DebugOut(_T("Open %s succeeded!!!\n"), (LPCTSTR)s);

	::ClearCommError(m_hCOM, &errors, &comstat);

	//turn off fAbort first
	DCB dcb;

    if( GetCommState(m_hCOM, &dcb)==FALSE )
	{
		CloseHandle(m_hCOM);
		m_hCOM = NULL;
		return NULL;
	}

	dcb.DCBlength = sizeof(DCB);
    dcb.Parity = NOPARITY;
    dcb.ByteSize = 8;
    dcb.StopBits = ONESTOPBIT;
    dcb.BaudRate = m_baud;			
    dcb.fBinary = TRUE;
    dcb.fParity = FALSE;

	if(m_flowCtrl == COMM_FC_HW)
		dcb.fOutxCtsFlow = TRUE;
	else
		dcb.fOutxCtsFlow = FALSE;

    dcb.fOutxDsrFlow = FALSE;
    dcb.fDtrControl = DTR_CONTROL_DISABLE;
    dcb.fDsrSensitivity = FALSE;
    dcb.fTXContinueOnXoff = FALSE;
	dcb.fErrorChar = FALSE;
    dcb.fNull = FALSE;
	dcb.fAbortOnError = FALSE;

	if(m_flowCtrl == COMM_FC_SW)
	{
		dcb.fOutX = TRUE;
		dcb.fInX = TRUE;
	}
	else
	{
		dcb.fOutX = FALSE;
		dcb.fInX = FALSE;
	}   
	
	if(m_flowCtrl == COMM_FC_SW
	|| m_flowCtrl == COMM_FC_NONE)
		dcb.fRtsControl = RTS_CONTROL_ENABLE;
	else if(m_flowCtrl == COMM_FC_HW)
		dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;		    

	if(m_flowCtrl == COMM_FC_SW)
	{
		dcb.XonChar = 0x11;
		dcb.XoffChar = 0x13;
	}
	else
	{
		dcb.XonChar = 0;
		dcb.XoffChar = 0;
	}

    dcb.ErrorChar = 0;
    dcb.EofChar = 0;
    dcb.EvtChar = 0;

	::ClearCommError(m_hCOM, &errors, &comstat);

	if( SetCommState(m_hCOM, &dcb)==FALSE )
	{
		CloseHandle(m_hCOM);
		m_hCOM = NULL;
		return NULL;
	}

	if( ::SetupComm(m_hCOM, 8192, 8192)==FALSE )
	{
		CloseHandle(m_hCOM);
		m_hCOM = NULL;
		return NULL;
	}

	if( ::PurgeComm(m_hCOM, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR)==FALSE )
	{
		CloseHandle(m_hCOM);
		m_hCOM = NULL;
		return NULL;
	}

	// Communications Properties
    COMMPROP cp;
    if(GetCommProperties(m_hCOM, &cp) == FALSE)
    {
		CloseHandle(m_hCOM);
		m_hCOM = NULL;
		return NULL;
    }

	COMMTIMEOUTS timeouts;
    timeouts.ReadIntervalTimeout = 0xFFFFFFFF;
    timeouts.ReadTotalTimeoutMultiplier = 0;
    timeouts.ReadTotalTimeoutConstant = 0;
    timeouts.WriteTotalTimeoutMultiplier = 0;
    timeouts.WriteTotalTimeoutConstant = 2000;
    if( ::SetCommTimeouts(m_hCOM, &timeouts) == FALSE ) 
	{
		CloseHandle(m_hCOM);
		m_hCOM = NULL;
		return NULL;
	}			
	
	m_hStopEvt = ::CreateEvent(NULL, TRUE, FALSE, NULL);
	if(m_hStopEvt == NULL)
	{
		CloseHandle(m_hCOM);
		m_hCOM = NULL;
		return false;
	}

	if(StartThread() == false)
	{
		return NULL;
	}

	return m_hCOM;
}

// Wait for thread
void CommModule::WaitForExit()
{
	if(m_hThread == NULL)
        return;
	
	WaitForSingleObject(m_hThread, INFINITE);
	CloseHandle(m_hThread);
	m_hThread = NULL;
}

void CommModule::StopThread()
{
	if(m_hThread == NULL) 
		return ;
	
	::SetEvent(m_hStopEvt);
	WaitForExit();
}

bool CommModule::StartThread()
{
	m_hThread = (HANDLE)_beginthreadex(
		NULL, 0, (PBEGINTHREADEX_THREADFUNC)CommModule::HelpThreadFunc, (LPVOID)this, 0, NULL);
	
	if( m_hThread )
		return true;

	return false;
}

DWORD CommModule::ThreadFunc()
{
	COMSTAT	comstat;
    DWORD	errors;
	
	while(1) 
	{
		//If dwMilliseconds is zero, the function tests the object's state and returns immediately
		if( ::WaitForSingleObject(m_hStopEvt, 0)==WAIT_OBJECT_0 ) 
		{
            ::ClearCommError(m_hCOM, &errors, &comstat);
			break;
		}

		::ClearCommError(m_hCOM, &errors, &comstat);
		
		if( !comstat.cbInQue )
        {
            Sleep(1); //dwMilliseconds
            continue;
        }
		
        int dwBytesRead = (DWORD) comstat.cbInQue;
        if( 512 <= (int) dwBytesRead ) 
            dwBytesRead = 512;
		
		if( ::ReadFile(m_hCOM, rawchars, dwBytesRead, &m_dwRead, NULL) ) 
		{
            if( m_dwRead==0 || m_data_cb==NULL)
                continue;
			
			m_iRead = m_dwRead;
			rawchars[m_dwRead] = 0;

			if(m_bLog)
				DebugOutA("\r\n[rxd] %s\r\n", rawchars);
			m_data_cb(0, (const char*)rawchars, m_iRead, m_pData);

        }
	}
	
	return 0;
}

DWORD CommModule::HelpThreadFunc(LPVOID param)
{
	CommModule *pto = (CommModule *)param;
	
	return pto->ThreadFunc();

}

bool CommModule::WriteData(const char *Buf, const int size)
{
	CString strDebug, strTemp;
	
	int nRetryCount = 0;
	int nSentBytes = 0;
	
	while( nSentBytes < size )
	{
		int wbytes = 0;
		int nPerSend = 0;
		
		// reset write bytes
		wbytes = 0;
		
		// set send bytes
		nPerSend = size - nSentBytes;

	//	if (nPerSend%8 == 0)
	//		nPerSend--;
		
		// write to com
		BOOL bWriteResult = WriteFile(m_hCOM, ((char*)Buf)+nSentBytes, 
			nPerSend, (unsigned long*)&wbytes, NULL);
		
		// check result
		if(!bWriteResult)
		{
			if(m_bLog)
				DebugOutA("\r\n[error] WriteFile failed: %d\r\n", GetLastError());
			// clear com error
			::ClearCommError(m_hCOM, NULL, NULL);
		}
		else if( wbytes < nPerSend )
		{
			nSentBytes += wbytes;

			if(m_bLog)
				DebugOutA("\r\n[error] not write done. To write =%d, written = %d\r\n", nPerSend, wbytes);
		}
		else
		{
			// update the counts of sent bytes
			nSentBytes += wbytes;
			// reset retry count and continue to skip retry
			nRetryCount = 0;
			continue;
		}
		
		// check retry count
		if( 3 <= nRetryCount )
		{	
			if(m_bLog)
				DebugOutA("\r\n[error] write failed: <%s>\r\n", Buf);
			return false;
		}
		
		// increase retry count
		nRetryCount++;
		
		// receiver might be in busy status, sleep awhile
		Sleep(100);
	}
	if(m_bLog)
		DebugOutA("\r\n[txd] %s\r\n", Buf);
	return true;
}

int CommModule::SetCallBack(DataNotify reply, void *pExt)
{
	m_data_cb = reply;
	m_pData = pExt;

	return 1;
}

void CommModule::Deinit_Port()
{
	StopThread();
	
	if(m_hCOM!=NULL)
	{		
		CloseHandle(m_hCOM);
		m_hCOM = NULL;
	}

	if(m_hStopEvt!=NULL)
	{		
		CloseHandle(m_hStopEvt);
		m_hStopEvt = NULL;
	}
}

void CommModule::EnableLog(BOOL bEnable)
{
	m_bLog = bEnable;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VC(Visual C++)解析串口通讯协议的代码是为了实现在Windows操作系统下利用串口进行通讯。下面是一个简单的示例代码来解析串口通讯协议。 首先,我们需要引入Windows的头文件,并设置串口的参数。 ```cpp #include <windows.h> HANDLE hSerial; void SerialSetup() { hSerial = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hSerial == INVALID_HANDLE_VALUE) { // 处理打开串口失败的情况 } DCB dcbSerialParams = { 0 }; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); if (!GetCommState(hSerial, &dcbSerialParams)) { // 处理获取串口参数失败的情况 } dcbSerialParams.BaudRate = CBR_9600; // 设置波特率为9600 dcbSerialParams.ByteSize = 8; // 设置数据位为8位 dcbSerialParams.StopBits = ONESTOPBIT; // 设置停止位为1位 dcbSerialParams.Parity = NOPARITY; // 设置校验位为无校验位 if (!SetCommState(hSerial, &dcbSerialParams)) { // 处理设置串口参数失败的情况 } } ``` 接下来,我们可以编写一个函数来解析串口接收到的数据。 ```cpp void ParseSerialData() { DWORD bytesRead; char buffer[256]; if (!ReadFile(hSerial, buffer, sizeof(buffer), &bytesRead, NULL)) { // 处理读取串口数据失败的情况 } for (int i = 0; i < bytesRead; i++) { // 处理接收到的串口数据 // 根据通讯协议解析数据 } } ``` 我们可以在主函数中调用以上两个函数。 ```cpp int main() { SerialSetup(); while (true) { ParseSerialData(); } return 0; } ``` 这段示例代码可以让我们理解如何使用VC解析串口通讯协议。当然,实际的通讯协议解析可能更加复杂,需要根据具体的协议格式来解析数据。以上仅为一个简单的示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值