Explorar o código

添加串口类;

scbc.sat2 %!s(int64=5) %!d(string=hai) anos
pai
achega
7919a9c299
Modificáronse 2 ficheiros con 486 adicións e 0 borrados
  1. 392 0
      SATService/SATService/SynSerial.cpp
  2. 94 0
      SATService/SATService/SynSerial.h

+ 392 - 0
SATService/SATService/SynSerial.cpp

@@ -0,0 +1,392 @@
+#include "StdAfx.h"
+#include "SynSerial.h"
+
+CSynSerial::CSynSerial(void) :m_hSerialPort(NULL)
+, m_dwInQueue(1024)
+, m_dwOutQueue(1024)
+{
+	memset(&m_dcb, 0, sizeof(DCB));
+	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
+	memset(&m_szSerialPort, 0, sizeof(TCHAR)*MAX_PORT_LEN);
+}
+
+CSynSerial::~CSynSerial(void)
+{
+	CloseSerialPort();
+}
+
+BOOL CSynSerial::OpenSerialPort( IN BYTE byCommPort, IN DWORD dwBaudRate, IN BYTE bySize, IN BYTE byParity, IN BYTE byStopBits, IN BYTE byStartAddr, IN INT nInterval )
+{
+	ASSERT(byCommPort);
+	CloseSerialPort();
+
+	_stprintf_s(m_szSerialPort, _T("\\\\.\\com%d"), (int)byCommPort);
+	m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL, NULL);
+	if (m_hSerialPort == INVALID_HANDLE_VALUE)
+	{
+		// 打开串口失败;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	BOOL bResult = FALSE;
+	// SetupComm设置缓冲区大小;
+	bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 在串口读写之前,清除缓冲区;
+	bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// GetCommState获取设备控制块状态;
+	memset(&m_dcb, 0, sizeof(DCB));
+	bResult = GetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	m_dcb.Parity = byParity;
+	if (m_dcb.Parity == NOPARITY)
+		m_dcb.fParity = FALSE;
+	else
+		m_dcb.fParity = TRUE;
+
+	m_dcb.BaudRate = dwBaudRate;
+	m_dcb.ByteSize = bySize;
+	m_dcb.StopBits = byStopBits;
+	if (m_dcb.ByteSize == 8)
+		m_dcb.StopBits = ONESTOPBIT;
+
+	// SetCommState设置设备的控制块状态;
+	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
+	bResult = SetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 获取设备的超时值;
+	bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 两字符之间最大的延时,设置0表示参数不起作用;
+	m_cts.ReadIntervalTimeout = 50;
+	m_cts.ReadTotalTimeoutMultiplier = 100;
+	m_cts.ReadTotalTimeoutConstant = 8000;
+	m_cts.WriteTotalTimeoutMultiplier = 100;
+	m_cts.WriteTotalTimeoutConstant = 5000;
+
+	// 设置设备的超时值;
+	bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+BOOL CSynSerial::OpenSerialPort( IN LPCTSTR lpCommPort, IN DWORD dwBaudRate, IN BYTE bySize, IN BYTE byParity, IN BYTE byStopBits, IN BYTE byStartAddr, IN INT nInterval )
+{
+	ASSERT(lpCommPort);
+	CloseSerialPort();
+
+	_stprintf_s(m_szSerialPort, _T("\\\\.\\%s"), lpCommPort);
+	m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL, NULL);
+	if (m_hSerialPort == INVALID_HANDLE_VALUE)
+	{
+		// 打开串口失败;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	BOOL bResult = FALSE;
+	// SetupComm设置缓冲区大小;
+	bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 在串口读写之前,清除缓冲区;
+	bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// GetCommState获取设备控制块状态;
+	memset(&m_dcb, 0, sizeof(DCB));
+	bResult = GetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	m_dcb.Parity = byParity;
+	if (m_dcb.Parity == NOPARITY)
+		m_dcb.fParity = FALSE;
+	else
+		m_dcb.fParity = TRUE;
+
+	m_dcb.BaudRate = dwBaudRate;
+	m_dcb.ByteSize = bySize;
+	m_dcb.StopBits = byStopBits;
+	if (m_dcb.ByteSize == 8)
+		m_dcb.StopBits = ONESTOPBIT;
+
+	// SetCommState设置设备的控制块状态;
+	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
+	bResult = SetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 获取设备的超时值;
+	bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 两字符之间最大的延时,设置0表示参数不起作用;
+	m_cts.ReadIntervalTimeout = 50;
+	m_cts.ReadTotalTimeoutMultiplier = 100;
+	m_cts.ReadTotalTimeoutConstant = 8000;
+	m_cts.WriteTotalTimeoutMultiplier = 100;
+	m_cts.WriteTotalTimeoutConstant = 5000;
+
+	// 设置设备的超时值;
+	bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+BOOL CSynSerial::ReOpenSerialPort()
+{
+	ASSERT(_tcslen(m_szSerialPort));
+	CloseSerialPort();
+
+	m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL, NULL);
+	if (m_hSerialPort == INVALID_HANDLE_VALUE)
+	{
+		// 打开串口失败;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	BOOL bResult = FALSE;
+	// SetupComm设置缓冲区大小;
+	bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 在串口读写之前,清除缓冲区;
+	bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// SetCommState设置设备的控制块状态;
+	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
+	bResult = SetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 设置设备的超时值;
+	bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+void CSynSerial::CloseSerialPort()
+{
+	if (m_hSerialPort != NULL && m_hSerialPort != INVALID_HANDLE_VALUE)
+		CloseHandle(m_hSerialPort);
+	m_hSerialPort = NULL;
+}
+
+BOOL CSynSerial::SetSerialPort(IN CONST DWORD & dwBaudRate, IN CONST BYTE & byByteSize, IN CONST BYTE & byParity, IN CONST BYTE & byStopBits, IN CONST BYTE & byStartAddr, IN CONST DWORD & dwInQueue, IN CONST DWORD & dwOutQueue)
+{
+	if (!IsOpen())
+		return FALSE;
+
+	BOOL bResult = FALSE;
+	// GetCommState获取设备控制块状态;
+	memset(&m_dcb, 0, sizeof(DCB));
+	bResult = GetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	m_dcb.Parity = byParity;
+	if (m_dcb.Parity == NOPARITY)
+		m_dcb.fParity = FALSE;
+	else
+		m_dcb.fParity = TRUE;
+
+	m_dcb.BaudRate = dwBaudRate;
+	m_dcb.ByteSize = byByteSize;
+	m_dcb.StopBits = byStopBits;
+	if (m_dcb.ByteSize == 8)
+		m_dcb.StopBits = ONESTOPBIT;
+
+	// SetCommState设置设备的控制块状态;
+	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
+	bResult = SetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 获取设备的超时值;
+	bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 两字符之间最大的延时,设置0表示参数不起作用;
+	m_cts.ReadIntervalTimeout = 50;
+	m_cts.ReadTotalTimeoutMultiplier = 100;
+	m_cts.ReadTotalTimeoutConstant = 8000;
+	m_cts.WriteTotalTimeoutMultiplier = 100;
+	m_cts.WriteTotalTimeoutConstant = 3000;
+
+	// 设置设备的超时值;
+	bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+void CSynSerial::SetSerialDCB(IN CONST DCB & dcb)
+{
+}
+
+void CSynSerial::SetSerialCommTimeouts(IN CONST COMMTIMEOUTS & commTimeouts)
+{
+}
+
+DWORD CSynSerial::WriteComm(IN BYTE * pWirteBuf, IN CONST INT32 nWriteSize)
+{
+	if (!IsOpen())
+		return 0;
+
+	if (pWirteBuf == NULL || !::AfxIsValidAddress(pWirteBuf, nWriteSize, FALSE))
+	{
+		return 0;
+	}
+	
+	DWORD dwErrorFlags;
+	DWORD dwBytesWritten = 0;	// 实际写入的字节数;
+	// 写前, 清除错误;
+	COMSTAT ComStat;
+	ClearCommError(m_hSerialPort, &dwErrorFlags, &ComStat);	
+	// 写前,清空缓存区;
+	PurgeComm(m_hSerialPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
+	if ( !WriteFile(m_hSerialPort, pWirteBuf, nWriteSize, &dwBytesWritten, NULL) )
+	{
+		DWORD dwError = GetLastError();
+	}	
+
+	// 返回写入字节数;
+	return dwBytesWritten;
+}
+
+DWORD CSynSerial::ReadComm(IN BYTE *pReadBuf, IN CONST DWORD& dwReadSize, WORD timeout /* = 300 */)
+{
+	if (!IsOpen())
+		return 0;
+
+	if (pReadBuf == NULL || !::AfxIsValidAddress(pReadBuf, dwReadSize, FALSE))
+	{
+		return 0;
+	}
+
+	DWORD dwBytesRead = 0;
+	DWORD dwErrorFlags = 0;
+	// ReadFile前,使用ClearCommError清除错误;
+	COMSTAT ComStat = {0};
+	DWORD dwLastLen = 0;
+	ULONGLONG ulTick = GetTickCount64();	
+	// 直到有数据为止,超时3秒;
+	//while (true)
+	{// cbInQue表示输入缓冲区的字节数; 
+		Sleep(timeout);
+		//if (GetTickCount64() - ulTick > timeout)
+		//	break;
+		ClearCommError(m_hSerialPort, &dwErrorFlags, &ComStat);
+		// 防止读一次没读完,再读一次;二次长度一样表示读完;
+		//if (ComStat.cbInQue != 0 && dwLastLen == ComStat.cbInQue)
+		//	break;
+		dwLastLen = ComStat.cbInQue;
+	}
+
+	if (ComStat.cbInQue == 0)
+	{
+		// 串口超时,无数据返回;
+		return 0;
+	}
+
+	dwBytesRead = ComStat.cbInQue;
+	if (dwReadSize < dwBytesRead)
+	{
+		dwBytesRead = dwReadSize;
+	}
+
+	if (ReadFile(m_hSerialPort, pReadBuf, dwBytesRead, &dwBytesRead, NULL))
+	{
+		return (INT)dwBytesRead;
+	}
+
+	return dwBytesRead;
+}

+ 94 - 0
SATService/SATService/SynSerial.h

@@ -0,0 +1,94 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Home], 保留所有权利;
+/*  模 块 名:同步串口模块;
+/*  描    述:;
+/*
+/*  版    本:[V];
+/*  作    者:[Home];
+/*  日    期:[12/20/2017];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Home];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+
+#ifndef __SYN_SERIAL__
+#define __SYN_SERIAL__
+
+#pragma once
+
+#define MAX_PORT_LEN 10
+
+class CSynSerial
+{
+public:
+	CSynSerial(void);
+	virtual ~CSynSerial(void);
+
+private:
+	DCB		m_dcb;
+	HANDLE	m_hSerialPort;
+	COMMTIMEOUTS	m_cts;
+
+	// 串口号(1~255);
+	TCHAR	m_szSerialPort[MAX_PORT_LEN];
+	// 输入缓存大小(byte);
+	DWORD	m_dwInQueue;
+	// 输出缓存大小(byte);
+	DWORD	m_dwOutQueue;
+
+public:
+	inline BOOL IsOpen() const {
+		return (m_hSerialPort == NULL || m_hSerialPort == INVALID_HANDLE_VALUE) ? FALSE : TRUE;
+	}
+
+	// 打开串口;
+	BOOL OpenSerialPort(
+		IN BYTE byCommPort,		// 串口号;
+		IN DWORD dwBaudRate,		// 波特率;
+		IN BYTE bySize,			// 数据位;
+		IN BYTE byParity,		// 校验位;
+		IN BYTE byStopBits,		// 停止位;
+		IN BYTE byStartAddr,		// 起始地址;
+		IN INT nInterval			// 间隔时间;
+	);
+
+	BOOL OpenSerialPort(
+		IN LPCTSTR lpCommPort,		// 串口号;
+		IN DWORD dwBaudRate,		// 波特率;
+		IN BYTE bySize,			// 数据位;
+		IN BYTE byParity,		// 校验位;
+		IN BYTE byStopBits,		// 停止位;
+		IN BYTE byStartAddr,		// 起始地址;
+		IN INT nInterval			// 间隔时间;
+		);
+
+	// 重装打开串口;
+	BOOL ReOpenSerialPort();
+	// 关闭串口;
+	void CloseSerialPort();
+	// 设置串口参数;
+	BOOL SetSerialPort(
+		IN CONST DWORD& dwBaudRate,		// 波特率;
+		IN CONST BYTE& byByteSize,		// 数据位;
+		IN CONST BYTE& byParity,		// 校验位;
+		IN CONST BYTE& byStopBits,		// 停止位;
+		IN CONST BYTE& byStartAddr,		// 起始地址;
+		IN CONST DWORD& dwInQueue,		// 输入缓存;
+		IN CONST DWORD& dwOutQueue		// 输出缓存;
+		);
+
+	// 设置dcb参数;
+	void SetSerialDCB(IN CONST DCB &dcb);
+	// 设置commtimeouts参数;
+	void SetSerialCommTimeouts(IN CONST COMMTIMEOUTS &commTimeouts);
+
+	virtual DWORD WriteComm(IN BYTE *pWirteBuf, IN CONST INT32 nWriteSize);
+	virtual DWORD ReadComm(IN BYTE *pReadBuf, IN CONST DWORD& dwReadSize, WORD timeout = 300);
+};
+
+#endif // __SYN_SERIAL__