📄 stopwaitcommdlg.cpp
字号:
// StopWaitCommDlg.cpp : implementation file
//
#include "stdafx.h"
#include "StopWaitComm.h"
#include "StopWaitCommDlg.h"
#include ".\stopwaitcommdlg.h"
#include "afxmt.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define STX 0x02
#define ETX 0x03
#define EOT 0x04
#define ENQ 0x05
#define ACK 0x06
#define IDLESTATE 0
#define SENDSTATE 1
#define RECVSTATE 2
#define BUFFER_SIZE 3000
#define TIMEOUT 5000
CFile SendFile,RecvFile; //发送和接收文件
HANDLE m_hCommPort; //保存打开的串行口设备句柄
char RecvBuf[BUFFER_SIZE], SendBuf[BUFFER_SIZE];
UINT SendLen,RecvPTR;
UINT CommState; //保存通信状态:IdleState、SendState和RecvState
BYTE CRC; //保存校验和
BYTE Sequence; //序列号使用0和1
bool ACKFlag; //接收到ACK:true
bool LastPacket; //是否最后一包
UINT STXFlag; //0:没收到STX;1:收到STX但未收到序列号;2:收到STX而且收到序列号
UINT_PTR m_nTimer; //定时器
UINT SendCount; //重发计数器
time_t TimeStart,TimeFinish;
ULONG TextLen; //发送文件的总长度
CString CommPort;//需要打开的串行口
UINT PacketLen,Speed,DelayTime;//数据包大小,串行口的速率,为模拟长线路而增加的线路延迟
CStopWaitCommDlg* pDlg;
UINT ReadChar(PVOID hWnd); //读取字符线程
void MakePacket(); //打包
void SendMsg(char *DisplayStr); //向串行口发送信息
bool SetupCommPort(); //设置串行口
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CStopWaitCommDlg dialog
CStopWaitCommDlg::CStopWaitCommDlg(CWnd* pParent /*=NULL*/)
: CDialog(CStopWaitCommDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CStopWaitCommDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CStopWaitCommDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CStopWaitCommDlg)
DDX_Control(pDX, IDOK, m_Send);
DDX_Control(pDX, IDC_SETUP, m_Setup);
DDX_Control(pDX, IDC_LOG, m_ListLog);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CStopWaitCommDlg, CDialog)
//{{AFX_MSG_MAP(CStopWaitCommDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_SETUP, OnSetup)
ON_WM_TIMER()
ON_WM_CLOSE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CStopWaitCommDlg message handlers
BOOL CStopWaitCommDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
CStopWaitCommApp* pApp=(CStopWaitCommApp*)AfxGetApp();
pDlg=(CStopWaitCommDlg*)pApp->m_pMainWnd;
m_Send.EnableWindow(false);
CommPort="COM1";Speed=9600;PacketLen=1500;DelayTime=0;
if (SetupCommPort())
{
m_Send.EnableWindow(true);
char str[100];
sprintf(str,"StopWaitComm 串行口=%s,速率=%i,包长度=%i,线路延迟+%i",CommPort,Speed,PacketLen,DelayTime);
pDlg->SetWindowText(str);
}
else
m_Send.EnableWindow(false);
return TRUE; // return TRUE unless you set the focus to a control
}
void CStopWaitCommDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CStopWaitCommDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x=(rect.Width() - cxIcon + 1)/2;
int y=(rect.Height() - cyIcon + 1)/2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CStopWaitCommDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CStopWaitCommDlg::OnOK()
{
// TODO: Add extra validation here
//获取需要发送的文件名
CString FileName;
CFileDialog GetFileName(TRUE,NULL,NULL,OFN_HIDEREADONLY,"文本文件(*.txt)|*.txt||",NULL);
if (GetFileName.DoModal()!=IDOK) return;
FileName=GetFileName.GetPathName();
if ( !SendFile.Open(FileName,CFile::modeRead|CFile::typeBinary,NULL)) //打开文件
{
MessageBox("发送文件打开错误!");
return;
}
//进入发送状态
m_Send.EnableWindow(false);
m_Setup.EnableWindow(false);
m_ListLog.InsertString(-1,"------进入发送状态------");
CommState=SENDSTATE;
time(&TimeStart); //开始计时
ACKFlag=false;
LastPacket=false;
Sequence=0;
SendCount=0;
TextLen=0;
SendBuf[0]=ENQ;
SendLen=1; //通知接收方开始发送
SendMsg("发送:ENQ");
m_nTimer=SetTimer(1,TIMEOUT,NULL); //设置定时器
}
UINT ReadChar(PVOID hWnd)
{
CEvent RecvEvent(0,TRUE,0,0);//发送和接收事件
OVERLAPPED RecvOV;
char DisplayStr[256],tempStr[50];
ULONG ReadLen;
double DiffTime,Ratio;
memset(&RecvOV,0,sizeof(RecvOV)); //初始化Overlapped变量
RecvOV.hEvent=RecvEvent;
while (true) //只要线程运行,就监视端口是否收到数据
{
if (CommState==RECVSTATE) m_nTimer=pDlg->SetTimer(1,3*TIMEOUT,NULL); //设置定时器
ReadFile(m_hCommPort,&RecvBuf[RecvPTR],1,&ReadLen,&RecvOV); //读字符
GetOverlappedResult(m_hCommPort,&RecvOV,&ReadLen,TRUE); //等待读状态完成
RecvEvent.ResetEvent(); //复位事件变量
if (ReadLen>0)
{
switch (CommState)
{
case IDLESTATE:
if (RecvBuf[RecvPTR]==ENQ) //收到ENQ,进入接收状态
{
pDlg->m_ListLog.InsertString(-1,"------进入接收状态------");
pDlg->m_ListLog.InsertString(-1,"接收:ENQ");
if ( !RecvFile.Open("receive.txt",CFile::modeCreate|CFile::modeWrite|CFile::typeBinary,NULL)) //打开文件
{
AfxMessageBox("接收文件打开错误!");
pDlg->m_ListLog.InsertString(-1,"------返回空闲状态------");
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -