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(); }