Windows serial port transceiver

The use of the windows serial port needs to call the header function <Windows.h> and <TCHAR.H> in advance.
<Windows.h> contains rich API interfaces, and <TCHAR.H> will use
the Windows serial port when passing in the serial port parameters. The use includes four steps: open the serial port, configure the serial port, read and write the serial port, and close the serial port.

//打开串口
void COM5::openSerial()
{
	hCom = CreateFile(_T("COM5"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
	//CreatFile的第一个参数需要用到<TCHAR.H>,这样才能创建一个句柄
	if (hCom == INVALID_HANDLE_VALUE)
	{
		cout << "COM5打开失败!" << endl;
		this->openFlag = false;
	}
	else
	{
		cout << "COM5打开成功!" << endl;
		this->openFlag = true;
	}
}

//设置串口
void COM5::setSerial(int BaudRate, int byte, int parity, int stopBit)
{
	SetupComm(hCom, 1024, 1024);//设置串口的接收缓冲和发送缓冲区域为1024个字节
	GetCommState(hCom, &this->dcb);//获取当前串口的配置
	this->dcb.BaudRate = BaudRate;
	this->dcb.ByteSize = byte;
	this->dcb.Parity = parity;
	this->dcb.StopBits = stopBit;//参数传入0代表停止位为1,传入1代表停止位为1.5,传入2代表停止位为2
	
	this->setFlag = SetCommState(hCom, &this->dcb);//将传入的参数设置到串口中去,设置成功返回1,设置失败返回0
	if (!this->setFlag)
	{
		cout << "COM5参数设置失败!" << endl;
	}
	else
	{
		cout << "COM5参数设置成功!" << endl;
	}

	COMMTIMEOUTS TimeOuts; //设定读超时
	TimeOuts.ReadIntervalTimeout = MAXDWORD;
	TimeOuts.ReadTotalTimeoutMultiplier = 0;
	TimeOuts.ReadTotalTimeoutConstant = 0; //设定写超时
	TimeOuts.WriteTotalTimeoutMultiplier = 500;
	TimeOuts.WriteTotalTimeoutConstant = 2000;
	SetCommTimeouts(hCom, &TimeOuts); //设置超时

	PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);//清空缓冲区
}

//发送数据
void COM5::sendData(int* data, int length) 
{
	DWORD  writernSize = 0;
	PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);//清空缓冲区
	this->sendFlag = WriteFile(hCom, data, length, &writernSize, NULL);
	if (!this->sendFlag)
	{
		cout << "发送失败" << endl;		
	}
}
//注:发送数据尚未按照要求去写,目前只是一个雏形

//接收数据
void COM5::receiveData(int* data, int length)
{
	DWORD ptr;
	int ch=0;
	int count = 0;
	bool headFlag = false;
	bool endFlag = false;
	//接收数据的构想:用死循环去接收,一次接收一个字符,当数据接收完成或者收到的数据长度大于给定的数据长度时跳出循环。此处ReadFile的返回值一直是true,或者说我不知道它在什么情况下才会返回false,直接把它作为循环条件,而该函数的第三个参数则是接收到字符就会返回非0,所以可以用来判断是否有收到字符,但是注意第三个参数传递的是地址,要用指针。
	while (ReadFile(hCom, &ch, 1, &ptr, NULL))
	{
		if (ptr)//判断是否接收到数据
		{
			//接收到了数据,进行处理,未接受到数据,不做处理

			//判断是否已经接收到头
			if (headFlag)
			{
				//已经接收到头,判断尾标记是否为true
				if (endFlag)
				{
					//已经接收到头且尾标记为true时,判断当前接受的字符是否是结束字符
					if (ch == 0x0a)
					{
						//已经接收到头且尾标记为true时,当前接受的字符是结束字符时,跳出循环
						break;
					}
					else
					{
						//已经接收到头且尾标记为true时,但当前接受的字符不是结束字符,重新开始接收,重置count以及头、尾标志
						count = 0;
						headFlag = false;
						endFlag = false;
					}	
				}
				else
				{
					//已经接收到头但尾标记为false时,判断当前接收到的字符是不是尾标志字符
					if (ch == 0x0d)
					{
						//已经接收到头,尾标记为false,而当前接收到的字符是尾标志字符,尾标志置为true
						endFlag = true;
					}
					else
					{
						//已经接收到头,尾标记为flase,且当前接收到的字符不是尾标志字符时,尾标记为false,把接收到的数据放在数组中
						endFlag = false;
						data[count] = ch;
						count++;
					}
				}
				//判断接收到的字符长度是否大于等于规定的字符长度
				if (count >= length)
				{
					//接收到的字符长度大于等于规定的字符长度,跳出循环
					break;
				}				
			}
			else
			{
				//之前未接受到头时,判断当前字符是否是头
				if (ch ==0x7e)
				{
					//之前未接受到头,但当前字符是头时,把头存入数组的首个地址,重新开始计数,头标记置为true
					count = 0;
					data[count] = ch;
					count++;
					headFlag = true;
				}
				else
				{
					//之前未接受到头,且当前字符也不是头时
					headFlag = false;
				}
			}
		}
	}

}

//关闭串口
void COM5::closeSerial()
{
	CloseHandle(hCom);
}

//构造函数,直接在定义时就调用了打开串口和设置串口的函数,减少代码的书写量
COM5::COM5(int BaudRate, int byte, int parity, int stopBit)
{
	openSerial();
	setSerial(BaudRate, byte, parity, stopBit);
}

//析构函数,调用串口关闭函数,直接在函数结束时关闭串口
COM5::~COM5()
{
	this->closeSerial();
	cout << "COM5关闭成功!" << endl;//调试时打开
}

Guess you like

Origin blog.csdn.net/weixin_44941350/article/details/123178217