当前位置: 首页 > news >正文

【51】MFC入门到精通——MFC串口助手(一)---初级版(串口设置、初始化、打开/关闭、状态显示),附源码

文章目录

  • 1 功能展示
  • 2 实现步骤
    • 2.1 添加控件 及 控件变量
    • 2.2 添加按钮及静态文本框
    • 2.3 声明其他变量 及 函数
  • 3 函数实现
    • 3.1 初始刷函数
    • 3.2 设置串口参数
    • 3.3 打开串口函数
    • 3.4 显示串口状态
    • 3.5 关闭串口
    • 3.6 更改串口、波特率、校验位、数据位、停止位
    • 3.7 串口状态显示
  • 4 完整代码
    • 4.1 ...Dlg.h文件
    • 4.2 ...Dlg.cpp文件
  • 5 小改进
  • 6 完整MFC项目项下载

1 功能展示

实现串口通信的上位机。
在这里插入图片描述

2 实现步骤

2.1 添加控件 及 控件变量

在工具栏中 拖拽5个 Combobox 控件,和5个 Static Text控件,
排好序,并如下命名;
在这里插入图片描述

给5个 Combobox 控件,分别添加以下控件变量 和 值变量 (通过右键控件,弹出的窗口添加)

//控件 列表框变量	
m_Combo_Com;				//列表框:串口
m_Combo_Baud;			//列表框:波特率
m_Combo_Check;			//列表框:校验位
m_Combo_Data;				//列表框:数据位
m_Combo_Stop;				//列表框:停止位//值 字符变量
m_Str_Com;					//字符变量:串口
m_Str_Baud;					//字符变量:波特率
m_Str_Check;				   //字符变量:校验位
m_Str_Data;			 	  //字符变量:数据位
m_Str_Stop;				  //字符变量:停止位

…Dlg.h文件中 会多出10行;
在这里插入图片描述

…Dlg.cpp文件中 会多出以下代码

在这里插入图片描述

2.2 添加按钮及静态文本框

添加4个 Static Text控件,和一个 Button 按钮
在这里插入图片描述
其ID命名如下

IDC_COMSTATUS_STATIC
IDC_PORTisOPEN_STATIC
IDC_TXLEN_STATIC
IDC_RXLEN_STATIC
IDC_OPENCOM_BUTTON

定义两个变量

public://自定义变量long			m_rxlen;				//接收数据个数long			m_txlen;				//发送数据个数

2.3 声明其他变量 及 函数

Dlg.h文件中 所有用户生成或添加的 变量及函数

public://自定义变量HANDLE			m_hCom;					//串口句柄volatile int	m_bConnected;			//串口连接成功指示BOOL			m_COMStatu;				//串口状态指示long			m_rxlen;				//接收数据个数long			m_txlen;				//发送数据个数//列表框变量CComboBox	m_Combo_Com;				//列表框:串口CComboBox	m_Combo_Baud;				//列表框:波特率CComboBox	m_Combo_Check;				//列表框:校验位CComboBox	m_Combo_Data;				//列表框:数据位CComboBox	m_Combo_Stop;				//列表框:停止位//字符变量CString		m_Str_Com;					//字符变量:串口CString		m_Str_Baud;					//字符变量:波特率CString		m_Str_Check;				//字符变量:校验位CString		m_Str_Data;					//字符变量:数据位CString		m_Str_Stop;					//字符变量:停止位//函数=====================================================================================
public://串口相关函数BOOL OpenComm(int Num);								//打开串口BOOL SetCommParameter();							//设置串口参数void DisplayStatus();								//显示串口状态void CloseConnection();								//关闭串口//按钮函数afx_msg void OnBnClickedOpencomButton();			//串口状态显示//列表框函数afx_msg void OnCbnSelchangeComboCom();				//更改串口afx_msg void OnCbnSelchangeComboBaud();				//更改波特率afx_msg void OnCbnSelchangeComboCheck();			//更改校验位afx_msg void OnCbnSelchangeComboData();				//更改数据位afx_msg void OnCbnSelchangeComboStop();				//更改停止位

3 函数实现

3.1 初始刷函数

在OnInitDialog()函数中添加

// TODO: 在此添加额外的初始化代码//========================================== = 初始化对话框========================================== =//设串口组合列表框TCHAR com[][6] = {_T("COM1"),_T("COM2"),_T("COM3"),_T("COM4"),_T("COM5"),_T("COM6"),_T("COM7"),_T("COM8"),_T("COM9") };for (int i = 0; i < 9; i++)m_Combo_Com.AddString(com[i]);m_Combo_Com.SetCurSel(0);//默认显示第1个串口号//设波特率组合列表框TCHAR baud[][7] = {_T("9600"),_T("19200"),_T("38400"),_T("43000"),_T("56000"),_T("57600"),_T("115200"),_T("128000"),_T("230400") };for (int i = 0; i < 9; i++)m_Combo_Baud.AddString(baud[i]);m_Combo_Baud.SetCurSel(5);//默认显示第6个波特率//设校验位组合列表框TCHAR check[][7] = {_T("None"),_T("Odd"),_T("Even") };for (int i = 0; i < 3; i++)m_Combo_Check.AddString(check[i]);m_Combo_Check.SetCurSel(0);//默认显示无校验//设数据位组合列表框TCHAR data[][2] = {_T("8"),_T("7"),_T("6") };for (int i = 0; i < 3; i++)m_Combo_Data.AddString(data[i]);m_Combo_Data.SetCurSel(0);//设停止位组合列表框TCHAR stop[][2] = { _T("1"),_T("2") };for (int i = 0; i < 2; i++)m_Combo_Stop.AddString(stop[i]);m_Combo_Stop.SetCurSel(0);//打开串口函数赋初值OpenComm(0);

3.2 设置串口参数

/==============================================设置串口参数==============================================
//设置串口参数
BOOL CSerialPortDlg::SetCommParameter()
{DCB dcb;	//DCB结构,定义了串口通信设备的控制设置if (!GetCommState(m_hCom, &dcb))//读取新创建的 m_hCom串口句柄的 DCB设备控制块结构体,当只需要设置一部分 DCB参数时,可以通过此函数读取现有参数,只改变部分参数即可return FALSE;	//如果读取不成功直接结束//设置波特率long baudrate[] = { 300,600,1200,2400,4800,9600,19200,38400,43000,56000,57600,115200,128000,230400 };int baudindex = m_Combo_Baud.GetCurSel();m_Combo_Baud.GetLBText(baudindex, m_Str_Baud);dcb.BaudRate = baudrate[baudindex];//读取并设置波特率参数//设置数据位int databit[] = { 8,7,6 };int dataindex = m_Combo_Data.GetCurSel();m_Combo_Data.GetLBText(dataindex, m_Str_Data);dcb.ByteSize = databit[dataindex];//设置校验位int checkindex = m_Combo_Check.GetCurSel();m_Combo_Check.GetLBText(checkindex, m_Str_Check);switch (checkindex){case 0: dcb.Parity = NOPARITY; break;case 1: dcb.Parity = ODDPARITY; break;case 2: dcb.Parity = EVENPARITY; break;default:;}//设置停止位int stopindex = m_Combo_Stop.GetCurSel();m_Combo_Stop.GetLBText(stopindex, m_Str_Stop);switch (stopindex){case 0: dcb.StopBits = ONESTOPBIT; break;case 1: dcb.StopBits = TWOSTOPBITS; break;default:;}//流控制 dcb.fInX = FALSE;dcb.fOutX = FALSE;dcb.fNull = FALSE;	//为TRUE时,接收时自动去掉空(0值)字节dcb.fBinary = TRUE;	//指定是否允许二进制模式。Win32 API不支持非二进制模式传输,应设置为true dcb.fParity = FALSE;dcb.fOutxCtsFlow = FALSE;dcb.fOutxDsrFlow = FALSE;return(SetCommState(m_hCom, &dcb)); //应用设置
}

3.3 打开串口函数

/==============================================打开串口==============================================
//打开串口函数
BOOL CSerialPortDlg::OpenComm(int Num)
{m_Combo_Com.GetLBText(Num, m_Str_Com);//获取串口Combo下拉框中对应于Num位置的串口名称,比如Num=0时,m_SeriouStr 为"COM1"m_hCom = CreateFile(m_Str_Com, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);//将串口作为一个文件来看,用CreateFile()函数打开串口,返回结果存储在m_hCom中if (m_hCom == INVALID_HANDLE_VALUE)//如果返回INVALID_HANDLE_VALUE表示打开串口失败,{AfxMessageBox(_T("打开串口失败!"));	//失败时弹出对话框提醒m_bConnected = 0;				    //将串口连接标志设为0return FALSE;					    //打开失败后不再继续往下进行,直接返回FALSE}m_bConnected = 1;	//将串口连接标志设为1return 0;
}

3.4 显示串口状态

//============================================显示串口状态============================================
//显示串口状态
void CSerialPortDlg::DisplayStatus()
{CWnd* static_status = GetDlgItem(IDC_COMSTATUS_STATIC);CWnd* static_txlen  = GetDlgItem(IDC_TXLEN_STATIC);CWnd* static_rxlen  = GetDlgItem(IDC_RXLEN_STATIC);CString status_str, txlen_str, rxlen_str;if (m_bConnected){status_str = _T("STATUS:") + m_Str_Com + " OPENED," + m_Str_Baud + ',' + m_Str_Check + ',' + m_Str_Data + ',' + m_Str_Stop;SetCommParameter();}elsestatus_str = _T("STATUS:") + m_Str_Com + " CLOSED," + m_Str_Baud + ',' + m_Str_Check + ',' + m_Str_Data + ',' + m_Str_Stop;static_status->SetWindowText(status_str);txlen_str.Format(_T("TX: % ld"), m_txlen);static_txlen->SetWindowText(txlen_str);rxlen_str.Format(_T("RX:%ld"), m_rxlen);static_rxlen->SetWindowText(rxlen_str);
}

3.5 关闭串口

//==============================================关闭串口==============================================
//关闭串口
void CSerialPortDlg::CloseConnection()
{if (!m_bConnected)return;m_bConnected = FALSE;SetCommMask(m_hCom, 0);CloseHandle(m_hCom);
}

3.6 更改串口、波特率、校验位、数据位、停止位

//==============================================更改串口设置==============================================
//更改串口
void CSerialPortDlg::OnCbnSelchangeComboCom()
{// TODO: 在此添加控件通知处理程序代码if (m_bConnected)CloseConnection();if (m_COMStatu){int i = m_Combo_Com.GetCurSel();OpenComm(i);}DisplayStatus();
}//更改波特率
void CSerialPortDlg::OnCbnSelchangeComboBaud()
{// TODO: 在此添加控件通知处理程序代码int baudindex;baudindex = m_Combo_Baud.GetCurSel();if (baudindex != CB_ERR){SetCommParameter();//把索引号为baudindex的数据放到m_Str_Baud变量中,传给m_Combo_Baud控件m_Combo_Baud.GetLBText(baudindex, m_Str_Baud); }DisplayStatus();
}//更改校验位
void CSerialPortDlg::OnCbnSelchangeComboCheck()
{// TODO: 在此添加控件通知处理程序代码int checkindex;checkindex = m_Combo_Check.GetCurSel();if (checkindex != CB_ERR){SetCommParameter();m_Combo_Check.GetLBText(checkindex, m_Str_Check);DisplayStatus();}
}//更改数据位
void CSerialPortDlg::OnCbnSelchangeComboData()
{// TODO: 在此添加控件通知处理程序代码int dataindex;dataindex = m_Combo_Data.GetCurSel();if (dataindex != CB_ERR){SetCommParameter();m_Combo_Data.GetLBText(dataindex, m_Str_Data);DisplayStatus();}
}//更改停止位
void CSerialPortDlg::OnCbnSelchangeComboStop()
{// TODO: 在此添加控件通知处理程序代码int stopindex;stopindex = m_Combo_Stop.GetCurSel();if (stopindex != CB_ERR){SetCommParameter();m_Combo_Stop.GetLBText(stopindex, m_Str_Stop);DisplayStatus();}
}

3.7 串口状态显示

//==========================================串口开关按钮状态显示==========================================
//串口状态显示
void CSerialPortDlg::OnBnClickedOpencomButton()
{// TODO: 在此添加控件通知处理程序代码m_COMStatu = !m_COMStatu;if (!m_COMStatu)GetDlgItem(IDC_PORTisOPEN_STATIC)->SetWindowText(_T("串口状态:串口已关闭"));elseGetDlgItem(IDC_PORTisOPEN_STATIC)->SetWindowText(_T("串口状态:串口已打开"));OnCbnSelchangeComboCom();DisplayStatus();return;
}

4 完整代码

4.1 …Dlg.h文件


// SerialPortDlg.h: 头文件
//#pragma once// CSerialPortDlg 对话框
class CSerialPortDlg : public CDialogEx
{
// 构造
public:CSerialPortDlg(CWnd* pParent = nullptr);	// 标准构造函数//变量=====================================================================================
public://自定义变量HANDLE			m_hCom;					//串口句柄volatile int	m_bConnected;			//串口连接成功指示BOOL			m_COMStatu;				//串口状态指示long			m_rxlen;				//接收数据个数long			m_txlen;				//发送数据个数//列表框变量CComboBox	m_Combo_Com;				//列表框:串口CComboBox	m_Combo_Baud;				//列表框:波特率CComboBox	m_Combo_Check;				//列表框:校验位CComboBox	m_Combo_Data;				//列表框:数据位CComboBox	m_Combo_Stop;				//列表框:停止位//字符变量CString		m_Str_Com;					//字符变量:串口CString		m_Str_Baud;					//字符变量:波特率CString		m_Str_Check;				//字符变量:校验位CString		m_Str_Data;					//字符变量:数据位CString		m_Str_Stop;					//字符变量:停止位//函数=====================================================================================
public://串口相关函数BOOL OpenComm(int Num);								//打开串口BOOL SetCommParameter();							//设置串口参数void DisplayStatus();								//显示串口状态void CloseConnection();								//关闭串口//按钮函数afx_msg void OnBnClickedOpencomButton();			//串口状态显示//列表框函数afx_msg void OnCbnSelchangeComboCom();				//更改串口afx_msg void OnCbnSelchangeComboBaud();				//更改波特率afx_msg void OnCbnSelchangeComboCheck();			//更改校验位afx_msg void OnCbnSelchangeComboData();				//更改数据位afx_msg void OnCbnSelchangeComboStop();				//更改停止位// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_SERIALPORT_DIALOG };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持// 实现
protected:HICON m_hIcon;// 生成的消息映射函数virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()};

4.2 …Dlg.cpp文件


// SerialPortDlg.cpp: 实现文件
//#include "pch.h"
#include "framework.h"
#include "SerialPort.h"
#include "SerialPortDlg.h"
#include "afxdialogex.h"#ifdef _DEBUG
#define new DEBUG_NEW
#endif// 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialogEx
{
public:CAboutDlg();// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_ABOUTBOX };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现
protected:DECLARE_MESSAGE_MAP()
};CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()// CSerialPortDlg 对话框CSerialPortDlg::CSerialPortDlg(CWnd* pParent /*=nullptr*/): CDialogEx(IDD_SERIALPORT_DIALOG, pParent), m_Str_Com(_T("")), m_Str_Baud(_T("")), m_Str_Check(_T("")), m_Str_Data(_T("")), m_Str_Stop(_T(""))
{m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CSerialPortDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDC_COMBO1, m_Combo_Com);DDX_Control(pDX, IDC_COMBO2, m_Combo_Baud);DDX_Control(pDX, IDC_COMBO3, m_Combo_Check);DDX_Control(pDX, IDC_COMBO4, m_Combo_Data);DDX_Control(pDX, IDC_COMBO5, m_Combo_Stop);DDX_CBString(pDX, IDC_COMBO1, m_Str_Com);DDX_CBString(pDX, IDC_COMBO2, m_Str_Baud);DDX_CBString(pDX, IDC_COMBO3, m_Str_Check);DDX_CBString(pDX, IDC_COMBO4, m_Str_Data);DDX_CBString(pDX, IDC_COMBO5, m_Str_Stop);
}BEGIN_MESSAGE_MAP(CSerialPortDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_OPENCOM_BUTTON, &CSerialPortDlg::OnBnClickedOpencomButton)
END_MESSAGE_MAP()// CSerialPortDlg 消息处理程序BOOL CSerialPortDlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != nullptr){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);			// 设置大图标SetIcon(m_hIcon, FALSE);		// 设置小图标// TODO: 在此添加额外的初始化代码//========================================== = 初始化对话框========================================== =//设串口组合列表框TCHAR com[][6] = {_T("COM1"),_T("COM2"),_T("COM3"),_T("COM4"),_T("COM5"),_T("COM6"),_T("COM7"),_T("COM8"),_T("COM9") };for (int i = 0; i < 9; i++)m_Combo_Com.AddString(com[i]);m_Combo_Com.SetCurSel(0);//默认显示第1个串口号//设波特率组合列表框TCHAR baud[][7] = {_T("9600"),_T("19200"),_T("38400"),_T("43000"),_T("56000"),_T("57600"),_T("115200"),_T("128000"),_T("230400") };for (int i = 0; i < 9; i++)m_Combo_Baud.AddString(baud[i]);m_Combo_Baud.SetCurSel(5);//默认显示第6个波特率//设校验位组合列表框TCHAR check[][7] = {_T("None"),_T("Odd"),_T("Even") };for (int i = 0; i < 3; i++)m_Combo_Check.AddString(check[i]);m_Combo_Check.SetCurSel(0);//默认显示无校验//设数据位组合列表框TCHAR data[][2] = {_T("8"),_T("7"),_T("6") };for (int i = 0; i < 3; i++)m_Combo_Data.AddString(data[i]);m_Combo_Data.SetCurSel(0);//设停止位组合列表框TCHAR stop[][2] = { _T("1"),_T("2") };for (int i = 0; i < 2; i++)m_Combo_Stop.AddString(stop[i]);m_Combo_Stop.SetCurSel(0);//打开串口函数赋初值OpenComm(0);return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}void CSerialPortDlg::OnSysCommand(UINT nID, LPARAM lParam)
{if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialogEx::OnSysCommand(nID, lParam);}
}// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。void CSerialPortDlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中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;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}
}//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CSerialPortDlg::OnQueryDragIcon()
{return static_cast<HCURSOR>(m_hIcon);
}//==============================================设置串口参数==============================================
//设置串口参数
BOOL CSerialPortDlg::SetCommParameter()
{DCB dcb;	//DCB结构,定义了串口通信设备的控制设置if (!GetCommState(m_hCom, &dcb))//读取新创建的 m_hCom串口句柄的 DCB设备控制块结构体,当只需要设置一部分 DCB参数时,可以通过此函数读取现有参数,只改变部分参数即可return FALSE;	//如果读取不成功直接结束//设置波特率long baudrate[] = { 300,600,1200,2400,4800,9600,19200,38400,43000,56000,57600,115200,128000,230400 };int baudindex = m_Combo_Baud.GetCurSel();m_Combo_Baud.GetLBText(baudindex, m_Str_Baud);dcb.BaudRate = baudrate[baudindex];//读取并设置波特率参数//设置数据位int databit[] = { 8,7,6 };int dataindex = m_Combo_Data.GetCurSel();m_Combo_Data.GetLBText(dataindex, m_Str_Data);dcb.ByteSize = databit[dataindex];//设置校验位int checkindex = m_Combo_Check.GetCurSel();m_Combo_Check.GetLBText(checkindex, m_Str_Check);switch (checkindex){case 0: dcb.Parity = NOPARITY; break;case 1: dcb.Parity = ODDPARITY; break;case 2: dcb.Parity = EVENPARITY; break;default:;}//设置停止位int stopindex = m_Combo_Stop.GetCurSel();m_Combo_Stop.GetLBText(stopindex, m_Str_Stop);switch (stopindex){case 0: dcb.StopBits = ONESTOPBIT; break;case 1: dcb.StopBits = TWOSTOPBITS; break;default:;}//流控制 dcb.fInX = FALSE;dcb.fOutX = FALSE;dcb.fNull = FALSE;	//为TRUE时,接收时自动去掉空(0值)字节dcb.fBinary = TRUE;	//指定是否允许二进制模式。Win32 API不支持非二进制模式传输,应设置为true dcb.fParity = FALSE;dcb.fOutxCtsFlow = FALSE;dcb.fOutxDsrFlow = FALSE;return(SetCommState(m_hCom, &dcb)); //应用设置
}//==============================================打开串口==============================================
//打开串口函数
BOOL CSerialPortDlg::OpenComm(int Num)
{m_Combo_Com.GetLBText(Num, m_Str_Com);//获取串口Combo下拉框中对应于Num位置的串口名称,比如Num=0时,m_SeriouStr 为"COM1"m_hCom = CreateFile(m_Str_Com, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);//将串口作为一个文件来看,用CreateFile()函数打开串口,返回结果存储在m_hCom中if (m_hCom == INVALID_HANDLE_VALUE)//如果返回INVALID_HANDLE_VALUE表示打开串口失败,{AfxMessageBox(_T("打开串口失败!"));	//失败时弹出对话框提醒m_bConnected = 0;				    //将串口连接标志设为0return FALSE;					    //打开失败后不再继续往下进行,直接返回FALSE}m_bConnected = 1;	//将串口连接标志设为1return 0;
}//============================================显示串口状态============================================
//显示串口状态
void CSerialPortDlg::DisplayStatus()
{CWnd* static_status = GetDlgItem(IDC_COMSTATUS_STATIC);CWnd* static_txlen  = GetDlgItem(IDC_TXLEN_STATIC);CWnd* static_rxlen  = GetDlgItem(IDC_RXLEN_STATIC);CString status_str, txlen_str, rxlen_str;if (m_bConnected){status_str = _T("STATUS:") + m_Str_Com + " OPENED," + m_Str_Baud + ',' + m_Str_Check + ',' + m_Str_Data + ',' + m_Str_Stop;SetCommParameter();}elsestatus_str = _T("STATUS:") + m_Str_Com + " CLOSED," + m_Str_Baud + ',' + m_Str_Check + ',' + m_Str_Data + ',' + m_Str_Stop;static_status->SetWindowText(status_str);txlen_str.Format(_T("TX: % ld"), m_txlen);static_txlen->SetWindowText(txlen_str);rxlen_str.Format(_T("RX:%ld"), m_rxlen);static_rxlen->SetWindowText(rxlen_str);
}//==============================================关闭串口==============================================
//关闭串口
void CSerialPortDlg::CloseConnection()
{if (!m_bConnected)return;m_bConnected = FALSE;SetCommMask(m_hCom, 0);CloseHandle(m_hCom);
}//==============================================更改串口设置==============================================
//更改串口
void CSerialPortDlg::OnCbnSelchangeComboCom()
{// TODO: 在此添加控件通知处理程序代码if (m_bConnected)CloseConnection();if (m_COMStatu){int i = m_Combo_Com.GetCurSel();OpenComm(i);}DisplayStatus();
}//更改波特率
void CSerialPortDlg::OnCbnSelchangeComboBaud()
{// TODO: 在此添加控件通知处理程序代码int baudindex;baudindex = m_Combo_Baud.GetCurSel();if (baudindex != CB_ERR){SetCommParameter();//把索引号为baudindex的数据放到m_Str_Baud变量中,传给m_Combo_Baud控件m_Combo_Baud.GetLBText(baudindex, m_Str_Baud); }DisplayStatus();
}//更改校验位
void CSerialPortDlg::OnCbnSelchangeComboCheck()
{// TODO: 在此添加控件通知处理程序代码int checkindex;checkindex = m_Combo_Check.GetCurSel();if (checkindex != CB_ERR){SetCommParameter();m_Combo_Check.GetLBText(checkindex, m_Str_Check);DisplayStatus();}
}//更改数据位
void CSerialPortDlg::OnCbnSelchangeComboData()
{// TODO: 在此添加控件通知处理程序代码int dataindex;dataindex = m_Combo_Data.GetCurSel();if (dataindex != CB_ERR){SetCommParameter();m_Combo_Data.GetLBText(dataindex, m_Str_Data);DisplayStatus();}
}//更改停止位
void CSerialPortDlg::OnCbnSelchangeComboStop()
{// TODO: 在此添加控件通知处理程序代码int stopindex;stopindex = m_Combo_Stop.GetCurSel();if (stopindex != CB_ERR){SetCommParameter();m_Combo_Stop.GetLBText(stopindex, m_Str_Stop);DisplayStatus();}
}//==========================================串口开关按钮状态显示==========================================
//串口状态显示
void CSerialPortDlg::OnBnClickedOpencomButton()
{// TODO: 在此添加控件通知处理程序代码m_COMStatu = !m_COMStatu;if (!m_COMStatu)GetDlgItem(IDC_PORTisOPEN_STATIC)->SetWindowText(_T("串口状态:串口已关闭"));elseGetDlgItem(IDC_PORTisOPEN_STATIC)->SetWindowText(_T("串口状态:串口已打开"));OnCbnSelchangeComboCom();DisplayStatus();return;
}

5 小改进

可以将 OnInitDialog() 函数中 串口初始化 部分进行 独立函数 封装

//初始化串口
BOOL CSerialPortDlg::InitComm()
{//设串口组合列表框TCHAR com[][6] = { _T("COM1"),_T("COM2"),_T("COM3"),_T("COM4"),_T("COM5"),_T("COM6"),_T("COM7"),_T("COM8"),_T("COM9") };for (int i = 0; i < 9; i++)m_Combo_Com.AddString(com[i]);m_Combo_Com.SetCurSel(0);//默认显示第1个串口号//设波特率组合列表框TCHAR baud[][7] = { _T("9600"),_T("19200"),_T("38400"),_T("43000"),_T("56000"),_T("57600"),_T("115200"),_T("128000"),_T("230400") };for (int i = 0; i < 9; i++)m_Combo_Baud.AddString(baud[i]);m_Combo_Baud.SetCurSel(5);//默认显示第6个波特率//设校验位组合列表框TCHAR check[][7] = { _T("None"),_T("Odd"),_T("Even") };for (int i = 0; i < 3; i++)m_Combo_Check.AddString(check[i]);m_Combo_Check.SetCurSel(0);//默认显示无校验//设数据位组合列表框TCHAR data[][2] = { _T("8"),_T("7"),_T("6") };for (int i = 0; i < 3; i++)m_Combo_Data.AddString(data[i]);m_Combo_Data.SetCurSel(0);//设停止位组合列表框TCHAR stop[][2] = { _T("1"),_T("2") };for (int i = 0; i < 2; i++)m_Combo_Stop.AddString(stop[i]);m_Combo_Stop.SetCurSel(0);return true;
}

6 完整MFC项目项下载

MFC串口助手初级版实现(串口设置、初始化、打开、关闭、状态显示)—代码注释非常详细

http://www.dtcms.com/a/285907.html

相关文章:

  • Java异步日志系统性能优化实践指南:基于Log4j2异步Appender与Disruptor
  • 鸿蒙实现一次上传多张图片
  • 物流3D工业相机:解锁自动化物流新纪元
  • 第三章-提示词-初级:一文带你入门提示词工程,开启AI高效交互之旅(11/36)
  • [Python] -实用技巧8-解锁 Python 中的 lambda 表达式用法
  • GISBox切片器技术解析:RVT模型到3DTiles瓦片的高性能转换方案
  • 内存数据库的持久化与恢复策略:数据安全性与重启速度的平衡点
  • QT窗口(3)-状态栏
  • 菱形继承 虚继承
  • vue-router
  • 前端篇——番外篇 Bootstrap框架
  • 【密码学】1. 引言
  • c++继承详解
  • 【物联网】基于树莓派的物联网开发【12】——树莓派硬件GPIO模块原理知识
  • 模式结构-微服务架构设计模式
  • 【PTA数据结构 | C语言版】二叉堆的快速建堆操作
  • 一文讲清楚React性能优化
  • mysql 性能优化之Explain讲解
  • RHEL/CentOS 的系统安装程序界面介绍
  • 周志华《机器学习导论》第9章 聚类
  • 分布式面试点
  • 算法-动态规划
  • MyBatis缓存实战指南:一级与二级缓存的深度解析与性能优化
  • 分布式短剧平台核心技术解析:CDN优化、AI推荐与多语言支付集成
  • 在 ASP.NET Core 和 JavaScript 中配置 WebSocket
  • Jfinal+SQLite处理 sqlite数据库执行FIND_IN_SET报错
  • .NET 8 Release Candidate 1 (RC1)现已发布,包括许多针对ASP.NET Core的重要改进!
  • 从复合变量到分组分析:piecewiseSEM 解析生态系统多因子交互作用
  • 深度剖析:最新发布的ChatGPT Agent 技术架构与应用场景
  • 专题:2025智能体研究报告|附70份报告PDF、原数据表汇总下载