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

📄 sl_plcview.cpp

📁 一个不错的PLC通讯程序,可以方便地实现远程监控,现场总线监控.
💻 CPP
字号:
// SL_PLCView.cpp : implementation of the CSL_PLCView class
//

#include "stdafx.h"
#include "SL_PLC.h"

#include "SL_PLCDoc.h"
#include "SL_PLCView.h"
#include "hex2a.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

const short   STX_start    =0x02;
const short   ETX_end	   =0x03;
const short   ENQ_request  =0x05;
const short   ACK_reply    =0x06;
const short   CMD0_read	   =0x30;
const short   CMD1_write   =0x31;
const short   CMD7_ForceON =0x37;
const short   CMD8_ForceOFF=0x38;



BOOL   volatile  g_bContinue=FALSE;


/////////////////////////////////////////////////////////////////////////////
// CSL_PLCView

IMPLEMENT_DYNCREATE(CSL_PLCView, CFormView)

BEGIN_MESSAGE_MAP(CSL_PLCView, CFormView)
//{{AFX_MSG_MAP(CSL_PLCView)
ON_BN_CLICKED(IDC_START, OnStart)
ON_BN_CLICKED(IDC_READPLC, OnReadPlc)
ON_BN_CLICKED(IDC_WRITEPLC, OnWritePlc)
ON_BN_CLICKED(IDC_CLOSE_COM, OnCloseCom)
ON_BN_CLICKED(IDC_ON, OnOn)
ON_BN_CLICKED(IDC_OFF, OnOff)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview)
END_MESSAGE_MAP()

/*BEGIN_EVENTSINK_MAP(CSL_PLCView, CView)
//{{AFX_EVENTSINK_MAP(CWaterCut1View)
ON_EVENT(CSL_PLCView, ID_CTRCOMM, 1 , ReadFromPLC, VTS_NONE)
//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()
*/

/////////////////////////////////////////////////////////////////////////////
// CSL_PLCView construction/destruction
CSL_PLCView * pView=NULL;
UINT ThreadForceOn(LPVOID  lparam)
{
/*  pView=(CSL_PLCView *)lparam;
int i;
char sum_Check[2];
char read_buffer;
int  Sum=0;
int  Sum_Check=0;
char ON_Address[]={0x30,0x30,0x38,0x30};

  pView->m_com.SetOutput(COleVariant((CString)ENQ_request));//向PLC发送ENQ请求
  while(g_bContinue==FALSE)
  Sleep(500);
  
	if(pView->m_data[0]!=ACK_reply) return 0 ;
	
	  // g_bContinue=FALSE;
	  
		pView->m_com.SetOutput(COleVariant((CString)STX_start));
		pView->m_com.SetOutput(COleVariant((CString)CMD7_ForceON));
		Sum+=1;//CMD7_ForceON;
		for(i=0;i<4;i++)
		{
		pView->m_com.SetOutput(COleVariant((CString)ON_Address[i]));
		//发送起始元地址的ASCII代码
		//Sum+=ON_Address[i];
		Sum++;
		}
		pView->m_com.SetOutput(COleVariant(ETX_end));//发送"结束"标志代码
		//Sum+=ETX_end;
		Sum+=1;
		
		  //changetoASCII(Sum_Check,Sum); //将“和”转化成ASCII代码
		  Sum_Check=HexToASCII(Sum);
		  pView->m_com.SetOutput(COleVariant((CString)54));//Sum_Check));
		  
			Sleep(1000);//等待PLC响应
			
			  //Serial.ReadData(&read_buffer,1);
			  //ReadFromPLC();
			  if(pView->m_data[0]==ACK_reply)//read_BUFFER==ACK_reply)
			  {
			  AfxMessageBox("ON 操作 OK!");
			  }
			  else
			  {
			  AfxMessageBox("ON 操作失败!");
			  }
	*/
	return 1;
}
CSL_PLCView::CSL_PLCView()
: CFormView(CSL_PLCView::IDD)
{
	//{{AFX_DATA_INIT(CSL_PLCView)
	// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// TODO: add construction code here
	m_bCreated=FALSE;
	
	
}

CSL_PLCView::~CSL_PLCView()
{
}

void CSL_PLCView::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CSL_PLCView)
	DDX_Control(pDX, IDC_GEAR1, m_ctrGear1);
	//}}AFX_DATA_MAP
}

BOOL CSL_PLCView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs
	
	return CFormView::PreCreateWindow(cs);
}

void CSL_PLCView::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();
	GetParentFrame()->RecalcLayout();
	ResizeParentToFit();
	
}

/////////////////////////////////////////////////////////////////////////////
// CSL_PLCView printing

BOOL CSL_PLCView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CSL_PLCView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CSL_PLCView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

void CSL_PLCView::OnPrint(CDC* pDC, CPrintInfo* /*pInfo*/)
{
	// TODO: add customized printing code here	
}

/////////////////////////////////////////////////////////////////////////////
// CSL_PLCView diagnostics

#ifdef _DEBUG
void CSL_PLCView::AssertValid() const
{
	CFormView::AssertValid();
}

void CSL_PLCView::Dump(CDumpContext& dc) const
{
	CFormView::Dump(dc);
}

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

/////////////////////////////////////////////////////////////////////////////
// CSL_PLCView message handlers

void CSL_PLCView::OnStart() 
{
	// TODO: Add your control notification handler code here
	if (m_ctrGear1.Load(MAKEINTRESOURCE(IDR_GEAR1),_T("GIF")))
		m_ctrGear1.Draw();
}

void CSL_PLCView::InitComm(int port)
{
	if(m_bCreated==FALSE)
	{
		WCHAR pwchLicenseKey[] =
		{
			0x0043,	0x006F,	0x0070,	0x0079,	0x0072,	0x0069,	
				0x0067,	0x0068,	0x0074,	0x0020,	0x0028,	0x0063,	
				0x0029,	0x0020,	0x0031,	0x0039,	0x0039,	0x0034,	
				0x0020
		};
		BSTR bstrLicense = ::SysAllocStringLen(pwchLicenseKey,
			sizeof(pwchLicenseKey)/sizeof(WCHAR));
		m_com.Create(NULL,WS_VISIBLE, CRect(10,10,10,10),this,
			ID_CTRCOMM, NULL, FALSE, bstrLicense);
		::SysFreeString(bstrLicense); 
		m_bCreated=TRUE;
	}
    if(!m_com.GetPortOpen())
	{
		m_com.SetCommPort(port);
		m_com.SetSettings("9600,e,7,1");//e-偶校验 7-数据位  1个停止位	
		m_com.SetInBufferSize(1024);		
		m_com.SetOutBufferSize(512);		
		m_com.SetInBufferCount(0);		
		m_com.SetInputMode(1);		
		m_com.SetInputLen(0);
		m_com.SetRThreshold(1);
		m_com.SetPortOpen(TRUE);
	}
	
}
char CSL_PLCView::HexChar(char c)//检测一个字符是不是十六进制字符,若是返回相应的值,否则返回0x10;
{
	if((c>='0')&&(c<='9'))
		return c-0x30;
	else if((c>='A')&&(c<='F'))
		return c-'A'+10;
	else if((c>='a')&&(c<='f'))
		return c-'a'+10;
	else return 0x10;
}

void  CSL_PLCView::ReadFromPLC()
{
	VARIANT m_input1;
	COleSafeArray m_input2;
	long length=0;
	CString str,str1;
	str1.Empty();
    memset(m_data,205,2);
	//	if(m_com.GetCommEvent()==2)
	{
		m_input1=m_com.GetInput();
		m_input2=m_input1;
		length=m_input2.GetOneDimSize();
		if (length==0) return;
		for(long i=0;i<length;i++)
			m_input2.GetElement(&i,m_data+i);
		m_com.SetInBufferCount(0);//清空接收缓冲区
		g_bContinue=TRUE;
	}
	//	return length;
}

void CSL_PLCView::SendForReadPLC()
{
	
	int  i;
	char senddatasum_CHECK[2];
	char readdatasum_CHECK[2];
	char total_BYTES[2]={0x31,0x32};
	char readdatasum_check[2];
	char m_readAddress[4]={0x30,0x30,0x38,0x30};

	int readdata_sum=0;
	int datasum_check=0;
	
	int read_bytes=0;
	int totalDATABYTES=0;
	
	InitComm(1);//OPEN COM1
	
	m_com.SetOutput(COleVariant((CString)ENQ_request));//向PLC发送ENQ请求
	Sleep(1000);
    if(m_data[0]!=ACK_reply) return ;
	
	m_com.SetOutput(COleVariant((CString)STX_start));//向PLC发送“开始”标志代码
	m_com.SetOutput(COleVariant((CString)CMD0_read));//发送“读”命令代码datasum_check+=CMD0_read
	for(i=0;i<4;i++)
	{
		m_com.SetOutput(COleVariant((CString)m_readAddress[i]));
		//发送起始元地址的ASCII代码
		datasum_check+=m_readAddress[i];
	}
	totalDATABYTES=HexToASCII(read_bytes);//将字节数转化成ascii代码
	
	for(i=0;i<2;i++)
	{
		//发送元件字节数的ASCII代码
		m_com.SetOutput(COleVariant((CString)total_BYTES[i]));
		datasum_check+=total_BYTES[i];
	}
	
	m_com.SetOutput(COleVariant((CString)ETX_end));
	datasum_check+=ETX_end;//注意  datasum_check
	
	//changetoASCII(senddatasum_CHECK,senddatasum_CHECK);//将字节数转化成ascii代码
	//  senddatasum_CHECK=HexToASCII(&senddatasum_CHECK);
	//将“和”转化成ASCII代码
	for(i=0;i<2;i++)
	{
		m_com.SetOutput(COleVariant((CString)senddatasum_CHECK[i]));
	}
	
	Sleep(1000);//等待PLC响应
	
	//Serial.ReadData(&read_BUFFER,1); wsf  
	//wsf	read_bytes=ReadFromPLC();//可注释掉,因是事件驱动
	
	if(m_data[0]==STX_start)
	{
		readdata_sum=0;
		for(i=0;i<2*read_bytes;i++)
		{
			//	Serial.ReadData(Read_char[i],1);//读read_bytes个字节
            //ReadFromPLC();
			readdata_sum+=m_data[i];//Read_char[i];
		}
		//	serial.ReadData(&read_BUFFER,1);
        ReadFromPLC();
		if(m_data[0]==ETX_end)//read_BUFFER==ETX_end
		{
			//	Serial.ReadData(readdatasum_CHECK,2);//读入得“和”的低2位ASCII码
            ReadFromPLC();
			readdata_sum+=ETX_end;
		}
		//changetoASCII(readdatasum_check,readdata_sum);//将字节数转化成ascii代码
		//		readdatasum_check=HexToASCII(readdata_sum);
		//将计算得到的“和”转化位ascii码
		if(*readdatasum_CHECK==*readdatasum_check)//“和”校验
		{
			AfxMessageBox("数据读出成功!");
		}
		else
		{
			AfxMessageBox("校验错误!");
		}
	}
	
}

void CSL_PLCView::SendForWritePLC()
{
	char    m_dataAddress[]={0x30,0x30,0x38,0x30};
	int  i=0,uTmp1;
	char total_BYTES[2]={0x31,0x32};
    char sum_Check[2]={0x30,0x30};
	
	int sumCheck=0;
	int bytesnumber=0;
	int total_DATABYTES=0;

	char   Write_ASC[]={0x01,0x00,0x00,0x00,0x00,0X00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

	InitComm(1);//OPEN COM1
	
	m_com.SetOutput(COleVariant((CString)ENQ_request));//向PLC发送ENQ请求
	g_bContinue=FALSE;
	int nTimers=0;
	while(g_bContinue==FALSE)
	{  
		ReadFromPLC();
		Sleep(500);
		nTimers++;
		if(nTimers==5 && g_bContinue==FALSE)return;
	}

    if(m_data[0]!=ACK_reply)  return ;
		
	m_com.SetOutput(COleVariant((CString)STX_start));//向PLC发送“开始”标志代码
	sumCheck=0;
	m_com.SetOutput(COleVariant((CString)CMD1_write));//发送“读”命令代码datasum_check+=CMD0_read
	sumCheck+=CMD1_write;
	for(i=0;i<4;i++)
	{
		m_com.SetOutput(COleVariant((CString)m_dataAddress[i]));
		//发送起始元地址的ASCII代码
		sumCheck+=m_dataAddress[i];
	}
	total_DATABYTES=HexToASCII(sumCheck);

	for(i=0;i<2;i++)
	{
		//发送元件字节数的ASCII代码
		m_com.SetOutput(COleVariant((CString)total_BYTES[i]));
		sumCheck+=total_BYTES[i];
	}

	for(i=0;i<bytesnumber*2;i++)
	{
		//发送要写入的数据的ASCII码
		m_com.SetOutput(COleVariant((CString)Write_ASC[i]));
		sumCheck+=Write_ASC[i];
	}
	
	m_com.SetOutput(COleVariant((CString)ETX_end));//发送"结束"标志代码
	sumCheck+=ETX_end;
	
	//将“和”转化成ASCII代码
    uTmp1=sumCheck & 0x0f;
    sum_Check[1]=HexToASCII(uTmp1);//2-0x32;
    uTmp1=(sumCheck>>4) & 0x0f;
    sum_Check[0]=HexToASCII(uTmp1);
	
	for(i=0;i<2;i++)
		m_com.SetOutput(COleVariant((CString)sum_Check[i]));
	
	g_bContinue=FALSE;
	nTimers=0;
	while(g_bContinue==FALSE)
	{  
		ReadFromPLC();
		Sleep(500);
		nTimers++;
		if(nTimers==5 && g_bContinue==FALSE)return;
	}
	
	//Serial.ReadData(&read_finishBUFFER,1);
	if(m_data[0]==ACK_reply)
	{
		AfxMessageBox("写入数据成功!");
	}
	else
	{
		AfxMessageBox("写入数据失败!");
	}
}


void CSL_PLCView::ForceOnOperation(char * ON_Address)
{
	int i;
	char sum_Check[2]={0x30,0x30};
	int  Sum=0,uTmp1;
	int  Sum_Check=0;
	int  nTimers=0;
   	
	InitComm(1);
	m_com.SetOutput(COleVariant((CString)ENQ_request));//向PLC发送ENQ请求
    while(g_bContinue==FALSE)
	{  
		ReadFromPLC();
		Sleep(500);
		nTimers++;
		if(nTimers==5 && g_bContinue==FALSE)return;
	}
	if(m_data[0]!=ACK_reply) 
		return ;
	g_bContinue=FALSE;
	m_com.SetOutput(COleVariant((CString)STX_start));
	m_com.SetOutput(COleVariant((CString)CMD7_ForceON));
	Sum+=CMD7_ForceON;
	for(i=0;i<4;i++)
	{
		m_com.SetOutput(COleVariant((CString)ON_Address[i]));
		//发送起始元地址的ASCII代码
		Sum+=ON_Address[i];
	}
	m_com.SetOutput(COleVariant((CString)ETX_end));//发送"结束"标志代码
	Sum+=ETX_end;
	
	//changetoASCII(Sum_Check,Sum); //将“和”转化成ASCII代码
    uTmp1=Sum & 0x0f;
    sum_Check[1]=HexToASCII(uTmp1);//2-0x32;
    uTmp1=(Sum>>4) & 0x0f;
    sum_Check[0]=HexToASCII(uTmp1);//0x30;//
	
	for(i=0;i<2;i++)
		m_com.SetOutput(COleVariant((CString)sum_Check[i]));//Sum_Check));
	
	g_bContinue=FALSE;
    
	nTimers=0;
    while(g_bContinue==FALSE)
	{  
		ReadFromPLC();
		Sleep(500);
		nTimers++;
		if(nTimers==5 && g_bContinue==FALSE)return;
	}
	
	if(m_data[0]==ACK_reply)//read_BUFFER==ACK_reply)
	{
		AfxMessageBox("ON 操作 OK!");
	}
	else
	{
		AfxMessageBox("ON 操作失败!");
	}
}

void CSL_PLCView::ForceOffOperation(char *OFF_Address)
{
	int i;
	char sum_Check[2];
	int  Sum=0,uTmp1;
	InitComm(1);
	
	m_com.SetOutput(COleVariant((CString)ENQ_request));//向PLC发送ENQ请求
	
	g_bContinue=FALSE;
    int nTimers=0;
    while(g_bContinue==FALSE)
	{  
		ReadFromPLC();
		Sleep(500);
		nTimers++;
		if(nTimers==5 && g_bContinue==FALSE)return;

	}
	if(m_data[0]!=ACK_reply)  return ;
	
	m_com.SetOutput(COleVariant((CString)STX_start));
	m_com.SetOutput(COleVariant((CString)CMD8_ForceOFF));
	Sum+=CMD8_ForceOFF;
	for(i=0;i<4;i++)
	{
		m_com.SetOutput(COleVariant((CString)OFF_Address[i]));	//发送起始元地址的ASCII代码
		
		Sum+=OFF_Address[i];
	}
	m_com.SetOutput(COleVariant((CString)ETX_end));//发送"结束"标志代码
	Sum+=ETX_end;
	
	//changetoASCII(Sum_Check,Sum); //将“和”转化成ASCII代码
    uTmp1=Sum & 0x0f;
    sum_Check[1]=HexToASCII(uTmp1);//2-0x32;
    uTmp1=(Sum>>4) & 0x0f;
    sum_Check[0]=HexToASCII(uTmp1);//0x30;/
	for(i=0;i<2;i++)
		m_com.SetOutput(COleVariant((CString)sum_Check[i]));//Sum_Check));
	
	g_bContinue=FALSE;
	nTimers=0;
	while(g_bContinue==FALSE)
	{  
		ReadFromPLC();
		Sleep(500);
		nTimers++;
		if(nTimers==5 && g_bContinue==FALSE)return;
	}
	
	if(m_data[0]==ACK_reply)//read_BUFFER==ACK_reply)
	{
		AfxMessageBox("OFF 操作 OK!");
	}
	else
	{
		AfxMessageBox("OFF 操作失败!");
	}
}

void CSL_PLCView::OnReadPlc() 
{
	// TODO: Add your control notification handler code here
	SendForReadPLC();
}


void CSL_PLCView::OnWritePlc() 
{
	// TODO: Add your control notification handler code here
	SendForWritePLC();
	
}

void CSL_PLCView::OnCloseCom() 
{
	// TODO: Add your control notification handler code here
	if(m_bCreated==FALSE)  return;
	
	if(m_com.GetPortOpen())
	{
		m_com.SetPortOpen(FALSE);
	}
}


void CSL_PLCView::OnOn() 
{
	// TODO: Add your control notification handler code here
	
	char address[]={0x30,0x30,0x38,0x30};
	ForceOnOperation(address);//X0
	//	
	//	AfxBeginThread( ThreadForceOn,this,THREAD_PRIORITY_NORMAL);
}

void CSL_PLCView::OnOff() 
{
	// TODO: Add your control notification handler code here
	char address[]={0x30,0x30,0x38,0x30};
	
	ForceOffOperation(address);//X0
}




⌨️ 快捷键说明

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