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

📄 comseries.c

📁 串口通讯源代码
💻 C
字号:
#include <io.h>
#include <windows.h> 
#include "comseries.h"

HANDLE hComm;
//用来存放当前的串口的数据,来返回
unsigned char* curentBufferData;
BYTE dataset[1024];
OVERLAPPED osWrite = {0};//重叠方式

INT OpenCommSeries(INT port, DWORD dwBaud, BYTE parity, BYTE DataBits, BYTE stopbits, BYTE fc, BOOL bOverlapped)
{
	char fname[MAX_PATH*2];
	sprintf(fname,"COM%d",port);
	hComm = CreateFile(fname,  
		GENERIC_READ|GENERIC_WRITE, 
		0,
		0, 
		OPEN_EXISTING,
		FILE_FLAG_OVERLAPPED,
		0);
	if (hComm == INVALID_HANDLE_VALUE)
		return -1;
	else
	{
		SetCommBuffer(hComm,1024,1024);
		SetCommTimeOut(hComm,MAXDWORD,MAXDWORD,63);
		SetCommDCB(hComm,dataset,dwBaud,parity,DataBits,stopbits,fc);
		return 0;
	}
}

INT SetCommBuffer(HANDLE hpComm,DWORD dInBuf,DWORD dOutBuf)
{
	//设置为1024字节的缓冲区
	BOOL ret=SetupComm(hpComm,dInBuf,dOutBuf); 
	return (ret==TRUE)?0:-1;
}

INT SetCommTimeOut(HANDLE hpComm,
				   DWORD dReadIntervalTimeout,
				   DWORD dReadTotalTimeoutMultiplier,
				   DWORD dReadTotalTimeoutConstant)
{
	BOOL ret;
	COMMTIMEOUTS TimeOuts;
	OVERLAPPED osWrite = {0};//重叠方式
	//设定读超时
	TimeOuts.ReadIntervalTimeout=dReadIntervalTimeout;
	TimeOuts.ReadTotalTimeoutMultiplier=dReadTotalTimeoutMultiplier;
	TimeOuts.ReadTotalTimeoutConstant=dReadTotalTimeoutConstant;
	//在读一次输入缓冲区的内容后读操作就立即返回,
	//而不管是否读入了要求的字符。
	//设定写超时
	osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (osWrite.hEvent == NULL)
		return -1;
	ret=SetCommTimeouts(hComm,&TimeOuts); //设置超时
	return (ret==TRUE)?0:-1;
}

INT SetCommDCB(HANDLE hpComm,BYTE *dt,DWORD dwBaud, BYTE parity, BYTE DataBits, BYTE stopbits, BYTE fc)
{
	BOOL ret;
	DCB dcb;
	FillMemory(&dcb, sizeof(dcb), 0);
	dcb.DCBlength = sizeof(dcb);
	
	//Setup the flow control 
	dcb.fDsrSensitivity = FALSE;
	dcb.BaudRate = dwBaud; 
	dcb.ByteSize = DataBits;
	switch (parity)
	{
    case EvenParity:  dcb.Parity = EVENPARITY;  break;
    case MarkParity:  dcb.Parity = MARKPARITY;  break;
    case NoParity:    dcb.Parity = NOPARITY;    break;
    case OddParity:   dcb.Parity = ODDPARITY;   break;
    case SpaceParity: dcb.Parity = SPACEPARITY; break;
	}
	switch (stopbits)
	{
    case OneStopBit:           dcb.StopBits = ONESTOPBIT;   break;
    case OnePointFiveStopBits: dcb.StopBits = ONE5STOPBITS; break;
    case TwoStopBits:          dcb.StopBits = TWOSTOPBITS;  break;
	}
	switch (fc)
	{
    case NoFlowControl:
		{
			dcb.fOutxCtsFlow = FALSE;
			dcb.fOutxDsrFlow = FALSE;
			dcb.fOutX = FALSE;
			dcb.fInX = FALSE;
			break;
		}
    case CtsRtsFlowControl:
		{
			dcb.fOutxCtsFlow = TRUE;
			dcb.fOutxDsrFlow = FALSE;
			dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
			dcb.fOutX = FALSE;
			dcb.fInX = FALSE;
			break;
		}
    case CtsDtrFlowControl:
		{
			dcb.fOutxCtsFlow = TRUE;
			dcb.fOutxDsrFlow = FALSE;
			dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
			dcb.fOutX = FALSE;
			dcb.fInX = FALSE;
			break;
		}
    case DsrRtsFlowControl:
		{
			dcb.fOutxCtsFlow = FALSE;
			dcb.fOutxDsrFlow = TRUE;
			dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
			dcb.fOutX = FALSE;
			dcb.fInX = FALSE;
			break;
		}
    case DsrDtrFlowControl:
		{
			dcb.fOutxCtsFlow = FALSE;
			dcb.fOutxDsrFlow = TRUE;
			dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
			dcb.fOutX = FALSE;
			dcb.fInX = FALSE;
			break;
		}
    case XonXoffFlowControl:
		{
			dcb.fOutxCtsFlow = FALSE;
			dcb.fOutxDsrFlow = FALSE;
			dcb.fOutX = TRUE;
			dcb.fInX = TRUE;
			dcb.XonChar = 0x11;
			dcb.XoffChar = 0x13;
			dcb.XoffLim = 100;
			dcb.XonLim = 100;
			break;
		}
	}
	if (!BuildCommDCB(dt, &dcb)) 
		return -1;
	else
	{
		ret=SetCommState(hpComm, &dcb);
		if (ret!=TRUE) return -1;
	}
	//清空
	ret=PurgeComm(hpComm, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
	return (ret==TRUE)?0:-1;
}

//向串口写入数据
INT WriteCOMBuffer(unsigned char *lpBuf, DWORD dwToWrite)
{
	DWORD dwWritten;
	DWORD dwRes;
	BOOL fRes;
	//写之前清除
	PurgeComm(hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
	
	//向指定的口写数据
	//如果这个时候不能及时返回的话,那么就会返回FALSE
	if (!WriteFile(hComm, lpBuf, dwToWrite, &dwWritten, &osWrite)) 
	{
		//得到错误的代码,以下说明不是因为发送延时出错,报错
		if (GetLastError() != ERROR_IO_PENDING)
		{
			fRes = -1;
			return -1;
		}
		//如果发生的是因为写入数据时的延时错误
		else
		{
			//那么就等待信号,有两种,一种是有信号了,一种是超时
			dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);
			//看返回值是什么以做下一步
			switch(dwRes)
			{
				//表明是有信号了
			case WAIT_OBJECT_0:
				//得到重叠的结果,如果为真的话,那么发送成功
				if (!GetOverlappedResult(hComm, &osWrite, &dwWritten, FALSE))
				{
					fRes = -1;
					return -1;
				}
				//如果发送成功完成
				else
					fRes = 0;
				break;
			default:	//其他处理
				return -1;
			}
		}
	}
	//出现这种情况说明立刻返回了
	else
		fRes = 0;
	//关闭事件
	CloseHandle(osWrite.hEvent);
	return fRes;
}

INT ReadCOMBuffer(BYTE *lpBuf)
{
	INT ret=0;
	INT len=0;
	DWORD dwRead;
	DWORD dwRes;
	BOOL fWaitingOnRead = FALSE;
	OVERLAPPED osReader = {0};
	BYTE llpBuf;
	//创建一个事件
	osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (osReader.hEvent == NULL)
	{
		//AfxMessageBox("创建事件失败!!!");
		ret= -1;
	}
	//如果并没有阻塞在读上面,那么执行以下代码
	if (!fWaitingOnRead)
	{
		do 
		{
			if (!ReadFile(hComm,&llpBuf,1, &dwRead,&osReader)) 
			{
				//AfxMessageBox("开始读数据!");
				if (GetLastError() != ERROR_IO_PENDING)  
				{
					ret= -1;
					//::OutputDebugString("出现读错误!!!\n");
					//AfxMessageBox("出现读错误!!!")
				}
				//否则说明数据在读的时候正在阻塞
				else
				{  
					ret= -1;
					//::OutputDebugString("读数据的时候发生了阻塞!!!\n");
					//AfxMessageBox("读数据的时候发生了阻塞!!!");
					fWaitingOnRead = TRUE;
					//看在等待的时候返回什么
					dwRes = WaitForSingleObject(osReader.hEvent,10);
					switch (dwRes)
					{
					case WAIT_OBJECT_0:
						if (!GetOverlappedResult(hComm, &osReader, &dwRead, FALSE))
						{
							// AfxMessageBox("读数据产生错误!!!");
							//::OutputDebugString("读数据产生错误!!!\n");
							ret= -1;
						}
						else
						{
							//::OutputDebugString("读数据成功!!!");
							*(lpBuf++) = llpBuf;
							len++;
							ret= 0;
							//AfxMessageBox("读数据成功!!!");
						}
						fWaitingOnRead = FALSE;
						break;
						//读写超时
					case WAIT_TIMEOUT:
						ret= -1;
						//::OutputDebugString("读超时!!!\n");
						//AfxMessageBox("读超时!!");
						break;
					default:
						ret= -1;
						//::OutputDebugString("出现不可预知错误!!!\n");
						// AfxMessageBox("出现不可预知错误!!!");
						break;
					}
				}
			}
			else
			{
				//::OutputDebugString("读数据成功!!!\n");
				*(lpBuf++) = llpBuf;
				len++;
				ret= 0;
				//AfxMessageBox("读数据成功!!!");
			}
		} while(dwRead);
		//如果很快就读完了并且返回了
		CloseHandle(osReader.hEvent);
		//清空缓冲区
		PurgeComm(hComm, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
	}
	return len;
}

INT CloseCommSeries(void)
{
	if (IsOpen())
	{
		//Close down the comms port
		BOOL bSuccess = CloseHandle(hComm);
		hComm = INVALID_HANDLE_VALUE;
		CloseHandle(osWrite.hEvent);
		return (!bSuccess)?-1:0;
	}
	else
		return 0;
}

INT IsOpen(void)
{
	return (hComm!=INVALID_HANDLE_VALUE)?-1:0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -