以下是一个简单的MFC串口调试助手的源码,可以实现串口的打开、关闭、发送和接收数据。需要注意的是,本程序仅供参考,具体实现可能因不同环境而异。
```
// SerialPortTestDlg.cpp : implementation file
//
#include "stdafx.h"
#include "SerialPortTest.h"
#include "SerialPortTestDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CSerialPortTestDlg dialog
CSerialPortTestDlg::CSerialPortTestDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_SERIALPORTTEST_DIALOG, pParent)
, m_strSend(_T(""))
, m_strReceive(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CSerialPortTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_SEND, m_strSend);
DDX_Text(pDX, IDC_EDIT_RECEIVE, m_strReceive);
}
BEGIN_MESSAGE_MAP(CSerialPortTestDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_OPEN, &CSerialPortTestDlg::OnBnClickedButtonOpen)
ON_BN_CLICKED(IDC_BUTTON_CLOSE, &CSerialPortTestDlg::OnBnClickedButtonClose)
ON_BN_CLICKED(IDC_BUTTON_SEND, &CSerialPortTestDlg::OnBnClickedButtonSend)
ON_MESSAGE(WM_COMM_RXCHAR, &CSerialPortTestDlg::OnCommRxChar)
END_MESSAGE_MAP()
// CSerialPortTestDlg message handlers
BOOL CSerialPortTestDlg::OnInitDialog()
{
CDialogEx::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
// TODO: Add extra initialization here
// 初始化串口控件
m_pSerial = new CSerialPort;
m_pSerial->m_hWnd = m_hWnd;
// 初始化串口列表
for (int i = 1; i <= 16; i++) {
CString strCom;
strCom.Format(_T("COM%d"), i);
((CComboBox*)GetDlgItem(IDC_COMBO_COM))->AddString(strCom);
}
((CComboBox*)GetDlgItem(IDC_COMBO_COM))->SetCurSel(0);
// 初始化波特率列表
((CComboBox*)GetDlgItem(IDC_COMBO_BAUDRATE))->AddString(_T("1200"));
((CComboBox*)GetDlgItem(IDC_COMBO_BAUDRATE))->AddString(_T("2400"));
((CComboBox*)GetDlgItem(IDC_COMBO_BAUDRATE))->AddString(_T("4800"));
((CComboBox*)GetDlgItem(IDC_COMBO_BAUDRATE))->AddString(_T("9600"));
((CComboBox*)GetDlgItem(IDC_COMBO_BAUDRATE))->AddString(_T("19200"));
((CComboBox*)GetDlgItem(IDC_COMBO_BAUDRATE))->AddString(_T("38400"));
((CComboBox*)GetDlgItem(IDC_COMBO_BAUDRATE))->AddString(_T("57600"));
((CComboBox*)GetDlgItem(IDC_COMBO_BAUDRATE))->AddString(_T("115200"));
((CComboBox*)GetDlgItem(IDC_COMBO_BAUDRATE))->SetCurSel(3);
// 初始化数据位列表
((CComboBox*)GetDlgItem(IDC_COMBO_DATABITS))->AddString(_T("5"));
((CComboBox*)GetDlgItem(IDC_COMBO_DATABITS))->AddString(_T("6"));
((CComboBox*)GetDlgItem(IDC_COMBO_DATABITS))->AddString(_T("7"));
((CComboBox*)GetDlgItem(IDC_COMBO_DATABITS))->AddString(_T("8"));
((CComboBox*)GetDlgItem(IDC_COMBO_DATABITS))->SetCurSel(3);
// 初始化停止位列表
((CComboBox*)GetDlgItem(IDC_COMBO_STOPBITS))->AddString(_T("1"));
((CComboBox*)GetDlgItem(IDC_COMBO_STOPBITS))->AddString(_T("1.5"));
((CComboBox*)GetDlgItem(IDC_COMBO_STOPBITS))->AddString(_T("2"));
((CComboBox*)GetDlgItem(IDC_COMBO_STOPBITS))->SetCurSel(0);
// 初始化校验位列表
((CComboBox*)GetDlgItem(IDC_COMBO_PARITY))->AddString(_T("无"));
((CComboBox*)GetDlgItem(IDC_COMBO_PARITY))->AddString(_T("奇校验"));
((CComboBox*)GetDlgItem(IDC_COMBO_PARITY))->AddString(_T("偶校验"));
((CComboBox*)GetDlgItem(IDC_COMBO_PARITY))->SetCurSel(0);
return TRUE; // return TRUE unless you set the focus to a control
}
void CSerialPortTestDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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
{
CDialogEx::OnPaint();
}
}
HCURSOR CSerialPortTestDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CSerialPortTestDlg::OnBnClickedButtonOpen()
{
// 获取串口参数
CString strCom, strBaudrate, strDatabits, strStopbits, strParity;
((CComboBox*)GetDlgItem(IDC_COMBO_COM))->GetWindowText(strCom);
((CComboBox*)GetDlgItem(IDC_COMBO_BAUDRATE))->GetWindowText(strBaudrate);
((CComboBox*)GetDlgItem(IDC_COMBO_DATABITS))->GetWindowText(strDatabits);
((CComboBox*)GetDlgItem(IDC_COMBO_STOPBITS))->GetWindowText(strStopbits);
((CComboBox*)GetDlgItem(IDC_COMBO_PARITY))->GetWindowText(strParity);
// 设置串口参数
m_pSerial->m_nComPort = _ttoi(&strCom.Right(1));
m_pSerial->m_nBaud = _ttoi(strBaudrate);
if (strDatabits == _T("5")) {
m_pSerial->m_nDataBits = 5;
}
else if (strDatabits == _T("6")) {
m_pSerial->m_nDataBits = 6;
}
else if (strDatabits == _T("7")) {
m_pSerial->m_nDataBits = 7;
}
else if (strDatabits == _T("8")) {
m_pSerial->m_nDataBits = 8;
}
if (strStopbits == _T("1")) {
m_pSerial->m_nStopBits = ONESTOPBIT;
}
else if (strStopbits == _T("1.5")) {
m_pSerial->m_nStopBits = ONE5STOPBITS;
}
else if (strStopbits == _T("2")) {
m_pSerial->m_nStopBits = TWOSTOPBITS;
}
if (strParity == _T("无")) {
m_pSerial->m_nParity = NOPARITY;
}
else if (strParity == _T("奇校验")) {
m_pSerial->m_nParity = ODDPARITY;
}
else if (strParity == _T("偶校验")) {
m_pSerial->m_nParity = EVENPARITY;
}
// 打开串口
if (m_pSerial->Open()) {
GetDlgItem(IDC_BUTTON_OPEN)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_CLOSE)->EnableWindow(TRUE);
}
else {
AfxMessageBox(_T("无法打开串口!"));
}
}
void CSerialPortTestDlg::OnBnClickedButtonClose()
{
// 关闭串口
m_pSerial->Close();
GetDlgItem(IDC_BUTTON_OPEN)->EnableWindow(TRUE);
GetDlgItem(IDC_BUTTON_CLOSE)->EnableWindow(FALSE);
}
void CSerialPortTestDlg::OnBnClickedButtonSend()
{
// 发送数据
UpdateData(TRUE);
m_pSerial->Write((LPCTSTR)m_strSend, m_strSend.GetLength());
}
afx_msg LRESULT CSerialPortTestDlg::OnCommRxChar(WPARAM wParam, LPARAM lParam)
{
// 接收数据
BYTE szBuf[4096];
int nCount = m_pSerial->Read(szBuf, 4096);
if (nCount > 0) {
szBuf[nCount] = 0;
m_strReceive += (LPCTSTR)szBuf;
UpdateData(FALSE);
}
return 0;
}
```
需要注意的是,本程序使用了一个名为“CSerialPort”的类来实现串口的打开、关闭、发送和接收数据的功能。该类的实现代码如下:
```
class CSerialPort
{
public:
CSerialPort() {
m_hComm = NULL;
m_hWnd = NULL;
m_nComPort = 1;
m_nBaud = 9600;
m_nDataBits = 8;
m_nStopBits = ONESTOPBIT;
m_nParity = NOPARITY;
}
~CSerialPort() {
Close();
}
BOOL Open() {
Close();
CString strCom;
strCom.Format(_T("\\\\.\\COM%d"), m_nComPort);
m_hComm = CreateFile(strCom, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (m_hComm == INVALID_HANDLE_VALUE) {
return FALSE;
}
DCB dcb;
GetCommState(m_hComm, &dcb);
dcb.BaudRate = m_nBaud;
dcb.ByteSize = m_nDataBits;
dcb.StopBits = m_nStopBits;
dcb.Parity = m_nParity;
SetCommState(m_hComm, &dcb);
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(m_hComm, &timeouts);
SetCommMask(m_hComm, EV_RXCHAR);
return TRUE;
}
void Close() {
if (m_hComm) {
CloseHandle(m_hComm);
m_hComm = NULL;
}
}
int Read(LPBYTE lpBuf, int nCount) {
DWORD dwRead = 0;
if (m_hComm && ReadFile(m_hComm, lpBuf, nCount, &dwRead, NULL)) {
return (int)dwRead;
}
return 0;
}
BOOL Write(LPCTSTR lpBuf, int nCount) {
DWORD dwWritten = 0;
if (m_hComm && WriteFile(m_hComm, lpBuf, nCount, &dwWritten, NULL)) {
return TRUE;
}
return FALSE;
}
HWND m_hWnd;
int m_nComPort;
int m_nBaud;
int m_nDataBits;
int m_nStopBits;
int m_nParity;
protected:
HANDLE m_hComm;
};
```
该类的实现使用了Win32 API中的串口相关函数,可以通过修改该类的实现来适应不同的需求。