c++学习 | MFC —— 串口通信(一)串口设置


一、目标

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

二、使用步骤

1.打开串口

头文件.h中

public:
	//自定义变量
	HANDLE			m_hCom;					//串口句柄
	volatile int	m_bConnected;			//串口连接成功指示
	
public:
	//串口相关函数
	BOOL OpenComm(int Num);					//打开串口函数

源文件.cpp中

BOOL CSerialPortDlg::OnInitDialog()
{
	...
	// TODO: 在此添加额外的初始化代码
	
	//设串口组合列表框
	TCHAR com[][6] = { "COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9" };
	for (int i = 0; i < 9; i++)
	m_Combo_Com.AddString(com[i]);
	m_Combo_Com.SetCurSel(0);

	//设波特率组合列表框
	TCHAR baud[][7] = { "300","600","1200","2400","4800","9600","19200","38400","43000","56000","57600","115200","128000","230400" };
	for (int i = 0; i < 14; i++)
	m_Combo_Baud.AddString(baud[i]);
	m_Combo_Baud.SetCurSel(5);

	//设校验位组合列表框
	TCHAR check[][7] = { "None","Odd","Even" };
	for (int i = 0; i < 3; i++)
	m_Combo_Check.AddString(check[i]);
	m_Combo_Check.SetCurSel(0);

	//设数据位组合列表框
	TCHAR data[][2] = { "8","7","6" };
	for (int i = 0; i < 3; i++)
	m_Combo_Data.AddString(data[i]);
	m_Combo_Data.SetCurSel(0);

	//设停止位组合列表框
	TCHAR stop[][2] = { "1","2" };
	for (int i = 0; i < 2; i++)
	m_Combo_Stop.AddString(stop[i]);
	m_Combo_Stop.SetCurSel(0);

	//打开串口函数赋初值
	OpenComm(0);
}


//打开串口函数。
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("打开串口失败!");	//失败时弹出对话框提醒
		m_bConnected = 0;				//将串口连接标志设为0
		return FALSE;					//打开失败后不再继续往下进行,直接返回FALSE
	}
	
	m_bConnected = 1;	//将串口连接标志设为1
	return 0;
}




2.设置串口

头文件.h中

public:
	//串口相关函数
	BOOL SetCommParameter();								//设置串口参数

源文件.cpp中

//设置串口参数
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.显示串口状态

头文件.h中

void DisplayStatus();								//显示串口状态

源文件.cpp中

//显示串口状态
void CSprDlg::DisplayStatus()
{
	CWnd* static_status = GetDlgItem(IDC_STATIC_COMSTATU);
	CWnd* static_txlen = GetDlgItem(IDC_STATIC_TXLEN);
	CWnd* static_rxlen = GetDlgItem(IDC_STATIC_RXLEN);
	CString status_str, txlen_str, rxlen_str;

	if (m_bConnected)
	{
		status_str = "STATUS:" + m_Str_Com + " OPENED," + m_Str_Baud + ',' + m_Str_Check + ',' + m_Str_Data + ',' + m_Str_Stop;
		SetCommParameter();
	}
		
	else
		status_str = "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("TX:%ld", m_txlen);
	static_txlen->SetWindowText(txlen_str);

	rxlen_str.Format("RX:%ld", m_rxlen);
	static_rxlen->SetWindowText(rxlen_str);
}

3.关闭串口

头文件.h中

public:
	//串口相关函数
	void CloseConnection();									//关闭串口

源文件.cpp中

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

3.串口设置更改事件

头文件.h中

public:
	//列表框函数
	afx_msg void OnSelchangeComboCOM();			//更改串口
	afx_msg void OnSelchangeComboBaud();		//更改波特率
	afx_msg void OnSelchangeComboCheck();		//更改校验位
	afx_msg void OnSelchangeComboData();		//更改数据位
	afx_msg void OnSelchangeComboStop();		//更改停止位
	

源文件.cpp中

//更改串口
void CSprDlg::OnCbnSelchangeComboCom()
{
	// TODO: 在此添加控件通知处理程序代码
	if (m_bConnected)
		CloseConnection();
	if (m_COMStatu)
	{
		int i = m_Combo_Com.GetCurSel();
		OpenComm(i);
	}
	DisplayStatus();
}

//更改波特率
void CSprDlg::OnCbnSelchangeComboBaud()
{
	// TODO: 在此添加控件通知处理程序代码
	int baudindex;
	baudindex = m_Combo_Baud.GetCurSel();
	if (baudindex != CB_ERR)
	{
		SetCommParameter();
		m_Combo_Baud.GetLBText(baudindex, m_Str_Baud);
		
	}
	DisplayStatus();
}

//更改校验位
void CSprDlg::OnCbnSelchangeComboCheck()
{
	// TODO: 在此添加控件通知处理程序代码
	int checkindex;
	checkindex = m_Combo_Check.GetCurSel();
	if (checkindex != CB_ERR)
	{
		SetCommParameter();
		m_Combo_Check.GetLBText(checkindex, m_Str_Check);
		DisplayStatus();
	}
}

//更改数据位
void CSprDlg::OnCbnSelchangeComboData()
{
	// TODO: 在此添加控件通知处理程序代码

	int dataindex;
	dataindex = m_Combo_Data.GetCurSel();
	if (dataindex != CB_ERR)
	{
		SetCommParameter();
		m_Combo_Data.GetLBText(dataindex, m_Str_Data);
		DisplayStatus();
	}
}

//更改停止位
void CSprDlg::OnCbnSelchangeComboStop()
{
	// TODO: 在此添加控件通知处理程序代码
	int stopindex;
	stopindex = m_Combo_Stop.GetCurSel();
	if (stopindex != CB_ERR)
	{
		SetCommParameter();
		m_Combo_Stop.GetLBText(stopindex, m_Str_Stop);
		DisplayStatus();
	}
}

4.打开关闭串口按钮

头文件.h中

public:
	//按钮函数
	afx_msg void OnButtonCOMstatu();			//串口状态显示

源文件.cpp中

//串口状态显示
void CSprDlg::OnBnClickedButtonOpencom()
{
	 TODO: 在此添加控件通知处理程序代码
	
	m_COMStatu = !m_COMStatu;
	if (!m_COMStatu)
		GetDlgItem(IDC_BUTTON_OPENCOM)->SetWindowText("串口打开");
	else
		GetDlgItem(IDC_BUTTON_OPENCOM)->SetWindowText("串口关闭");
	OnCbnSelchangeComboCom();
	DisplayStatus();

	return;
}

三、完整代码

头文件.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 OnBnClickedButtonOpencom();			//串口状态显示

	//列表框函数
	afx_msg void OnCbnSelchangeComboCom();				//更改串口
	afx_msg void OnCbnSelchangeComboBaud();				//更改波特率
	afx_msg void OnCbnSelchangeComboCheck();			//更改校验位
	afx_msg void OnCbnSelchangeComboData();				//更改数据位
	afx_msg void OnCbnSelchangeComboStop();				//更改停止位
	
};

源文件.cpp中


===========================================初始化对话框===========================================
//初始化对话框
BOOL CSprDlg::OnInitDialog()
{
	// TODO: 在此添加额外的初始化代码

	//设串口组合列表框
	TCHAR com[][6] = { "COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9" };
	for (int i = 0; i < 9; i++)
		m_Combo_Com.AddString(com[i]);
	m_Combo_Com.SetCurSel(0);
	
	//设波特率组合列表框
	TCHAR baud[][7] = { "300","600","1200","2400","4800","9600","19200","38400","43000","56000",
						"57600","115200","128000","230400" };
	for (int i = 0; i < 14; i++)
		m_Combo_Baud.AddString(baud[i]);
	m_Combo_Baud.SetCurSel(11);
	
	//设校验位组合列表框
	TCHAR check[][7] = { "N","O","E" };
	for (int i = 0; i < 3; i++)
		m_Combo_Check.AddString(check[i]);
	m_Combo_Check.SetCurSel(0);
	
	//设数据位组合列表框
	TCHAR data[][2] = { "8","7","6" };
	for (int i = 0; i < 3; i++)
		m_Combo_Data.AddString(data[i]);
	m_Combo_Data.SetCurSel(0);
	
	//设停止位组合列表框
	TCHAR stop[][2] = { "1","2" };
	for (int i = 0; i < 2; i++)
		m_Combo_Stop.AddString(stop[i]);
	m_Combo_Stop.SetCurSel(0);

	OpenComm(0);

	return TRUE;  
}

==============================================打开串口==============================================

//打开串口
BOOL CSprDlg::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("打开串口失败!");	//失败时弹出对话框提醒
		m_bConnected = 0;				//将串口连接标志设为0
		return FALSE;					//打开失败后不再继续往下进行,直接返回FALSE
	}

	m_bConnected = 1;
	return 0;
}
============================================显示串口状态============================================

//显示串口状态
void CSprDlg::DisplayStatus()
{
	CWnd* static_status = GetDlgItem(IDC_STATIC_COMSTATU);
	CWnd* static_txlen = GetDlgItem(IDC_STATIC_TXLEN);
	CWnd* static_rxlen = GetDlgItem(IDC_STATIC_RXLEN);
	CString status_str, txlen_str, rxlen_str;

	if (m_bConnected)
	{
		status_str = "STATUS:" + m_Str_Com + " OPENED," + m_Str_Baud + ',' + m_Str_Check + ',' + m_Str_Data + ',' + m_Str_Stop;
		SetCommParameter();
	}
		
	else
		status_str = "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("TX:%ld", m_txlen);
	static_txlen->SetWindowText(txlen_str);

	rxlen_str.Format("RX:%ld", m_rxlen);
	static_rxlen->SetWindowText(rxlen_str);
}

==============================================关闭串口==============================================

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

==============================================设置串口参数==============================================

//设置串口参数
BOOL CSprDlg::SetCommParameter()
{
	DCB dcb;
	if (!GetCommState(m_hCom, &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;
	dcb.fBinary = TRUE;
	dcb.fParity = FALSE;
	dcb.fOutxCtsFlow = FALSE;
	dcb.fOutxDsrFlow = FALSE;

	return(SetCommState(m_hCom, &dcb));
}


==========================================串口开关按钮状态显示==========================================

//串口状态显示
void CSprDlg::OnBnClickedButtonOpencom()
{
	 TODO: 在此添加控件通知处理程序代码
	
	m_COMStatu = !m_COMStatu;
	if (!m_COMStatu)
		GetDlgItem(IDC_BUTTON_OPENCOM)->SetWindowText("串口打开");
	else
		GetDlgItem(IDC_BUTTON_OPENCOM)->SetWindowText("串口关闭");
	OnCbnSelchangeComboCom();
	DisplayStatus();

	return;
}

==============================================更改串口设置==============================================

//更改串口
void CSprDlg::OnCbnSelchangeComboCom()
{
	// TODO: 在此添加控件通知处理程序代码
	if (m_bConnected)
		CloseConnection();
	if (m_COMStatu)
	{
		int i = m_Combo_Com.GetCurSel();
		OpenComm(i);
	}
	DisplayStatus();
}

//更改波特率
void CSprDlg::OnCbnSelchangeComboBaud()
{
	// TODO: 在此添加控件通知处理程序代码
	int baudindex;
	baudindex = m_Combo_Baud.GetCurSel();
	if (baudindex != CB_ERR)
	{
		SetCommParameter();
		m_Combo_Baud.GetLBText(baudindex, m_Str_Baud);
		
	}
	DisplayStatus();
}

//更改校验位
void CSprDlg::OnCbnSelchangeComboCheck()
{
	// TODO: 在此添加控件通知处理程序代码
	int checkindex;
	checkindex = m_Combo_Check.GetCurSel();
	if (checkindex != CB_ERR)
	{
		SetCommParameter();
		m_Combo_Check.GetLBText(checkindex, m_Str_Check);
		DisplayStatus();
	}
}

//更改数据位
void CSprDlg::OnCbnSelchangeComboData()
{
	// TODO: 在此添加控件通知处理程序代码

	int dataindex;
	dataindex = m_Combo_Data.GetCurSel();
	if (dataindex != CB_ERR)
	{
		SetCommParameter();
		m_Combo_Data.GetLBText(dataindex, m_Str_Data);
		DisplayStatus();
	}
}

//更改停止位
void CSprDlg::OnCbnSelchangeComboStop()
{
	// TODO: 在此添加控件通知处理程序代码
	int stopindex;
	stopindex = m_Combo_Stop.GetCurSel();
	if (stopindex != CB_ERR)
	{
		SetCommParameter();
		m_Combo_Stop.GetLBText(stopindex, m_Str_Stop);
		DisplayStatus();
	}
}

  • 13
    点赞
  • 132
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值