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

📄 examviewview.cpp

📁 一个很好的串口程序,利用modbus协议来写的,对很多人可能会有帮助.
💻 CPP
字号:
// examviewView.cpp : implementation of the CExamviewView class
//

#include "stdafx.h"
#include "examview.h"

#include "examviewDoc.h"
#include "examviewView.h"

#include "ComSetSheet.h"
#include "ComSetDlg.h"

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

#define CHECKVALUE(pt,nl)	if((btData==NULL)||(nLength<=0)){AfxMessageBox("无效数组!");return -1;}
/////////////////////////////////////////////////////////////////////////////
// CExamviewView

//CComSetSheet m_ComSetSheet("多路温度仪");//参数是指显示标题
IMPLEMENT_DYNCREATE(CExamviewView, CFormView)

BEGIN_MESSAGE_MAP(CExamviewView, CFormView)
	//{{AFX_MSG_MAP(CExamviewView)
	ON_WM_CREATE()
	ON_COMMAND(ID_FILE_EXPORT, OnFileExport)
	ON_COMMAND(ID_FILE_IMPORT, OnFileImport)
	ON_COMMAND(IDM_COM_SETUP, OnComSetup)
	ON_COMMAND(IDM_COM_OPEN, OnComOpen)
	ON_COMMAND(IDM_COM_CLOSE, OnComClose)
	ON_WM_TIMER()
	ON_COMMAND(IDM_COM_READ, OnComRead)
	//}}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()

/////////////////////////////////////////////////////////////////////////////
// CExamviewView construction/destruction

CExamviewView::CExamviewView()
	: CFormView(CExamviewView::IDD)
{
	//{{AFX_DATA_INIT(CExamviewView)
	m_bTune1 = FALSE;
	m_bTune2 = FALSE;
	m_bTune4 = FALSE;
	m_bTune3 = FALSE;
	//}}AFX_DATA_INIT
	// TODO: add construction code here

}

CExamviewView::~CExamviewView()
{
}

void CExamviewView::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CExamviewView)
	DDX_Control(pDX, IDC_MSCOMM1, m_MSComm);
	DDX_Check(pDX, IDC_TUNE1, m_bTune1);
	DDX_Check(pDX, IDC_TUNE2, m_bTune2);
	DDX_Check(pDX, IDC_TUNE4, m_bTune4);
	DDX_Check(pDX, IDC_TUNE3, m_bTune3);
	//}}AFX_DATA_MAP
}

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

	return CFormView::PreCreateWindow(cs);
}

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

}

/////////////////////////////////////////////////////////////////////////////
// CExamviewView printing

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

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

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

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

/////////////////////////////////////////////////////////////////////////////
// CExamviewView diagnostics

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

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

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

/////////////////////////////////////////////////////////////////////////////
// CExamviewView message handlers

BEGIN_EVENTSINK_MAP(CExamviewView, CFormView)
    //{{AFX_EVENTSINK_MAP(CExamviewView)
	ON_EVENT(CExamviewView, IDC_MSCOMM1, 1 /* OnComm */, OnComm, VTS_NONE)
	//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()

void CExamviewView::OnComm() //OnComm的编写是主要的问题
{
	// TODO: Add your control notification handler code here
//	if(stop)return;
	VARIANT variant_inp;
	COleSafeArray safearray_inp;
	long length,i;
	BYTE data[4096];
	CString strtemp;
	CString strDisp;
	int nEvent=m_MSComm.GetCommEvent();
	int k;
	switch (nEvent)
//接收缓冲区内有字符
	{
	case 2:
		k=m_MSComm.GetInBufferCount();
		if(k>0)
		{
		variant_inp=m_MSComm.GetInput();//读取缓冲区内的数据
		safearray_inp=variant_inp;//将VARIANT型变量转换为ColeSafeArray型变量
		length=safearray_inp.GetOneDimSize();//确定数据长度
		for(i=0;i<length;i++)
		safearray_inp.GetElement(&i,data+i);//将数据转换为BYTE型数组
		for(i=0;i<length;i++)
		{
			BYTE bt=*(char*)(data+i);//字符型
			strtemp.Format("%02X",bt);//将字符送入临时变量strtemp存放
			strDisp+=strtemp;//加入接收编辑框对应字符串
		}
		CString w;
		w.Format("%d",k);
		MessageBox(w);
		CDC* pDC=GetDC();
		pDC->TextOut(200,100,"Com1接收到"+strDisp);
		ReleaseDC(pDC);


//		strtemp.Format("OK,'%s' Received",strDisp);
//		m_MSComm.SetOutput(COleVariant(SendData));//发送数据
		
		}
		break;
		
				
										
												
											
/*此例是温度采集程序的例子
			CFile file;//将数组转换为Cstring型变量
			CString tempstr;
			BYTE a=* (char *)(data+i);
			BYTE b=* (char *)(data+(++i));
			float c=(float)a+(float)(b%10)/10;
			strtemp.Format("%2.1f ",c);//将a格式化
			if (strtemp.GetLength()<5) strtemp="0"+strtemp;
			strtemp = strtemp.Right(5);
			m_ReceiveData+=strtemp;//将刚采集的数加到编辑框中
			LineHight[121]=a;
			Display();//对数据显示前的处理
			//将数据保存到文件中
			if (m_ReceiveData.GetLength()>=600)//600个字符刚好对应120个数据
			{
				CStdioFile readfile; 
				CString readstr,readstr2;
				if(readfile.Open(FilePath,CFile::modeRead))
				{
					while(readfile.ReadString(readstr))//逐行查询,至到文件尾
					{
						readstr2+=readstr;
					}
					readfile.Close();
				}

				if (file.Open(FilePath,CFile::modeCreate|CFile::modeReadWrite))
				{
					file.Write(readstr2,readstr2.GetLength());//原来的数据
 					file.Write(m_ReceiveData,600);//写入新的120个数据
					file.Close();
					m_ReceiveData="";//清除编辑框内容
					break;
				}
			}
		}
*/	}
	UpdateData(FALSE);//更新编辑框内容

}

int CExamviewView::OnCreate(LPCREATESTRUCT lpCreateStruct) //来源于VC-TC串口编程实例P65
{
	if (CFormView::OnCreate(lpCreateStruct) == -1)
		return -1;
	DWORD style=WS_VISIBLE;
	// TODO: Add your specialized creation code here
	m_MSComm.Create(NULL,0,CRect(0,0,0,0),this,IDC_MSCOMM1);
	m_MSComm.SetCommPort(1);//在设置选项里的port值不能初始时未能传递过来
	m_MSComm.SetInputMode(1);
	m_MSComm.SetInBufferSize(1024);
	m_MSComm.SetOutBufferSize(512);

	m_MSComm.SetRThreshold(1);
	m_MSComm.SetInputLen(0);
	m_MSComm.SetSettings("9600,n,8,1");
	if(!m_MSComm.GetPortOpen())
		m_MSComm.SetPortOpen(TRUE);
	else
		MessageBox("打开串口出错");
	m_MSComm.GetInput();//先预读以清除残留数据
	return 0;
}

void CExamviewView::OnFileExport() 
{
	// TODO: Add your command handler code here
	CString ch="abcd";
	CFileDialog fileDlg(FALSE);//FALSE为保存
	fileDlg.m_ofn.lpstrTitle="导出数据";//标题
	fileDlg.m_ofn.lpstrDefExt="xxl";//默认保存的文件类型
	fileDlg.m_ofn.lpstrFilter="XXL Files(*.xxl)\0*.xxl\0All Files(*.*)\0*.*\0\0";//过滤
	if(IDOK==fileDlg.DoModal())
	{
		CFile file(ch,CFile::modeCreate | CFile::modeWrite);
		file.Write(ch,strlen(ch));
		file.Close();//响应文件名的输出方式还有问题存在
	}
}

void CExamviewView::OnFileImport() 
{
	// TODO: Add your command handler code here
	CFileDialog fileDlg(TRUE);//FALSE为保存
	fileDlg.m_ofn.lpstrTitle="导出数据";//标题
	fileDlg.m_ofn.lpstrFilter="XXL Files(*.xxl)\0*.txt\0All Files(*.*)\0*.*\0\0";//过滤
	if(IDOK==fileDlg.DoModal())
	{
		CString ch="abcd";
		CFile file(ch,CFile::modeRead);
		char *pBuf;
		DWORD dwFileLen;
		dwFileLen=file.GetLength();
		pBuf=new char[dwFileLen+1];
		pBuf[dwFileLen]=0;
		file.Read(pBuf,dwFileLen);
		file.Close();//响应文件名的输出方式还有问题存在
		MessageBox(pBuf);	
	}
}

void CExamviewView::OnComSetup() //在此处实现端口设置参数的传递。但是参数的具体传递细节没有解决
{
	// TODO: Add your command handler code here
	CComSetSheet m_ComSetSheet("多路温度仪");//参数是指显示标题
	UpdateData(TRUE);
	CString porttemp;
	if(IDOK==m_ComSetSheet.DoModal())
	{
		baudtemp=m_ComSetSheet.m_ComSetDlg.m_sBaud;//属性表属性值的访问方式。得到的是CString类型
		porttemp=m_ComSetSheet.m_ComSetDlg.m_sPort;
		porttemp=porttemp.Mid(3,1);
		char portt=atoi(porttemp);
 		switch(portt)
		{
		case 1:
			port=1;
			break;
		case 2:
			port=2;
			break;
		case 3:
			port=3;
			break;
		case 4:
			port=4;
			break;
		default:
			break;
		}
//		DevID=m_ComSetSheet.m_ComSetDlg.m_sDevID;
//		DevID=1;
/*		if(m_MSComm.GetCommPort==port)
		;
		else{
		m_MSComm.SetPortOpen(FALSE);
		m_MSComm.SetCommPort(port);
		baudtemp.Format("%d,n,8,1",baudtemp);
		m_MSComm.SetSettings(baudtemp);
		m_MSComm.SetPortOpen(TRUE);
		}//		itoa(port,1,10);
*/
  //		char cc[10];
	//		((CComboBox*)GetDlgItem(IDC_PORT))->GetLBText(index,cc);
		
//		port=index+1;
//		itoa(port,cc,10);
//		MessageBox(/*"波特率是:"+baud+"端口是COM"+*/port);
	}
	m_ComSetSheet.m_ComSetDlg.m_sBaud=baudtemp;//属性表属性值的访问方式。得到的是CString类型
	m_ComSetSheet.m_ComSetDlg.m_sPort=porttemp;	
	UpdateData(FALSE);//TRUE控件到变量.FALSE变量到控件

//		char index;
//		index=GetDlgItem(IDC_PORT)->GetCurSel();
//		port=atoi(index)+1;
//		MessageBox(port);

}

void CExamviewView::OnComClose() 
{
	// TODO: Add your command handler code here
	if(m_MSComm.GetPortOpen())
		m_MSComm.SetPortOpen(FALSE);
}


void CExamviewView::OnComOpen() 
{
	// TODO: Add your command handler code here
	if(!m_MSComm.GetPortOpen())
	m_MSComm.SetPortOpen(TRUE);//打开串口
		//应该还有一些后续的操作情形,暂时留待协议能完成之后再行添加


}

WORD CExamviewView::ANSI_CRC_16(BYTE *btData, int nLength)
{
	CHECKVALUE(btData,nLength);
	WORD CRC=0xFFFF;
	BYTE j,Tmp=0;
	int i;
    for(i=0;i<nLength;i++)
    {     
		CRC^=btData[i];                      
		for (j=0;j<8;j++)                   	
		{                                   	
			Tmp=CRC&0x0001;             	
			CRC=CRC>>1;                 	
			if(Tmp)CRC=(CRC^0xA001);    	
		}                                   	
    }
	return ((CRC>>8)+(CRC<<8));	/* 应用时高在先 */
}

//把CString转成16进制数
int CExamviewView::StrToHex(CString str, BYTE *btData)
{
	int nLength=str.GetLength();
	if(nLength<2)	return 0;
	for(int i=0;i<nLength;i+=2)	_stscanf(str.Mid(i,2),"%02X",&btData[i/2]);
	return (i+1)/2;
/*以下是得到CRC校验码的主函数过程
	CString strTemp;
	strTemp=m_strCRC;
	
	WORD CRC;
	BYTE btData[4096*2];	
	int nLength=StrToHex(strTemp,btData);
     
	CRC=ANSI_CRC_16(btData,nLength);	//ANSI-16
	CString str;
	str.Format(" %02X %02X",(BYTE)(CRC>>8),(BYTE)CRC);
*/

}


CString CExamviewView::Combine(CString DevID, CString Address)
{
	CString sendtemp1,CRCAdd;
	sendtemp1=DevID+"03"+Address+"0002";
	WORD CRC;
	BYTE btData[4096];
	int nLength=StrToHex(sendtemp1,btData);

	CRC=ANSI_CRC_16(btData,nLength);
	CRCAdd.Format("%02X%02X",(BYTE)(CRC>>8),(BYTE)CRC);

	sendtemp1+=CRCAdd;
	return sendtemp1;
}

void CExamviewView::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	OnComRead();
	CFormView::OnTimer(nIDEvent);
}

void CExamviewView::OnComRead() 
{
	// TODO: Add your command handler code here
	CString sDevID;
	CComSetSheet m_ComSetSheet("多路温度仪");//参数是指显示标题
//	UpdateData(TRUE);
	int DevIDtemp=m_ComSetSheet.m_ComSetDlg.m_sDevID;
//	int DevIDtemp=5;
	sDevID.Format("%X",DevIDtemp);

	int DevNum=sDevID.GetLength();
//	int d=aoti(DevNum.GetBuffer(DevNum.GetLength()));

	switch(DevNum)
	{
	case 1:
		sDevID="0"+sDevID;
		break;
	case 0:
		MessageBox("请确认已经输入了站地址DE");
		break;
	default:
		break;
	}
	CByteArray hexdata;
	CString SendData=Combine(sDevID,"0012");
	int len=String2Hex(SendData,hexdata); //此处返回的len可以用于计算发送了多少个十六进制数
	m_MSComm.SetOutput(COleVariant(hexdata)); //发送十六进制数据
	MessageBox(SendData);
}

int CExamviewView::String2Hex(CString str, CByteArray &senddata)
{
	int hexdata,lowhexdata;
	int hexdatalen=0;
	int len=str.GetLength();
	senddata.SetSize(len/2);
	for(int i=0;i<len;)
	{
		char lstr,hstr=str[i];
		if(hstr==' ')
		{
			i++;
			continue;
		}
		i++;
		if(i>=len)
		break;
		lstr=str[i];
		hexdata=ConvertHexChar(hstr);
		lowhexdata=ConvertHexChar(lstr);
		if((hexdata==16)||(lowhexdata==16))
			break;
		else 
			hexdata=hexdata*16+lowhexdata;
			i++;
			senddata[hexdatalen]=(char)hexdata;
			hexdatalen++;
	}
	senddata.SetSize(hexdatalen);
	return hexdatalen;
}


char CExamviewView::ConvertHexChar(char ch)
{
	if((ch>='0')&&(ch<='9'))
		return ch-0x30;
	else if((ch>='A')&&(ch<='F'))
		return ch-'A'+10;
	else if((ch>='a')&&(ch<='f'))
		return ch-'a'+10;
	else return (-1);
}

⌨️ 快捷键说明

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