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

📄 stopwaitcommdlg.cpp

📁 停等协议 实现停等协议 利用发送端和接收端 利用串口
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -