文章目录
- 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串口助手初级版实现(串口设置、初始化、打开、关闭、状态显示)—代码注释非常详细