对获取EF3返回锁存点功能,基本实现

This commit is contained in:
zhengxuan.zhang
2022-12-01 16:03:30 +08:00
parent 65cb1d3804
commit d652f671db
11 changed files with 349 additions and 171 deletions
+147 -38
View File
@@ -189,6 +189,15 @@ DWORD CPSerial::Open()
if (SetupComm(m_PortHandle, 2048, 2048))
{
// Setup the event masks for the monitoring task
// 设置你关心的事件, 当此事件发生时, 将得到事件通知, 通过SetCommMask函数设置, SetCommMask函数两个参数, 第一个为串口句柄, 第二个为事件, 可通过位或的方式指定多个事件,如下:
// BOOL WINAPI SetCommMask(
// __in HANDLE hFile,
// __in DWORD dwEvtMask);
//示例代码:
// SetCommMask(m_hCom, EV_RXCHAR);
// EV_RXCHAR事件指当输入缓冲区内有数据时, 通过WaitCommEvent函数可获得通知, 其他事件同理, 其他事件还有EV_BREAK / EV_CTS / EV_RING等,
if (SetCommMask(m_PortHandle, EV_RXCHAR | EV_TXEMPTY | EV_BREAK |
EV_CTS | EV_DSR | EV_ERR | EV_RLSD))
{
@@ -444,7 +453,7 @@ DWORD CPSerial::WritePort(const char* Buffer, DWORD Bytes)
}
//==========================================================================
/////////////////////////////////////////////////////////////////////////////
//单纯读取单包串口数据,拼包功能在上层实现
int CPSerial::ReadBlock(BYTE* abIn, int MaxLength)
{
@@ -454,14 +463,26 @@ int CPSerial::ReadBlock(BYTE* abIn, int MaxLength)
ClearCommError(m_PortHandle, &dwErrorFlags, &ComStat);
if (dwErrorFlags > 0)
{
//PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR
//分别表示:
//立即中断写操作并清空输出缓冲区 | 清空输出缓冲区 | 立即中断读操作并清空输入缓冲区 | 清空输入缓冲区
PurgeComm(m_PortHandle, PURGE_RXABORT | PURGE_RXCLEAR);
return 0;
}
dwLength = (static_cast<DWORD>(MaxLength) < ComStat.cbInQue ? MaxLength : ComStat.cbInQue);
//memset(abIn, 0, MaxLength);
//如果有字符即读入, 这种策略下无法解决读入的字符不是完整的一帧的问题 Bug
//如果有字符即读入, 这种策略下无法解决读入的字符不是完整的一帧的问题
if (dwLength)
{
//BOOL ReadFile(
// HANDLE hFile, //文件的句柄
// LPVOID lpBuffer, //用于保存读入数据的一个缓冲区
// DWORD nNumberOfBytesToRead, //要读入的字节数
// LPDWORD lpNumberOfBytesRead, //指向实际读取字节数的指针
// LPOVERLAPPED lpOverlapped
// //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。
// //该结构定义了一次异步读取操作。否则,应将这个参数设为NULL
//);
JudgeRead = ReadFile(m_PortHandle, abIn, dwLength, &dwLength, &m_ReceiveOLap); //读出字符至abIn处
if (!JudgeRead)
{
@@ -469,10 +490,17 @@ int CPSerial::ReadBlock(BYTE* abIn, int MaxLength)
if (GetLastError() == ERROR_IO_PENDING)
{
// WaitForSingleObject(m_osRead.hEvent,INFINITE);
GetOverlappedResult(m_PortHandle, &m_ReceiveOLap, &dwLength, TRUE);
GetOverlappedResult(m_PortHandle, &m_ReceiveOLap, &dwLength, TRUE); //等待一次异步读取完成
m_ReceiveOLap.Offset = 0;
// m_osRead.Offset=(m_osRead.Offset+dwLength)%MAXBLOCK;
//等待一次异步操作超时的情况下,GetOverlappedResult返回FALSE,同时GetLastError返回ERROR_IO_INCOMPLETE
/* if (WaitForSingleObject(m_osRead.hEvent, 1000) == WAIT_TIMEOUT)
{
dwLength = 0;
} */
}
//异常情况
else
{
dwLength = 0;
@@ -482,9 +510,69 @@ int CPSerial::ReadBlock(BYTE* abIn, int MaxLength)
return dwLength;
}
/////////////////////////////////////////////////////////////////////////////
// ReceiveTask() : Internal function, this runs as a thread and provides the
// OnRecieve and OnTransmit events
int CPSerial::Receive(void* buf, int maxlen, bool sync)
{
//HANDLE hCom = *(HANDLE*)m_PortHandle;
if (sync)
{
//同步方式
DWORD wCount = maxlen; //成功读取的数据字节数
BOOL bReadStat = ReadFile(m_PortHandle, //串口句柄
buf, //数据首地址
wCount, //要读取的数据最大字节数
&wCount, //DWORD*,用来接收返回成功读取的数据字节数
NULL); //NULL为同步发送,OVERLAPPED*为异步发送
if (!bReadStat)
{
return 0;
}
return wCount;
}
else
{
//异步方式
DWORD wCount = maxlen; //成功读取的数据字节数
DWORD dwErrorFlags; //错误标志
COMSTAT comStat; //通讯状态
OVERLAPPED m_osRead; //异步输入输出结构体
//创建一个用于OVERLAPPED的事件处理,不会真正用到,但系统要求这么做
memset(&m_osRead, 0, sizeof(m_osRead));
//m_osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, L"ReadEvent");
ClearCommError(m_PortHandle, &dwErrorFlags, &comStat); //清除通讯错误,获得设备当前状态
if (!comStat.cbInQue)return 0; //如果输入缓冲区字节数为0,则返回false
BOOL bReadStat = ReadFile(m_PortHandle, //串口句柄
buf, //数据首地址
wCount, //要读取的数据最大字节数
&wCount, //DWORD*,用来接收返回成功读取的数据字节数
&m_osRead); //NULL为同步发送,OVERLAPPED*为异步发送
if (!bReadStat)
{
if (GetLastError() == ERROR_IO_PENDING) //如果串口正在读取中
{
//GetOverlappedResult函数的最后一个参数设为TRUE
//函数会一直等待,直到读操作完成或由于错误而返回
GetOverlappedResult(m_PortHandle, &m_osRead, &wCount, TRUE);
/* memcpy(m_RecvData, buf, wCount);
m_iRecvBytes = wCount;
m_iRecvState = true;*/
}
else
{
ClearCommError(m_PortHandle, &dwErrorFlags, &comStat); //清除通讯错误
CloseHandle(m_osRead.hEvent); //关闭并释放hEvent的内存
return 0;
}
}
return wCount;
}
}
/*
// C prototype : void HexToStr(char *pszDest, byte *pbSrc, int nLen)
@@ -510,19 +598,22 @@ void CPSerial::hex2str(char* pszDest, byte* pbSrc, int nLen)
pszDest[nLen * 2] = '\0';
}
#if 1
/////////////////////////////////////////////////////////////////////////////
// ReceiveTask() : Internal function, this runs as a thread and provides the
// OnRecieve and OnTransmit events
void CPSerial::ReceiveTask(void)
{
//DWORD BytesWritten;
DWORD Events;
unsigned long State;
int temp_Packlen = 0; //临时存放包长度
do
{
Sleep(2);
Sleep(3);
BYTE abIn[MAXBLOCK];
int len;
len = ReadBlock(abIn, MAXBLOCK); //单包读取
//len = ReadBlock(abIn, MAXBLOCK); //读取一包串口数据
len = Receive(abIn, MAXBLOCK, 0);//方式2
if ((len > 0) && (len < MAX_RECIEVE_BUFFER_SIZE))
{
//memset(m_RecvData, 0, m_iRecvBytes);
@@ -530,37 +621,54 @@ void CPSerial::ReceiveTask(void)
{
auto pszDest = new char[len * 2 + 1];
hex2str(pszDest, abIn, len);
printf("len=%d, m_iExpectBytes=%d, %s\n", len, m_iExpectBytes, pszDest);
printf("kaishi len=%d, m_iExpectBytes=%d, %s\n", len, m_iExpectBytes, pszDest); //打印单包数据,每次可以从这里得到单包数据
}
if (m_iExpectBytes != 0) //当有期望值时,进行拼包
{
//循环拼包
if (m_iRecvBytes < m_iExpectBytes)
{
while (m_iRecvBytes < m_iExpectBytes)
{
memcpy(m_RecvData + m_iRecvBytes, abIn, len);
m_iRecvBytes += len;
auto pszDest = new char[m_iRecvBytes * 2 + 1];
hex2str(pszDest, m_RecvData, m_iRecvBytes);
printf("11111=%d %s\n", m_iRecvBytes, pszDest);
}
}
else // 大于等于期望返回数量,成功
{
memcpy(m_RecvData, abIn, len);
m_iRecvBytes = len;
m_iRecvState = TRUE;
}
}
else //无期望返回数量时,随机返回单包数据
// 第一层判断,当前接收正好为期望返回
if (len == m_iExpectBytes)
{
memcpy(m_RecvData, abIn, len);
m_iRecvBytes = len;
m_iRecvState = TRUE;
m_iRecvState = true;
printf("=====");
temp_Packlen = 0;
}
// 第二层判断,当前接收为期望返回的一部分
else if (len < m_iExpectBytes)
{
memcpy(m_RecvData + temp_Packlen, abIn, len);
temp_Packlen += len;
//打印拼包后的数据
auto pszDest = new char[m_iRecvBytes * 2 + 1];
hex2str(pszDest, m_RecvData, m_iRecvBytes);
printf("pinbao = %d %s\n", m_iRecvBytes, pszDest);
// 第三层判断,当前接收为期望返回的最后一部分
if (temp_Packlen == m_iExpectBytes)
{
m_iRecvBytes = temp_Packlen;
m_iRecvState = true;
printf("pinbao========");
}
}
// 第四层判断,当前接收为期望返回的超出部分,以实际接收为准
else if (len > m_iExpectBytes)
{
memcpy(m_RecvData, abIn, len);
m_iRecvBytes = len;
m_iRecvState = true;
printf(">>>>>>>>>>>>========");
temp_Packlen = 0;
}
}
// Events=0;
//
// // Wait for a comm event
@@ -614,7 +722,7 @@ void CPSerial::ReceiveTask(void)
}
#endif
#if 0
void CPSerial::ReceiveTask(void)
{
@@ -685,9 +793,10 @@ void CPSerial::OnReceive()
char s[MAX_RECIEVE_BUFFER_SIZE] = {0};
s[1] = '\0';
CurrentPointer = 0;
int num = 0;
if (m_HandShake == CS_HANDSHAKE_FOR_TRESASTR_E)
{
int num = ReadPort(s, MAX_RECIEVE_BUFFER_SIZE);
num = ReadPort(s, MAX_RECIEVE_BUFFER_SIZE);
if ((num > 0) && (num < MAX_RECIEVE_BUFFER_SIZE))
{
if (m_IsWrtingData)
@@ -709,7 +818,7 @@ void CPSerial::OnReceive()
}
else
{
int num = ReadPort(s, m_iRecvCount);
num = ReadPort(s, m_iRecvCount);
printf("----Data received:: %d----\r\n", num);
if ((num > 0) && (num < MAX_RECIEVE_BUFFER_SIZE))
{
@@ -723,7 +832,7 @@ void CPSerial::OnReceive()
}
}
}
//LineReceive(s, num);
LineReceive(s, num);
}