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

📄 commdlg.cpp

📁 双机冗余系统采用主备机原则运用软件方式通过串口相互通信
💻 CPP
字号:
// CommDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Comm.h"
#include "CommDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////
/////////////////////////////////////
	DCB dcb;		//编程配置串口结构
	HANDLE hCom;	//句柄
	DWORD dwError,dwEvtMask,dwEvent;
	BOOL fSuccess;//判断是否成功

	OVERLAPPED o;
	COMMPROP	CommProp;	//串口信息结构,不可更改
	COMMTIMEOUTS timeouts;	//定义超时设置结构
	COMSTAT cs;

	BOOL test=TRUE;
	char input[1000];
	CString receiveData,sendData;
	HWND hWndUpdate;
	int t=50;

/////////////////////////////////////////////////////////////////////////////
// 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()

/////////////////////////////////////////////////////////////////////////////
// CCommDlg dialog

CCommDlg::CCommDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CCommDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CCommDlg)
	m_sendData = _T("");
	m_receiveData = _T("");
	m_sleepTime = 0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CCommDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CCommDlg)
	DDX_Text(pDX, IDC_EDIT1, m_sendData);
	DDX_Text(pDX, IDC_EDIT2, m_receiveData);
	DDX_Text(pDX, IDC_EDIT3, m_sleepTime);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CCommDlg, CDialog)
	//{{AFX_MSG_MAP(CCommDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_DESTROY()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, OnSend)
	ON_BN_CLICKED(IDC_BUTTON2, OnReceive)
	ON_BN_CLICKED(IDC_BUTTON3, OnCommCfgDlg)
	ON_MESSAGE(WM_USERUPDATE,OnUserUpdate)
	ON_BN_CLICKED(IDC_BUTTON4, OnSleepTime)
	ON_BN_CLICKED(IDC_BUTTON5, OnRTSON)
	ON_BN_CLICKED(IDC_BUTTON6, OnRTSOFF)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCommDlg message handlers

BOOL CCommDlg::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
	
//////////////////////////////////////////////////////////////	
//打开COM2口
	hCom=CreateFile("COM1",GENERIC_READ|GENERIC_WRITE,//访问类型可读写
		0,//独占串口
		NULL,//无安全属性
		OPEN_EXISTING,//打开已存在的串口
		FILE_FLAG_OVERLAPPED,//异步串口
		NULL);//模块句柄为空

	if(hCom==INVALID_HANDLE_VALUE)	//检测打开是否成功。
	{
		dwError=GetLastError();
		MessageBox("Error");
	}
	SetupComm(hCom,1024,1024);	//设置接收,发送缓冲区各1024字节
	GetCommProperties(hCom,&CommProp);	//获取串口信息
	
	
////////////////定义串口//////////////////////////////////
//////获取DCB结构
	fSuccess=GetCommState(hCom,&dcb);
	if(!fSuccess)
		MessageBox("获取DCB结构错误!");
	
	//检测串口是否支持19200的波特率
	if(CommProp.dwSettableBaud&BAUD_19200)
		dcb.BaudRate=19200;		//定义19200的波特率
	dcb.ByteSize=8;			//定义串口的数据位数8
	dcb.Parity=NOPARITY;	//无奇偶校验
	dcb.StopBits=ONESTOPBIT;//一位停止位
	dcb.EvtChar=0x7e;		//定义当接收此字符时,产生一事件
	fSuccess=SetCommState(hCom,&dcb);//设置串口

	if(!fSuccess) //检测串口DCB结构设置是否正确
		MessageBox("DCB结构设置错误!");
	
//////////////////超时设定///////////////////////////////////
	GetCommTimeouts(hCom,&timeouts);
	timeouts.ReadIntervalTimeout=MAXDWORD;//读区间超时设定
	timeouts.ReadTotalTimeoutConstant=1000;
	timeouts.WriteTotalTimeoutConstant=1000;
	SetCommTimeouts(hCom,&timeouts);
//////////////////////////////////////////////////////////////
	
	m_sleepTime=t;
	UpdateData(FALSE);	
	OnReceive();
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CCommDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

void CCommDlg::OnDestroy()
{
	WinHelp(0L, HELP_QUIT);
	CDialog::OnDestroy();
}

// 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 CCommDlg::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 CCommDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

///////////////////////////////////////////////////////////////
////////////////TimeProc定时线程///////////////////////////////
/*UINT TimeProc(LPVOID param)
{
	::Sleep(5000);//延时0.5秒
	if(test==FALSE)
	{
		SetCommMask(hCom,0);	//取消读串口通讯等待事件
		PurgeComm(hCom,PURGE_RXCLEAR);
	}
	return 0;
}
*/
///////////////////ReadProc读线程///////////////////////
UINT ReadProc(LPVOID param)
{
	unsigned long nBytesRead;
	while(test)
	{
		//设置通信检测事件。检测到。
		SetCommMask(hCom,EV_RXCHAR);//EV_RXFLAG);
		
	//	AfxMessageBox("等待通信事件!");
		//检测通信事件。
		if(WaitCommEvent(hCom,&dwEvent,NULL))
		{
			::Sleep(t);
//		AfxMessageBox("准备读串口!");
			//获取缓冲区字节数。
			ClearCommError(hCom,&dwError,&cs);
			if(/*(dwEvent&EV_RXCHAR)&&*/cs.cbInQue)
			{
	//			AfxMessageBox("读串口!");
				//读串口
				if(!ReadFile(hCom,input,cs.cbInQue,
					&nBytesRead,NULL))
				{
	//				AfxMessageBox("读串口失败!");
					return 0;
				}
				else
				{	
	//				AfxMessageBox("读串口成功!");
					receiveData=CString(input,nBytesRead);
					char stest[2];
					sprintf(stest,"%d",nBytesRead);
//					AfxMessageBox(receiveData);
					::PostMessage(hWndUpdate,WM_USERUPDATE,0,0);
				}
			}
		}
		PurgeComm(hCom,PURGE_RXCLEAR);
	}
	return 1;
}

///////////////////////////////////////////////////////////////
void CCommDlg::OnSend() 
{
	// TODO: Add your control notification handler code here
	unsigned long nToWrite;
	UpdateData();
	PurgeComm(hCom,PURGE_TXCLEAR);//清发送缓冲区。
	PurgeComm(hCom,PURGE_RXCLEAR);//清接受缓冲区。	
	//::MessageBox((HWND)param,"正在写串口","写串口",MB_OK);
	WriteFile(hCom,m_sendData,m_sendData.GetLength(),&nToWrite,NULL);
	PurgeComm(hCom,PURGE_TXCLEAR);
	
}

void CCommDlg::OnReceive() 
{
	// TODO: Add your control notification handler code here
	//定义四个句柄,用于读线程,写线程,定时线程,反馈函数。
	HWND hWndread=GetSafeHwnd();
//	HWND hWndTime=GetSafeHwnd();
	hWndUpdate=GetSafeHwnd();
	//test=FALSE;
	//启动读线程.
	AfxBeginThread(ReadProc,hWndread,THREAD_PRIORITY_NORMAL);
	//启动定时线程.
//	AfxBeginThread(TimeProc,hWndTime,THREAD_PRIORITY_NORMAL);
}

//OnUserUpDate 处理反馈信息
LONG CCommDlg::OnUserUpdate(WPARAM wParam,LPARAM lParam)
{
	//等待读线程完毕,或超出定时。
	m_receiveData=receiveData;
	UpdateData(FALSE);
	return 0;
}

void CCommDlg::OnCommCfgDlg() 
{
	// TODO: Add your control notification handler code here
	COMMCONFIG cc;
	cc.dcb=dcb;
	if(!CommConfigDialog("com2",GetSafeHwnd(),&cc))
		return;
	dcb=cc.dcb;
	SetCommState(hCom,&dcb);
}


void CCommDlg::OnSleepTime() 
{
	// TODO: Add your control notification handler code here
	UpdateData();
	t=m_sleepTime;
}

void CCommDlg::OnRTSON() 
{
	// TODO: Add your control notification handler code here
	/*
	CLRDTR		DTR置OFF
	CLRRTS		RTS置OFF
	SETDTR		DTR置ON
	SETRTS		RTS置ON
	SETXOFF		模拟XOFF字符的接收
	SETXON		模拟XON字符的接收
	SETBREAK	在发送中产生一个中止(与SetCommBreak)
	CLRBREAK	在发送中清除中止(与ClearCommBreak)
	*/
	EscapeCommFunction(hCom,SETRTS);
}

void CCommDlg::OnRTSOFF() 
{
	// TODO: Add your control notification handler code here
	EscapeCommFunction(hCom,CLRRTS);	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -