📄 comseries.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 + -