www.gusucode.com > vc串口控制单片机实现AD转换和温度测量 > vc串口控制单片机实现AD转换和温度测量/csdn/myComm/myCommDlg.cpp

    // myCommDlg.cpp : implementation file
//

#include "stdafx.h"
#include "myComm.h"
#include "myCommDlg.h"

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

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

/////////////////////////////////////////////////////////////////////////////
// CMyCommDlg dialog

CMyCommDlg::CMyCommDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMyCommDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CMyCommDlg)
	m_bAD = FALSE;
	m_bTemper = FALSE;
	m_fVol = 0.0f;
	m_fTemp = 0.0f;
	m_strCommState = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	//初始化串口相关参数
	m_strCommSet = _T("9600, N, 8, 1");
	m_nBaud=9600;
	m_nCom=1;
	m_cParity='N';
	m_nDatabits=8;
	m_nStopbits=1;
	m_bTesting = false;
	m_nRevIndex = 0;
	m_bRecv = false;
	m_dwCommEvents = EV_RXFLAG | EV_RXCHAR;
}

void CMyCommDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMyCommDlg)
	DDX_Check(pDX, IDC_CHECK_AD, m_bAD);
	DDX_Check(pDX, IDC_CHECK_TEMPER, m_bTemper);
	DDX_Text(pDX, IDC_EDIT_VOL, m_fVol);
	DDX_Text(pDX, IDC_EDIT_TEMPER, m_fTemp);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMyCommDlg, CDialog)
	//{{AFX_MSG_MAP(CMyCommDlg)
	ON_MESSAGE(WM_COMM_RXCHAR, OnCommunication)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BTN_SETCOMM, OnBtnSetcomm)
	ON_BN_CLICKED(IDC_BTN_OPENCOMM, OnBtnOpencomm)
	ON_BN_CLICKED(IDC_BTN_CLOSECOMM, OnBtnClosecomm)
	ON_BN_CLICKED(IDC_BTN_TEST, OnBtnTest)
	ON_BN_CLICKED(IDC_BTN_STOP, OnBtnStop)
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMyCommDlg message handlers

BOOL CMyCommDlg::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
	
	// TODO: Add extra initialization here
	SetDlgItemText(IDC_COMM_STATE, " "); //设置串口状态提示

	return TRUE;  // return TRUE  unless you set the focus to a control
}

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

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

void CMyCommDlg::OnBtnSetcomm() 
{
	// TODO: Add your control notification handler code here
	CCommSetDdlg dlg;
	if (IDOK == dlg.DoModal())
	{
		m_nCom = dlg.m_nCom;				//串口号
		m_nBaud = dlg.m_nBaud;				//波特率
		m_cParity = dlg.m_cParity;		    //校验位
		m_nDatabits = dlg.m_nDatabits;		//数据位
		m_nStopbits = dlg.m_nStopbits;		//停止位
		m_strCommSet = dlg.m_strCommSet;    //用于设置控件的总体字符串
	}
}

void CMyCommDlg::OnBtnOpencomm() 
{
	// TODO: Add your control notification handler code here
	if (m_Port.InitPort(this, m_nCom, m_nBaud, m_cParity, m_nDatabits,m_nStopbits,
		m_dwCommEvents, 512))
	{
		m_Port.StartMonitoring();
		m_strCommState.Format("串口COM%d已经打开\n", m_nCom);
		m_strCommState += "设置参数:";
		m_strCommState += m_strCommSet;
		SetDlgItemText(IDC_COMM_STATE, m_strCommState);
		m_bOpenPort = true;
	}
	else
	{
		AfxMessageBox("没有发现此串口或被占用");		
	}
	
}

void CMyCommDlg::OnBtnClosecomm() 
{
	// TODO: Add your control notification handler code here
	if (m_bOpenPort)
	{
		m_Port.ClosePort();
		m_bOpenPort = false;
	}
	m_strCommState.Format("串口COM%d已经关闭", m_nCom);
	SetDlgItemText(IDC_COMM_STATE, m_strCommState);
}

BEGIN_EVENTSINK_MAP(CMyCommDlg, CDialog)
    //{{AFX_EVENTSINK_MAP(CMyCommDlg)	
	//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()

//发送数据
//DEL void CMyCommDlg::OnBtnSend() 
//DEL {
//DEL 	// TODO: Add your control notification handler code here
//DEL 	CString strSend;
//DEL 	GetDlgItemText(IDC_EDIT_SEND, strSend);
//DEL 	m_Comm.SetOutput(COleVariant(strSend));	//发送数据
//DEL 
//DEL 
//DEL 	/*	char TxData[100];
//DEL 	int Count = m_strEditTXData.GetLength();
//DEL 	for(int i = 0; i < Count; i++)
//DEL 	TxData[i] = m_strEditTXData.GetAt(i);
//DEL 	CByteArray array;     
//DEL 	array.RemoveAll();
//DEL 	array.SetSize(Count);
//DEL 	for(i=0;i<Count;i++)
//DEL 	array.SetAt(i, TxData[i]);
//DEL 	m_ctrlComm.SetOutput(COleVariant(array)); // 发送数据	
//DEL 	*/	
//DEL 	
//DEL 	////////////////注:以下代码用于第3章第3.2.3节
//DEL 	/////////////////如何发送接收ASCII值为0和大于128的字符?的测试代码
//DEL 	/*	unsigned char chData[8];
//DEL 	chData[0]=0;    chData[1]=1;    chData[2]=13; 
//DEL 	chData[3]=12;   chData[4]=0;    chData[5]=10;
//DEL 	chData[6]=156;   //156的16进制值为0X9C
//DEL 	chData[7]=255;   //255的16进制值为0XFF
//DEL 	
//DEL 	  CByteArray binData;
//DEL 	  binData.RemoveAll(); //清空binData
//DEL 	  for(int i=0;i<8;i++)
//DEL 	  binData.Add(chData[i]);
//DEL 	  COleVariant var(binData); //将binData转化为Variant数据类型
//DEL 	  m_ctrlComm.SetOutput(var);
//DEL */
//DEL }

//向单片机发送控制信号
bool CMyCommDlg::SendControl()
{
	UpdateData(TRUE);	//获取复选框状态           
	if (m_Port.m_hComm == NULL)
	{
		MessageBox("串口状态错误!");
		m_bTesting = false;
		return false;
	}
	char bArray[6];                     //利用VC++6.0 实现上位机与PLC的串行通信 
	char begin, bytecount, control, fcs;
	begin = '*';
	bytecount = 0x01;
	if (m_bAD && m_bTemper)
	{
		control = 0x03;	//0000_0011;
		m_con = BOTH;
	}
	else if(m_bAD)
	{
		control = 0x01;	//0000_0001;
		m_con = ONLYAD;
	}
	else if(m_bTemper)
	{
		control = 0x02; //0000_0010;
		m_con = ONLYTEMP;
	}
	else
	{
		MessageBox("请设置采集方式!");
		m_con = NONE;
		m_bTesting = false;
		return false;
	}
	fcs = control^bytecount;
	bArray[0] = begin;
	bArray[1] = 0;
	bArray[2] = bytecount;
	bArray[3] = control;
	bArray[4] = fcs;
	bArray[5] = '$';	

	m_Port.WriteToPort(bArray, 6);
	m_bTesting = true;
	return true;
}

//发送停止采集 
void CMyCommDlg::OnBtnStop() 
{
	// TODO: Add your control notification handler code here
	if (m_Port.m_hComm == NULL)
	{
		MessageBox("串口状态错误!");
		m_bTesting = false;
		return;
	}

	char bArray[6];                     //利用VC++6.0 实现上位机与PLC的串行通信 
	char begin, bytecount, control, fcs;
	begin = '*';
	bytecount = 0x01;	
	control = 0x40;	//0100_0000;	
	fcs = control^bytecount;

	bArray[0] = begin;
	bArray[1] = 0;
	bArray[2] = bytecount;
	bArray[3] = control;
	bArray[4] = fcs;
	bArray[5] = '$';
	m_Port.WriteToPort(bArray, 6);
	
	m_bTesting = false;
	m_fVol = 0.0f;
	m_fTemp = 0.0f;
	UpdateData(FALSE);
	//设置控件的可用性;
	((CButton *)GetDlgItem(IDC_BTN_OPENCOMM))->EnableWindow(TRUE);
	((CButton *)GetDlgItem(IDC_BTN_CLOSECOMM))->EnableWindow(TRUE);
	((CButton *)GetDlgItem(IDC_BTN_TEST))->EnableWindow(TRUE);
	((CButton *)GetDlgItem(IDC_BTN_SETCOMM))->EnableWindow(TRUE);
	((CButton *)GetDlgItem(IDC_BTN_STOP))->EnableWindow(FALSE);
	((CButton *)GetDlgItem(IDC_CHECK_AD))->EnableWindow(TRUE);
	((CButton *)GetDlgItem(IDC_CHECK_TEMPER))->EnableWindow(TRUE);

	m_nRevIndex = 0;
	memset(m_cByte, 0, 10);
	m_bRecv = false;
}

//发送接收错误信号
void CMyCommDlg::SendError()
{
	if (m_Port.m_hComm == NULL)
	{
		MessageBox("串口状态错误!");
		m_bTesting = false;
		return;
	}
	char bArray[6];                     //利用VC++6.0 实现上位机与PLC的串行通信 
	char begin, bytecount, control, fcs;
	begin = '*';
	bytecount = 0x01;	
	control = 0xF0;	//1111_0000;	
	fcs = control^bytecount;
	bArray[0] = begin;
	bArray[1] = 0;
	bArray[2] = bytecount;
	bArray[3] = control;
	bArray[4] = fcs;
	bArray[5] = '$';
	
	m_Port.WriteToPort(bArray, 6);
}


//根据是否正在采集来使能控件
void CMyCommDlg::UpdateWnd(bool testing)
{
	if (testing)
	{	//正在采集
		((CButton *)GetDlgItem(IDC_BTN_OPENCOMM))->EnableWindow(FALSE);
		((CButton *)GetDlgItem(IDC_BTN_CLOSECOMM))->EnableWindow(FALSE);
		((CButton *)GetDlgItem(IDC_BTN_TEST))->EnableWindow(FALSE);
		((CButton *)GetDlgItem(IDC_BTN_SETCOMM))->EnableWindow(FALSE);
		((CButton *)GetDlgItem(IDC_BTN_STOP))->EnableWindow(TRUE);
		((CButton *)GetDlgItem(IDC_CHECK_AD))->EnableWindow(FALSE);
		((CButton *)GetDlgItem(IDC_CHECK_TEMPER))->EnableWindow(FALSE);		
	} 
	else
	{
		((CButton *)GetDlgItem(IDC_BTN_OPENCOMM))->EnableWindow(TRUE);
		((CButton *)GetDlgItem(IDC_BTN_CLOSECOMM))->EnableWindow(TRUE);
		((CButton *)GetDlgItem(IDC_BTN_TEST))->EnableWindow(TRUE);
		((CButton *)GetDlgItem(IDC_BTN_SETCOMM))->EnableWindow(TRUE);
		((CButton *)GetDlgItem(IDC_BTN_STOP))->EnableWindow(FALSE);
		((CButton *)GetDlgItem(IDC_CHECK_AD))->EnableWindow(TRUE);
		((CButton *)GetDlgItem(IDC_CHECK_TEMPER))->EnableWindow(TRUE);
	}
}

//测试发送信号
void CMyCommDlg::OnBtnTest() 
{
	// TODO: Add your control notification handler code here
	m_bRecv = false;
	bool bf = SendControl();
	//设置相关控件的可用性;

	((CButton *)GetDlgItem(IDC_BTN_OPENCOMM))->EnableWindow(FALSE);
	((CButton *)GetDlgItem(IDC_BTN_CLOSECOMM))->EnableWindow(FALSE);
	((CButton *)GetDlgItem(IDC_BTN_TEST))->EnableWindow(FALSE);
	((CButton *)GetDlgItem(IDC_BTN_SETCOMM))->EnableWindow(FALSE);
	((CButton *)GetDlgItem(IDC_BTN_STOP))->EnableWindow(TRUE);
	((CButton *)GetDlgItem(IDC_CHECK_AD))->EnableWindow(FALSE);
	((CButton *)GetDlgItem(IDC_CHECK_TEMPER))->EnableWindow(FALSE);	
	
//	AfxBeginThread(ThreadProc1, (LPVOID)(this),THREAD_PRIORITY_BELOW_NORMAL);
}

void CMyCommDlg::CFunction()
{
	//进行校验
	char cf;
	int i;
				cf = 0x00;
				for (i=1; i<m_nRevIndex-1; i++)
				{
					cf ^= m_cByte[i];
				}
				if (cf)
				{
					m_nRevIndex = 0;
					memset(m_cByte, 0, 10);
					m_bRecv = false;
					SendError();
				}
				else //开始对数据进行解析
				{
					if(m_cByte[1] == 0 && m_cByte[3] == 0xF0) //从机接受命令出错
					{
						m_nRevIndex = 0;
						memset(m_cByte, 0, 10);
						m_bRecv = false;
						SetDlgItemText(IDC_EDIT_TEMPER, "");
						SetDlgItemText(IDC_EDIT_VOL, "");
						SendControl();
					}
					else if(m_cByte[1] == 0x02) //表示测量的是温度
					{
						short *temp = (short *)(m_cByte+3);  //有符号变量强制类型转换,当最高位为1时自动变为负数
						m_fTemp = *temp * 0.0625; 
						
						CString str;
						str.Format("%.2f", m_fTemp);
						SetDlgItemText(IDC_EDIT_TEMPER, str);
						SetDlgItemText(IDC_EDIT_VOL, "");
						m_nRevIndex = 0;
						m_bRecv = false;
						memset(m_cByte, 0, 10);
					}
					else if (m_cByte[1] == 0x01) //表示测量的是电压
					{
						int vol = m_cByte[3];
						m_fVol = vol*5.0/255;
						
						CString str;
						str.Format("%.2f", m_fVol);
						SetDlgItemText(IDC_EDIT_VOL, str);
						SetDlgItemText(IDC_EDIT_TEMPER, "");
						m_nRevIndex = 0;
						m_bRecv = false;
						memset(m_cByte, 0, 10);
					}
					else if (m_cByte[1] == 0x03) //表示测量的是电压和温度
					{
						int vol = m_cByte[3];
						m_fVol = vol*5.0/255;
						CString str;
						str.Format("%.2f", m_fVol);
						SetDlgItemText(IDC_EDIT_VOL, str);
						
						short *temp = (short *)(m_cByte+4);  //有符号变量强制类型转换,当最高位为1时自动变为负数
						m_fTemp = *temp * 0.0625; 						
						str.Format("%.2f", m_fTemp);
						SetDlgItemText(IDC_EDIT_TEMPER, str);
						
						m_nRevIndex = 0;
						m_bRecv = false;
						memset(m_cByte, 0, 10);
					}
					else 
					{	
						m_bRecv = false;
						m_nRevIndex = 0;
						memset(m_cByte, 0, 10);
						SendError();
					}
				}
}


UINT ThreadProc1(LPVOID lpParameter)
{
	CMyCommDlg *pDlg = (CMyCommDlg *)lpParameter;
	while (!pDlg->m_bRecv);	
	pDlg->CFunction();
	return 0;
}

static long rxdatacount=0;  //该变量用于接收字符计数
LONG CMyCommDlg::OnCommunication(WPARAM ch, LPARAM port)
{
	if (port<=0 || port>4)
	{
		return -1;
	}
	if (m_nRevIndex == 0 )
	{
		if (ch == 0x2a)
		{
			m_cByte[m_nRevIndex++] = 0x2a;
		}
		else
		{
			m_nRevIndex = 0;
			memset(m_cByte, 0, 10);
			SendError();
		}
	}
	else
		m_cByte[m_nRevIndex++] = ch;	
	//判断字节是否接受完
	if (ch == 0x24 )
	{
		if (m_cByte[2]+5 == m_nRevIndex) //长度条件也满足
		{
			m_bRecv = true;
			CFunction();
		}
	}
	if (m_nRevIndex > 9)
	{
		m_nRevIndex = 0;
		memset(m_cByte, 0, 10);
		SendError();
	}
	return 0;
}

void CMyCommDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	
	// TODO: Add your message handler code here
	m_Port.ClosePort();
}