📄 pc2plcview.cpp
字号:
// 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 + -