当前位置: 首页 > 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 串口参数 与预设不完全一致
  • 5 完整代码
    • 5.1 ...Dlg.h文件
    • 4.2 ...Dlg.cpp文件
  • 6 小改进
  • 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(2);//默认显示第3个波特率//设校验位组合列表框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[] = {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 串口参数 与预设不完全一致

我们预期是:串口号COM1,波特率38400,校验None,数据8,停止位1;
但实际效果:波特率19200、校验Even、数据6显示的不对。
在这里插入图片描述
解决办法:
【52】MFC入门到精通——(CComboBox)下拉框选项顺序与初始化不一致,默认显示项也不一致

5 完整代码

5.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(2);//默认显示第3个波特率//设校验位组合列表框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[] = {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;
}

6 小改进

可以将 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(2);//默认显示第3个波特率//设校验位组合列表框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.xdnf.cn/news/1146385.html

相关文章:

  • 机器学习基础:线性回归算法详解(原理+代码+实战)
  • Proto文件从入门到精通——现代分布式系统通信的基石(含实战案例)
  • 数据库模型异常问题深度解析:冗余与操作异常
  • 柴油机活塞cad【4张】三维图+设计说明书
  • 小架构step系列18:工具
  • 《每日AI-人工智能-编程日报》--2025年7月18日
  • 【洛谷P1417】烹调方案 题解
  • SQL注入基础尝试
  • 71 模块编程之新增一个字符设备
  • ArcGIS Pro+PS 实现地形渲染效果图
  • 上网行为管理-web认证服务
  • 【C++基础】--多态
  • ThreadLocal 在 Spring 与数据库交互中的应用笔记
  • 北京-4年功能测试2年空窗-报培训班学测开-第五十四天
  • Kubernetes Pod深度理解
  • 大模型格式
  • 外部DLL创建及使用
  • UVC for USBCamera in Android - 篇二
  • 腾讯 ChatBI 调研
  • 如何为“地方升学导向型”语校建模?Prompt 框架下的宇都宫日建工科专门学校解析(7 / 500)
  • Java HashMap高频面试题深度解析
  • 对于编码电机-520直流减速电机
  • 【AI News | 20250717】每日AI进展
  • 3.3 参数传递方式
  • 应用集成体系深度解析:从数据互通到流程协同
  • 20250718【顺着234回文链表做两题反转】Leetcodehot100之20692【直接过12明天吧】今天计划
  • Machine Learning HW2 report:语音辨识(Hongyi Lee)
  • 操作系统-处理机调度和死锁进程同步
  • 全球天气预报5天(经纬度版)免费API接口教程
  • HarmonyOS-ArkUI Web控件基础铺垫4--TCP协议- 断联-四次挥手解析