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

📄 pc2plcview.cpp

📁 本程序主要通过VC实现计算机与西门子S7-200间的串口通讯。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// PC2PLCView.cpp : implementation of the CPC2PLCView class
//

#include "stdafx.h"
#include "PC2PLC.h"

#include "PC2PLCDoc.h"
#include "PC2PLCView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//定义全局变量
HANDLE hCom;                               //串口句柄
DWORD ThreadProcWrite(LPVOID pParam);      //写线程函数
DWORD ThreadProcRead(LPVOID pParam);       //读线程函数
OVERLAPPED Wol={0};                        //写操作OVERLAPPED结构变量
OVERLAPPED Rol={0};                        //读操作OVERLAPPED结构变量
HANDLE hThreadWrite;                       //写线程句柄
HANDLE hThreadRead;                        //读线程句柄
HWND hWnd;                                 //窗口句柄

BYTE myRByte[300];                         //存放已读数据
BYTE myWByte[300];                         //存放欲写数据
 
long dataRLen;                             //接收数据的长度
long dataWLen;                             //发送数据的长度

bool blnError;                             //错误标志,在接收命令代码中使用
int	intWrite=0;                            //反映写操作的状态,0-无意义,1-写错误,2-写正确
int intRead=0;                             //反映读操作的状态,0-无意义,1-读错误,2-读正确


/////////////////////////////////////////////////////////////////////////////
// CPC2PLCView

IMPLEMENT_DYNCREATE(CPC2PLCView, CEditView)

BEGIN_MESSAGE_MAP(CPC2PLCView, CEditView)
	//{{AFX_MSG_MAP(CPC2PLCView)
	ON_COMMAND(ID_SETUP, OnSetup)
	ON_COMMAND(ID_RECEIVE, OnReceive)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_UPDATE_COMMAND_UI(ID_RECEIVE, OnUpdateReceive)
	ON_COMMAND(ID_OPENCOM, OnOpencom)
	ON_UPDATE_COMMAND_UI(ID_SETUP, OnUpdateSetup)
	ON_UPDATE_COMMAND_UI(ID_OPENCOM, OnUpdateOpencom)
	ON_UPDATE_COMMAND_UI(ID_CLOSECOM, OnUpdateClosecom)
	ON_COMMAND(ID_CLOSECOM, OnClosecom)
	ON_UPDATE_COMMAND_UI(ID_APP_EXIT, OnUpdateAppExit)
	ON_WM_CHAR()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPC2PLCView construction/destruction

CPC2PLCView::CPC2PLCView()
{
	// TODO: add construction code here
	myCom="COM4";                      //默认设置
	myBaudRate=CBR_4800;
	myfParity=false;
	myParity=NOPARITY;

}

CPC2PLCView::~CPC2PLCView()
{
}

BOOL CPC2PLCView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	BOOL bPreCreated = CEditView::PreCreateWindow(cs);
	cs.style &= ~(ES_AUTOHSCROLL|WS_HSCROLL);	// Enable word-wrapping


	return bPreCreated;
}

/////////////////////////////////////////////////////////////////////////////
// CPC2PLCView drawing

void CPC2PLCView::OnDraw(CDC* pDC)
{
	CPC2PLCDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
}

/////////////////////////////////////////////////////////////////////////////
// CPC2PLCView diagnostics

#ifdef _DEBUG
void CPC2PLCView::AssertValid() const
{
	CEditView::AssertValid();
}

void CPC2PLCView::Dump(CDumpContext& dc) const
{
	CEditView::Dump(dc);
}

CPC2PLCDoc* CPC2PLCView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPC2PLCDoc)));
	return (CPC2PLCDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CPC2PLCView message handlers

void CPC2PLCView::OnSetup() 
{
	// TODO: Add your command handler code here
	CString strStatus;
	if(mySetupDlg.DoModal()==IDOK)
	{
		switch (mySetupDlg.m_Com)
		{
		case 0:
			{
			strStatus="COM1";
			strStatus+="  ";
			myCom="COM1";
			break;
			}
		case 1:
			{
			strStatus="COM2";
			strStatus+="  ";
			myCom="COM2";
			break;
			}

		case 2:
			{
			strStatus="COM3";
			strStatus+="  ";
			myCom="COM3";
			break;
			}

		case 3:
			{
			strStatus="COM4";
			strStatus+="  ";
			myCom="COM4";
			break;
			}

		case 4:
			{
			strStatus="COM5";
			strStatus+="  ";
			myCom="COM5";
			}
			break;
		case 5:
			{
			strStatus="COM6";
			strStatus+="  ";
			myCom="COM6";
			}
			break;
		}
		switch(mySetupDlg.m_BaudRate)
		{

		case 0:
			{
			strStatus+="19200";
			strStatus+="  ";
			myBaudRate=CBR_19200;
			break;
			}
		case 1:
			{
			strStatus+="9600";
			strStatus+="  ";
			myBaudRate=CBR_9600;
			break;
			}
		case 2:
			{
			strStatus+="4800";
			strStatus+="  ";
			myBaudRate=CBR_4800;
			break;
			}
		case 3:
			{
			strStatus+="2400";
			strStatus+="  ";
			myBaudRate=CBR_2400;
			break;
			}
		}
		switch(mySetupDlg.m_Parity)
		{
		case 0:
			{
			myfParity=false;
			myParity=NOPARITY;
			strStatus+="N";
			strStatus+="-8-1";
			break;
			}
		case 1:
			{
			myfParity=TRUE;
			myParity=ODDPARITY;
			strStatus+="O";
			strStatus+="-8-1";
			break;
			}
		case 2:
			{
			myfParity=true;
			myParity=EVENPARITY;
			strStatus+="E";
			strStatus+="-8-1";
			break;
			}
		}

		CMainFrame* m_pGetFrame=(CMainFrame*) AfxGetApp()->m_pMainWnd ;
		CStatusBar* m_pStatus=&m_pGetFrame->m_wndStatusBar;
		m_pStatus->SetPaneText(1,strStatus);            //将通信参数显示在状态条上
		
	}
}
//*******************************************
//***接收操作代码*************************
//********************************************
void CPC2PLCView::OnReceive() 
{
	// TODO: Add your command handler code here
	int i,j;
	CString strDis,strTemp;
	char myChar[20];
	BYTE xorByte;                                     //存放奇偶校验和
	PurgeComm(hCom,PURGE_RXCLEAR);                    //清空接收和发送缓冲区
	PurgeComm(hCom,PURGE_TXCLEAR);
	myWByte[0]=5;
	dataWLen=1;
	CEdit& myEdit=this->GetEditCtrl( );
	myEdit.SetSel(1000000,1000000);

	strDis="";
	strDis+="<-- [ENQ] ";
	_strdate(myChar);
	strDis+=myChar;
	strDis+=" ";
	_strtime(myChar);
	strDis+=myChar;
	strDis+="\15\12";
	myEdit.ReplaceSel(strDis);
	intWrite=0;
	if (!myfuncWrite())                              //发出ENQ读数据请求
	{
		myEdit.SetSel(1000000,1000000);
		strDis="";
		strDis+="   通信错误\15\12\15\12";
		myEdit.ReplaceSel(strDis);
		Beep(1000,50);
		return;
	}

	dataRLen=3;
	intRead=0;
	if(myfuncRead(5))                                //读数据,应该为“ACK,长度,长度取反值”
	{
		strDis="--> ";
		for(i=0;i<=2;i++)
		{
			strTemp.Format("%02X",myRByte[i]);      //将16进制数格式化为2位形式
			strDis+=strTemp;
			strDis+="|";
		}
		myEdit.SetSel(1000000,1000000);
		strDis+="\15\12";
		strDis.MakeUpper();
		myEdit.ReplaceSel(strDis);                 //显示接收到的数据

	}
	else//若出错,说明通信故障,退出此次读数据操作
	{
		blnError=true;
		myEdit.SetSel(1000000,1000000);
		strDis="";
		strDis+="   通信错误\15\12\15\12";
		myEdit.ReplaceSel(strDis);
		Beep(1000,50);
		return;
	}
	for(i=0;i<3;i++)                               //对数据进行3次校验
	{
		if((myRByte[0]==6) && ((myRByte[1]+myRByte[2])==255))
		{
			blnError=false;
			break;
		}
		else
		{
			blnError=true;
		}
		myWByte[0]=21;
		dataWLen=1;
		intWrite=0;
		myEdit.SetSel(1000000,1000000);
		strDis="";
		strDis+="<-- [NAK]\15\12";
		myEdit.ReplaceSel(strDis);
		if(!myfuncWrite())                        //若校验未通过,则回应NAK,要求重发
		{
			blnError=true;
			break;
		}
		dataRLen=3;
		intRead=0;
		if(myfuncRead(21))//再次读取数据,应该为“ACK,长度,长度取反值”
		{
			strDis="--> ";
			strTemp.Format("%02X",myRByte[0]);
			strDis+=strTemp;
			strDis+="|";
			strTemp.Format("%02X",myRByte[1]);
			strDis+=strTemp;
			strDis+="|";
			strTemp.Format("%02X",myRByte[2]);
			strDis+=strTemp;
			myEdit.SetSel(1000000,1000000);
			strDis+="\15\12";
			strDis.MakeUpper();
			myEdit.ReplaceSel(strDis);//
		}
		else
		{
			blnError=true;
			myEdit.SetSel(1000000,1000000);
			strDis="";
			strDis+="   通信错误\15\12\15\12";
			strDis.MakeUpper();
			myEdit.ReplaceSel(strDis);
			Beep(1000,50);
			return;
		}

	}


	if (blnError)//若出错,说明通信存在故障,则退出本次操作
	{
		myEdit.SetSel(1000000,1000000);
		strDis="";
		strDis+="   通信错误\15\12\15\12";
		strDis.MakeUpper();
		myEdit.ReplaceSel(strDis);
		Beep(1000,50);
		blnError=false;
		return;
	}
	//正常通信,继续进行
	myWByte[0]=6;                                 //收到长度及其取反值,且校验正确,回应ACK
	dataWLen=1;
	myEdit.SetSel(1000000,1000000);
	strDis="";
	strDis+="<-- [ACK]\15\12";
	strDis.MakeUpper();
	myEdit.ReplaceSel(strDis);
	intWrite=0;
	if (!myfuncWrite())
	{
		myEdit.SetSel(1000000,1000000);
		strDis="";
		strDis+="   通信错误\15\12\15\12";
		strDis.MakeUpper();
		myEdit.ReplaceSel(strDis);
		Beep(1000,50);
		return;
	}

	//回应ACK成功,等待接收数据
	dataRLen=myRByte[1]+1;
	for(i=0;i<3;i++)                            //若1次未读出正确数据,则重新操作,共循环3次
	{
		intRead=0;
		if(myfuncRead(21))
		{

			strDis="--> ";
			xorByte=0;
			for(j=0;j<=dataRLen-2;j++)
			{
				strTemp.Format("%02X",myRByte[j]);
				strDis+=strTemp;
				strDis+="|";
				xorByte^=myRByte[j];
			}
			strTemp.Format("%02X",myRByte[dataRLen-1]);
			strDis+=strTemp;
			myEdit.SetSel(1000000,1000000);
			strDis+="\15\12";
			strDis.MakeUpper();
			myEdit.ReplaceSel(strDis);         //显示接收到的数据

			if(myRByte[dataRLen-1]==xorByte)   //校验数据
			{
				
				blnError=false;
				break;
			}
			else
			{
				blnError=true;
			}
		}
		else
		{
			blnError=true;
			break;
		}
		myWByte[0]=21;
		dataWLen=1;
		intWrite=0;
		myEdit.SetSel(1000000,1000000);
		strDis="";
		strDis+="<-- [NAK]\15\12";
		strDis.MakeUpper();
		myEdit.ReplaceSel(strDis);
		if(!myfuncWrite())                    //数据校验出错,响应NAK,要求重发

⌨️ 快捷键说明

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