?? serialportdlg.cpp
字號:
// SerialPortDlg.cpp : implementation file
//
#include "stdafx.h"
#include "SerialPort.h"
#include "SerialPortDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSerialPortDlg dialog
CSerialPortDlg::CSerialPortDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSerialPortDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CSerialPortDlg)
m_strSendEdit = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CSerialPortDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSerialPortDlg)
DDX_Control(pDX, IDC_CLOSE_COM, m_ButClose);
DDX_Control(pDX, IDC_OPEN_COM, m_ButOpen);
DDX_Control(pDX, IDC_STOP, m_ComboStop);
DDX_Control(pDX, IDC_PARITY, m_ComboParity);
DDX_Control(pDX, IDC_PORT, m_ComboPort);
DDX_Control(pDX, IDC_DATA, m_ComboData);
DDX_Control(pDX, IDC_BAUD, m_ComboBaud);
DDX_Text(pDX, IDC_SEND_EDIT, m_strSendEdit);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CSerialPortDlg, CDialog)
//{{AFX_MSG_MAP(CSerialPortDlg)
ON_BN_CLICKED(IDC_OPEN_COM, OnOpenCom)
ON_BN_CLICKED(IDC_CLOSE_COM, OnCloseCom)
ON_BN_CLICKED(IDC_SEND, OnSend)
ON_BN_CLICKED(IDC_CLEAR_SEND, OnClearSend)
ON_BN_CLICKED(IDC_CLEAR_REC, OnClearRec)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSerialPortDlg message handlers
BOOL CSerialPortDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 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
CenterWindow(GetDesktopWindow()); // center to the hpc screen
m_ComboBaud.SetCurSel(5); /* 默認波特率為: 115200 */
m_ComboData.SetCurSel(1); /* 默認數據位為: 8位 */
m_ComboParity.SetCurSel(0); /* 默認校驗為: 無 */
m_ComboPort.SetCurSel(0); /* 默認端口為: COM1 */
m_ComboStop.SetCurSel(0); /* 默認停止位為: 1位 */
m_ButClose.EnableWindow(FALSE); /* "關閉端口"按鍵無效 */
m_hComm = INVALID_HANDLE_VALUE; /* 串口操作句柄無效 */
m_ExitThreadEvent = NULL; /* 串口接收線程退出事件無效 */
m_strRecDisp = _T(""); /* 接收顯示字符為空 */
UpdateData(FALSE);
return TRUE;
}
/****************************************************************
實 驗 代 碼
*****************************************************************/
/*******************************************************************************************
函數名稱: CSerialPortDlg::OpenPort
描 述: 打開串口
輸入參數: LPCTSTR Port: 串口名,如"COM0:","COM1:"
int BaudRate: 波特率
int DataBits: 數據位, 取值為7或8
int StopBits: 停止位
int Parity : 奇偶校驗位
輸出參數: 無
返 回: FALSE: 失敗; TRUE: 成功
********************************************************************************************/
BOOL CSerialPortDlg::OpenPort(LPCTSTR Port, int BaudRate, int DataBits, int StopBits, int Parity)
{
COMMTIMEOUTS CommTimeOuts;
// 打開串口
m_hComm = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if(m_hComm == INVALID_HANDLE_VALUE)
{
MessageBox(_T("無法打開端口或端口已打開!請檢查是否已被占用."));
return FALSE;
}
GetCommState(m_hComm, &dcb); /* 讀取串口的DCB */
dcb.BaudRate = BaudRate;
dcb.ByteSize = DataBits;
dcb.Parity = Parity;
dcb.StopBits = StopBits;
dcb.fParity = FALSE; /* 禁止奇偶校驗 */
dcb.fBinary = TRUE;
dcb.fDtrControl = 0; /* 禁止流量控制 */
dcb.fRtsControl = 0;
dcb.fOutX = 0;
dcb.fInX = 0;
dcb.fTXContinueOnXoff = 0;
//設置狀態參數
SetCommMask(m_hComm, EV_RXCHAR); /* 串口事件:接收到一個字符 */
SetupComm(m_hComm, 16384, 16384); /* 設置接收與發送的緩沖區大小 */
if(!SetCommState(m_hComm, &dcb)) /* 設置串口的DCB */
{
MessageBox(_T("無法按當前參數配置端口,請檢查參數!"));
ClosePort();
return FALSE;
}
//設置超時參數
GetCommTimeouts(m_hComm, &CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout = 100; /* 接收字符間最大時間間隔 */
CommTimeOuts.ReadTotalTimeoutMultiplier = 1;
CommTimeOuts.ReadTotalTimeoutConstant = 100; /* 讀數據總超時常量 */
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
if(!SetCommTimeouts(m_hComm, &CommTimeOuts))
{
MessageBox(_T("無法設置超時參數!"));
ClosePort();
return FALSE;
}
PurgeComm(m_hComm, PURGE_TXCLEAR | PURGE_RXCLEAR); /* 清除收/發緩沖區 */
return TRUE;
}
/*******************************************************************************************
函數名稱: CSerialPortDlg::ClosePort
描 述: 關閉串口
輸入參數: 無
輸出參數: 無
返 回: FALSE: 失敗; TRUE: 成功
********************************************************************************************/
BOOL CSerialPortDlg::ClosePort(void)
{
if(m_hComm != INVALID_HANDLE_VALUE)
{
SetCommMask(m_hComm, 0);
PurgeComm(m_hComm, PURGE_TXCLEAR | PURGE_RXCLEAR); /* 清除收/發緩沖 */
CloseHandle(m_hComm); /* 關閉串口操作句柄 */
m_hComm = INVALID_HANDLE_VALUE;
return TRUE;
}
return FALSE;
}
/*******************************************************************************************
函數名稱: CALLBACK CSerialPortDlg::OnCommRecv
描 述: 串口接收數據成功回調函數
輸入參數: 無
輸出參數: 無
返 回: FALSE: 失敗; TRUE: 成功
********************************************************************************************/
void CALLBACK CSerialPortDlg::OnCommRecv(CWnd* pWnd, char *buf, int buflen)
{
CString tmp;
CSerialPortDlg * pDlg = (CSerialPortDlg*)pWnd;
CEdit *pRecvStrEdit = (CEdit*)pDlg->GetDlgItem(IDC_REC_DISP);
/* 取得控件指針 */
for (int i = 0; i < buflen; i++, buf++)
{
tmp.Format(_T("%c"), *buf); /* 將字符轉換為字符串 */
pDlg->m_strRecDisp += tmp;
}
pRecvStrEdit->SetWindowText(pDlg->m_strRecDisp); /* 顯示在窗口上 */
}
/*******************************************************************************************
函數名稱: CSerialPortDlg::CommRecvTread
描 述: 串口接收線程
輸入參數: LPVOID lparam: 線程參數,創建線程時傳入
輸出參數: 無
返 回: 0: 線程退出, 返回值沒特殊含義
********************************************************************************************/
DWORD CSerialPortDlg::CommRecvTread(LPVOID lparam)
{
DWORD dwLength;
char *recvBuf = new char[1024];
CSerialPortDlg *pDlg = (CSerialPortDlg*)lparam;
while(TRUE)
{ /* 等待線程退出事件 */
if (WaitForSingleObject(pDlg->m_ExitThreadEvent, 0) == WAIT_OBJECT_0)
break;
if (pDlg->m_hComm != INVALID_HANDLE_VALUE)
{ /* 從串口讀取數據 */
BOOL fReadState = ReadFile(pDlg->m_hComm, recvBuf, 1024, &dwLength, NULL);
if(!fReadState)
{
//MessageBox(_T("無法從串口讀取數據!"));
}
else
{
if(dwLength != 0)
OnCommRecv(pDlg, recvBuf, dwLength); /* 接收成功調用回調函數 */
}
}
}
delete[] recvBuf;
return 0;
}
// 定義串口設置參數表格
const CString PorTbl[6] = {_T("COM1:"),_T("COM2:"),_T("COM3:"),_T("COM4:"),_T("COM5:"), _T("COM6:")};
const DWORD BaudTbl[6] = {4800, 9600, 19200, 38400, 57600,115200};
const DWORD DataBitTbl[2] = {7, 8};
const BYTE StopBitTbl[3] = {ONESTOPBIT, ONE5STOPBITS, TWOSTOPBITS};
const BYTE ParityTbl[4] = {NOPARITY, ODDPARITY, EVENPARITY, MARKPARITY};
/*******************************************************************************************
函數名稱: CSerialPortDlg::OnOpenCom
描 述: "打開端口" 按鍵單擊事件代碼
輸入參數: 無
輸出參數: 無
返 回: 無
********************************************************************************************/
void CSerialPortDlg::OnOpenCom()
{
DWORD IDThread;
HANDLE hRecvThread; /* 接收線程句柄 */
UpdateData(TRUE);
CString strPort = PorTbl[m_ComboPort.GetCurSel()]; /* 查表獲取參數值 */
DWORD baud = BaudTbl[m_ComboBaud.GetCurSel()];
DWORD databit = DataBitTbl[m_ComboData.GetCurSel()];
BYTE stopbit = StopBitTbl[m_ComboStop.GetCurSel()];
BYTE parity = ParityTbl[m_ComboParity.GetCurSel()];
BOOL ret = OpenPort(strPort, baud, databit, stopbit, parity); /* 打開串口 */
if (ret == FALSE)
return;
m_ExitThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* 創建串口接收線程退出事件*/
// 創建串口接收線程
hRecvThread = CreateThread(0, 0, CommRecvTread, this, 0, &IDThread);
if (hRecvThread == NULL)
{
MessageBox(_T("創建接收線程失敗!"));
return;
}
CloseHandle(hRecvThread);
m_ButOpen.EnableWindow(FALSE); /* 打開端口按鍵禁止 */
m_ButClose.EnableWindow(TRUE); /* 關閉端口按鍵使能 */
MessageBox(_T("打開") + strPort + _T("成功!"));
}
/*******************************************************************************************
函數名稱: CSerialPortDlg::OnOpenCom
描 述: "關閉端口" 按鍵單擊事件代碼
輸入參數: 無
輸出參數: 無
返 回: 無
********************************************************************************************/
void CSerialPortDlg::OnCloseCom()
{
if (m_ExitThreadEvent != NULL)
{
SetEvent(m_ExitThreadEvent); /* 通知線程退出 */
Sleep(1000);
CloseHandle(m_ExitThreadEvent);
m_ExitThreadEvent = NULL;
}
m_ButOpen.EnableWindow(TRUE); /* 打開端口按鍵禁止 */
m_ButClose.EnableWindow(FALSE); /* 關閉端口按鍵使能 */
ClosePort();
}
/*******************************************************************************************
函數名稱: CSerialPortDlg::OnOpenCom
描 述: "關閉端口" 按鍵單擊事件代碼
輸入參數: 無
輸出參數: 無
返 回: 無
********************************************************************************************/
void CSerialPortDlg::OnSend()
{
DWORD dwactlen;
if (m_hComm == INVALID_HANDLE_VALUE)
{
MessageBox(_T("串口未打開!"));
return;
}
UpdateData(TRUE);
int len = m_strSendEdit.GetLength(); /* 取得輸入字符串長度 */
char *psendbuf = new char[len];
for(int i = 0; i < len;i++)
psendbuf[i] = (char)m_strSendEdit.GetAt(i); /* 轉換為單字節字符 */
WriteFile(m_hComm, psendbuf, len, &dwactlen, NULL); /* 從串口發送數據 */
delete[] psendbuf;
}
/*******************************************************************************************
函數名稱: CSerialPortDlg::OnClearSend
描 述: "清除發送緩沖區" 按鍵單擊事件代碼
輸入參數: 無
輸出參數: 無
返 回: 無
********************************************************************************************/
void CSerialPortDlg::OnClearSend()
{
m_strSendEdit = _T(""); /* 清除發送區的字符 */
UpdateData(FALSE);
}
/*******************************************************************************************
函數名稱: CSerialPortDlg::OnClearRec
描 述: "清除接收緩沖區" 按鍵單擊事件代碼
輸入參數: 無
輸出參數: 無
返 回: 無
********************************************************************************************/
void CSerialPortDlg::OnClearRec()
{
m_strRecDisp = _T("");
SetDlgItemText(IDC_REC_DISP,m_strRecDisp); /* 清除接收區的字符 */
}
/*******************************************************************************************
函數名稱: CSerialPortDlg::OnDestroy
描 述: 窗口銷毀事件處理函數
輸入參數: 無
輸出參數: 無
返 回: 無
********************************************************************************************/
void CSerialPortDlg::OnDestroy()
{
CDialog::OnDestroy();
if (m_ExitThreadEvent != NULL)
{
SetEvent(m_ExitThreadEvent); /* 通知串口接收線程退出 */
Sleep(1000);
CloseHandle(m_ExitThreadEvent); /* 關閉接收線程退出事件句柄 */
m_ExitThreadEvent = NULL;
}
ClosePort(); /* 關閉串口 */
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -