📄 stopwaitcommdlg.cpp
字号:
pDlg->m_Send.EnableWindow(false);
pDlg->m_Setup.EnableWindow(false);
CommState=RECVSTATE;//进入接收状态
Sequence=0;
RecvPTR=0;
STXFlag=0;
TextLen=0;
time(&TimeStart);
SendBuf[0]=ACK; //发送确认信息
SendBuf[1]=Sequence;
SendLen=2;
SendMsg("发送:ACK 0");
}
break;
case SENDSTATE:
if (ACKFlag==true)
{
if (RecvBuf[RecvPTR]==Sequence)
{
sprintf(DisplayStr,"接收:ACK %i",Sequence);pDlg->m_ListLog.InsertString(-1,DisplayStr);
SendCount=0;
pDlg->KillTimer(m_nTimer);//重新计时
if (LastPacket==true) //是否最后一包
{
CommState=IDLESTATE;
SendFile.Close(); //最后一包,关闭文件
SendBuf[0]=EOT; //通知接收方开始发送
SendBuf[1]=EOT;
SendLen=2;
SendMsg("发送:EOT");
pDlg->m_ListLog.InsertString(-1,"------返回空闲状态------");
time(&TimeFinish); //显示统计信息
DiffTime=difftime(TimeFinish,TimeStart);
if (((ULONG) DiffTime)==0) sprintf(tempStr,"xxxxx"); //该程序只能精确到秒
else
{
Ratio=(((TextLen*9.0)/Speed)/DiffTime)*100;
sprintf(tempStr,"%f%%",Ratio);
}
pDlg->m_ListLog.InsertString(-1,"统计信息(注意本程序的传输时间只能精确到秒):");
sprintf(DisplayStr,"数据速率:%i字节/秒;数据包长:%i字节;线路延迟:+%i微秒;",Speed,PacketLen,DelayTime);
pDlg->m_ListLog.InsertString(-1,DisplayStr);
sprintf(DisplayStr,"数据长度:%li字节;传输耗时:%li秒;传输效率:%s。",TextLen,(ULONG) DiffTime,tempStr);
pDlg->m_ListLog.InsertString(-1,DisplayStr);
pDlg->m_Send.EnableWindow(true);
pDlg->m_Setup.EnableWindow(true);
}
else
{
MakePacket();
SendMsg("发送:信息......");
if(Sequence ==0 )Sequence=1;//变换Sequence.
else Sequence=0;
m_nTimer=pDlg->SetTimer(1,TIMEOUT,0); //设置定时器
}
}
ACKFlag=false;
}
else
if (RecvBuf[RecvPTR]==ACK) ACKFlag=true;
break;
case RECVSTATE:
switch (STXFlag)
{
case 0:
switch (RecvBuf[RecvPTR])
{
case EOT:
CommState=IDLESTATE;RecvPTR=0; //接收完成,连接断开
pDlg->m_ListLog.InsertString(-1,"接收:完成");
RecvFile.Close ();
pDlg->m_ListLog.InsertString(-1,"------返回空闲状态------");
pDlg->KillTimer(m_nTimer);
time(&TimeFinish); //显示统计信息
DiffTime=difftime(TimeFinish,TimeStart);
if (((ULONG) DiffTime)==0) sprintf(tempStr,"xxxxxx"); //该程序只能精确到秒
else
{
Ratio=(((TextLen*9.0)/Speed)/DiffTime)*100;
sprintf(tempStr,"%f%%",Ratio);
}
pDlg->m_ListLog.InsertString(-1,"统计信息(注意本程序的传输时间只能精确到秒):");
sprintf(DisplayStr,"数据速率:%i字节/秒;数据包长:%i字节;线路延迟:+%i微秒;",Speed,PacketLen,DelayTime);
pDlg->m_ListLog.InsertString(-1,DisplayStr);
sprintf(DisplayStr,"数据长度:%li字节;传输耗时:%li秒;传输效率:%s。",TextLen,(ULONG) DiffTime,tempStr);
pDlg->m_ListLog.InsertString(-1,DisplayStr);
pDlg->m_Send.EnableWindow(true);
pDlg->m_Setup.EnableWindow(true);
break;
case ENQ:
pDlg->m_ListLog.InsertString(-1,"接收:ENQ");
SendBuf[0]=ACK; SendBuf[1]=Sequence; SendLen=2; //发送确认信息
sprintf(DisplayStr,"发送:ACK %i",Sequence);
SendMsg(DisplayStr);
break;
case STX:
STXFlag=1;
break;
}
break;
case 1:
if (RecvBuf[RecvPTR]==Sequence)
{
STXFlag=2;
CRC=0;
}
else STXFlag=0;
break;
case 2:
switch (RecvBuf[RecvPTR])
{
case ETX:
if (CRC==0)
{
pDlg->m_ListLog.InsertString(-1,"接收:信息......");
RecvFile.Write(RecvBuf,RecvPTR-1); //将接收信息存入文件
TextLen=TextLen+RecvPTR-1;
if(Sequence==0)Sequence=1;
else Sequence=0;
SendBuf[0]=ACK; SendBuf[1]=Sequence; SendLen=2;
sprintf(DisplayStr,"发送:ACK %i",Sequence);
SendMsg(DisplayStr);
}
RecvPTR=0;STXFlag=0; //开始新的一包
break;
default:
if (RecvPTR < BUFFER_SIZE) CRC=CRC^RecvBuf[RecvPTR++];
else {RecvPTR=0;STXFlag=0;}
break;
}
break;
}
break;
}
}
}
return 0;
}
void MakePacket() //打包
{
int len,i;
SendBuf[0]=STX;SendBuf[1]=Sequence;
len=SendFile.Read(&SendBuf[2],PacketLen); //读取数据
CRC=0; //计算校验和
for (i=0;i<len;i++)
CRC=CRC^SendBuf[i+2];
SendBuf[2+len]=CRC;
SendBuf[2+len+1]=ETX;
SendLen=2+1+len+1;
if(len==PacketLen)LastPacket=false;
else LastPacket=true;
TextLen=TextLen+len;
}
void SendMsg(char *DisplayStr) //向串行口发送信息
{
CEvent SendEvent(0,TRUE,0,0); //发送和接收事件
OVERLAPPED SendOV;
ULONG SentLen;
memset(&SendOV,0,sizeof(SendOV)); //初始化Overlapped变量
SendOV.hEvent=SendEvent;
Sleep(DelayTime); //模拟长线路延迟
WriteFile(m_hCommPort,SendBuf,SendLen,&SentLen,&SendOV);
GetOverlappedResult(m_hCommPort,&SendOV,&SentLen,TRUE); //等待发送完成
SendEvent.ResetEvent();
pDlg->m_ListLog.InsertString(-1,DisplayStr); //显示信息
}
void CStopWaitCommDlg::OnCancel()
{
// TODO: Add extra cleanup here
CDialog::OnCancel();
}
void CStopWaitCommDlg::OnSetup()
{
// TODO: Add your control notification handler code here
}
void CStopWaitCommDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
switch (CommState)
{
case SENDSTATE:
if (SendCount<3)
{
SendCount++;
KillTimer(m_nTimer);
SendMsg("超时重传......");
m_nTimer=SetTimer(1,TIMEOUT,NULL);
}
else
{
pDlg->KillTimer(m_nTimer);
m_ListLog.InsertString(-1,"发送超时......");
CommState=IDLESTATE;
SendFile.Close(); //最后一包,关闭文件
SendBuf[0]=EOT;SendBuf[1]=EOT;SendLen=2; //通知接收方开始发送
SendMsg("发送:EOT");
m_ListLog.InsertString(-1,"------返回空闲状态------");
m_Send.EnableWindow(true);
m_Setup.EnableWindow(true);
}
break;
case RECVSTATE:
m_ListLog.InsertString(-1,"接收超时......");
CommState=IDLESTATE;RecvPTR=0; //接收完成,连接断开
pDlg->m_ListLog.InsertString(-1,"接收:完成");
RecvFile.Close ();
m_ListLog.InsertString(-1,"------返回空闲状态------");
KillTimer(m_nTimer);
m_Send.EnableWindow(true);
m_Setup.EnableWindow(true);
break;
}
CDialog::OnTimer(nIDEvent);
}
bool SetupCommPort() //设置串行口
{
DCB CommDCB; //串行口的设备控制块
m_hCommPort=CreateFile (CommPort, //打开串行口
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
NULL);
if(m_hCommPort==INVALID_HANDLE_VALUE)
{
AfxMessageBox("系统无法打开此串口设备(CreateFile)!");
return false;
}
AfxBeginThread(ReadChar,NULL,THREAD_PRIORITY_NORMAL);
if(!GetCommState(m_hCommPort,&CommDCB)) //得到原来的串口参数
{
AfxMessageBox("无法得到串口状态(GetCommState)!");
CloseHandle(m_hCommPort);
return false;
}
CommDCB.BaudRate =Speed; //设置新的串口参数
CommDCB.ByteSize =8;
CommDCB.Parity = NOPARITY;
CommDCB.StopBits = ONESTOPBIT ;
CommDCB.fBinary = TRUE ;
CommDCB.fParity = FALSE;
if(!SetCommState(m_hCommPort, &CommDCB))
{
AfxMessageBox("无法设置串口状态(SetupCommState)!");
CloseHandle(m_hCommPort);
return false;
}
if (!SetupComm(m_hCommPort,BUFFER_SIZE,BUFFER_SIZE)) //设置缓冲区
{
AfxMessageBox("设置缓冲区错误(SetupComm)!");
CloseHandle(m_hCommPort);
return false;
}
if (!PurgeComm(m_hCommPort, PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT)) //清除所有接收和发送缓冲区中的数据
{
AfxMessageBox("清空缓冲区错误(PurgeComm)!");
CloseHandle(m_hCommPort);
return false;
}
RecvPTR=0;
return true;
}
void CStopWaitCommDlg::OnClose()
{
// TODO: Add your message handler code here and/or call default
CloseHandle(m_hCommPort);
CDialog::OnClose();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -