// Serial.h: interface for the CSerial class.
//
//////////////////////////////////////////////////////////////////////
/*---------------------------------------------------------------------------
概述:串口读写操作类,用于对串口进行读写操作,即收发数据。

使用环境:windows操作系统
		  VS2008 VS2010 VS2013

应用示例:
	
	1. 定义对象
	   CSerial m_Serial;
    
	2. 初始化
	if (!m_Serial.Initialize("COM5",38400))
	{
		MessageBox("串口初始化失败","提示");
	}
	
	3. 设置串口接收数据回调函数
	m_Serial.SetComReadCallback(GetSerialPortData);
	
	函数定义示例如下:
	void GetSerialPortData(char *buffer,const DWORD size)
	{
		// 完成数据接收后的处理工作
	}

	4. 通过串口发送数据
	if (TRUE == m_Serial.IsInitialized())
	{
		unsigned char buffer[10];
		m_Serial.WriteABuffer(buffer,10);  // 举例
	}

	5. 卸载串口
	if (TRUE == m_Serial.IsInitialized())
	{
		m_Serial.DeInit();
	}

	其它接口函数根据实际需求进行调用。
	

问题及解决情况记录:
			问题1:
			解决情况:

			问题2:
			解决情况:

			......

修改记录:	
			版本   日期		   作者		   备注
            V1.0   2016/11/29  王家星	   在原有代码整理与简化,添加头文件注释 
----------------------------------------------------------------------------*/



#if !defined(AFX_SERIAL_H_UAV)
#define AFX_SERIAL_H_UAV

#if _MSC_VER > 1000
#pragma once
#endif 

#define MAX_OUT_BUFFER	2048
#define MAX_IN_BUFFER	2048
#define	CHECK_TIMEOUT	110

// 回调函数定义
typedef void(*COMCALLBACK)(char *buffer,const DWORD size);

class CSerial  
{
public:
	CSerial();
	virtual ~CSerial();
public:
	/*  【1】
	功能: 设置对串口读入数据进行处理的回调函数
	输入: 
		  func,串口回调函数地址
	输出:
		  返回值:无
	*/
	void SetComReadCallback(COMCALLBACK func);

	/*  【2】
	功能: 初始化串口
	输入:
		  1. serial_port,用字符串表示的串口名称:例如:“COM5”
	      2. baud_rate,波特率
	      3. byte_size,数据位长度
	      4. parity ,校验类型
	      5. stopbits,停止位长度
	输出:
		返回值:	BOOL 型,表明是否初始化成功char *serial_port,
	*/
	BOOL Initialize(PCTSTR serial_port,
		            DWORD baud_rate = CBR_9600,
		            BYTE byte_size = 8,
		            BYTE parity = NOPARITY,
		            BYTE stopbits = ONESTOPBIT);

	/*  【3】
	功能: 判断是否已经进行了初始化
	输入:		
	输出:
		返回值:	BOOL 型,表明是否初始化成功
	*/
	BOOL IsInitialized()const;

	
	/*  【4】
	功能: 断开串口
	输入:		
	输出:
		返回值:		
	*/
	void DeInit();


	/*  【5】
	功能:通过串口向外发送数据
	输入:
		 1. buffer:待发送的数据
		 2. size:buffer的大小
	输出:
		返回值:		
	*/
	void WriteABuffer(unsigned char*buffer,DWORD size);


	/*  【6】
	功能:读进串口数据
	输入:
		 buffer,读进的数据
	输出:
		返回值:	DWORD型,读进的数据的大小
	*/
	DWORD ReadABuffer(char*buffer);


	/*  【7】
	功能:获取读串口完成事件句柄
	输入:	
	输出:
		返回值:HANDLE* 型,读串口完成事件句柄
	*/
	HANDLE* GetReadCompletedEvent()const;

	/*  【8】
	功能: 得到写串口完成事件句柄
	输入: 	
	输出:
		 返回值:HANDLE* 型,写串口完成事件句柄
	*/
	HANDLE* GetWriteCompletedEvent()const;

	/*  【9】
	功能: 关闭写串口线程
	输入: 		
	输出:
		返回值:		
	*/
	void ExitWriteThread();

	/*  【10】
	功能: 重启写串口线程
	输入:		
	输出:
		返回值:	BOOL 型,表明是否成功
	*/
	BOOL RestartWriteThread();

	/*  【11】
	功能: 重启读串口线程
	输入:		
	输出:
		 返回值: BOOL型,表明是否成功
	*/
	BOOL RestartReadThread();

	/*  【12】
	功能: 退出读串口线程
	输入:		
	输出:
		返回值:		
	*/
	void ExitReadThread();

	/*  【13】
	功能: 获取串口写线程ID
	输入: 		
	输出: 
		返回值:DWORD型,写线程ID
	*/
	DWORD GetWriteThreadID()const;

	/*  【14】
	功能: 获取串口读线程ID
	输入:		
	输出:
		返回值:DWORD型,读线程ID
	*/
	DWORD GetReadThreadID()const;

	
	/*  【15】
	功能: 读串口线程函数
	输入:		
		LPVOID para,传入读串口线程的参数,为PDATA_PACKAGE型
	输出:
		返回值:DWORD 型,表明线程返回
	*/
	friend DWORD WINAPI ReadThreadFunc(LPVOID para);

	
	/*  【16】
	功能: 写串口线程函数
	输入: 
		LPVOID para,传入写串口线程的参数,为PDATA_PACKAGE型
	输出:
		返回值:	DWORD 型,表明线程返回
	*/
	friend DWORD WINAPI WriteThreadFunc(LPVOID para);

protected:	
	void HandleSuccessRead();
	HANDLE	m_hComHandle;				/*串口句柄*/
	HANDLE	m_hWriteThread;				/*写串口线程句柄*/	
	DWORD	m_dwWriteProcID;			/*写串口线程ID*/	
	HANDLE	m_hReadThread;				/*读串口线程句柄*/	
	DWORD	m_dwReadProcID;				/*读串口线程ID*/	
	HANDLE	m_hWriteCompletedEvent;		/*写串口完成事件*/	
	HANDLE	m_hReadCompletedEvent;		/*读串口完成事件*/	
	BOOL	m_bIsInitialized;			/*是否初始化的标志*/	
	HANDLE	m_hExitReadThreadEvent;		/*结束读串口线程的事件句柄*/	
	HANDLE	m_hExitWriteThreadEvent;	/*结束写串口线程的事件句柄*/	
	HANDLE	m_hStartWriteEvent;			/*开始写串口时间句柄*/
	DWORD	m_dwWritten;				/*实际向外发送的数据量*/
	DWORD	m_dwToWrite;				/*需要向外发送的数据量*/
	DWORD	m_dwRead;					/*实际读进的数据*/
	CRITICAL_SECTION m_csReadSection;	/*处理读入数据的关键代码段*/
	CRITICAL_SECTION m_csWriteSection;	/*处理发送数据的关键代码段*/

	char	out_buffer[MAX_OUT_BUFFER];
	char	in_buffer[MAX_IN_BUFFER];
	COMCALLBACK  ReadCallBack;			/*处理输入的回调函数*/
};

#endif // !defined(AFX_SERIAL_H_UAV)