MFC+CSerialPort实现64位串口通信详解(VS2017)

本文介绍如何利用CSerialPort类实现64位串口通信,并以工业三色报警灯为例,详细讲解了从环境搭建到串口的打开、关闭及数据收发的全过程。

最近几天,一直在苦恼MFC不提供64位的COMM串口通信控件,转而发现CSerialPort类,但是CSDN上的CSerialPort类Demo程序都不适用于我的工业三色报警灯(USB转232串口),所以写篇文章,记录一下。

1、三色灯是USB接口的,厂家提供了USB转232串口的驱动,安装后插上设备,在“设备管理器”-》“端口(COM和LPT)”里面能看到对应的设备端口号,这个端口号要记住。

 2、下载CSerialPort类,已经编译好的静态版本链接如下:

64位串口通信CSerialPort类文件-C++文档类资源-CSDN下载

3、在VS2017中创建MFC对话框程序,应用程序类型选择“基于对话框”,首页选择“在静态库中使用MFC”。

4、生成的项目----右击“属性”---按下图设置,注意字符集选择UNICODE。

 

5、项目----添加现有项-----把下载的CSerialPort类文件都导入工程,生成对应的类

 6、生成的项目----右击“属性”-----“链接器”-----“输入”-----附件依赖项,输入SetupAPI.lib,回车。

7、打开工程项目中Dlg类的头文件,按照下图添加头文件和namespace,修改类的继承关系。 

#pragma once
#include "SerialPort.h"
#include "SerialPortInfo.h"

using namespace itas109;
using namespace std;

// CCSerialPortTestDlg 对话框
//class CCSerialPortTestDlg : public CDialogEx
class CCSerialPortTestDlg : public CDialogEx, public has_slots<>
{
// 构造
public:
	CCSerialPortTestDlg(CWnd* pParent = nullptr);	// 标准构造函数

 8、在protect权限下面增加一行函数声明,但是无需在cpp中定义函数。

protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);

	
	afx_msg LRESULT OnReceiveStr(WPARAM str, LPARAM commInfo);


	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()

 9、在项目的Dlg类里面添加一个public函数OnReceive:

void CCSerialPortTestDlg::OnReceive()
{
	char* str = NULL;
	str = new char[1024];
	int iRet = m_SerialPort.readAllData(str);

	if (iRet > 0)
	{
		str[iRet] = '\0';

		CString str1((char*)str);

	}
}

 

10、在项目的Dlg类里面添加串口变量CSerialPort m_SerialPort;后面用他来进行串口传输的各种操作。

11、在对话框中添加一个按钮IDC_BUTTON_OPENCOMM,双击添加响应函数如下。该函数用来打开和关闭串口。其中的init函数用来设置端口号(COM6),波特率,校验位,停止位等等,我把设置写死了,后期根据需要可以在对话框上添加选择框。

void CCSerialPortTestDlg::OnBnClickedButtonOpencomm()
{
	// TODO: 在此添加控件通知处理程序代码
	string portName;
	CString temp;
	CString strOpenClose;
	GetDlgItemText(IDC_BUTTON_OPENCOMM, strOpenClose);
	if (strOpenClose == _T("关闭串口"))
	{
		m_SerialPort.close();
	}
	
#ifdef UNICODE
	portName = CW2A(_T("COM6"));
#else
	int nSpaceIndex = temp.Find(" "); // 查找 空格 出现的索引
	CString strPortName = temp.Mid(0, nSpaceIndex);

	portName = strPortName.GetBuffer();

#endif	

	m_SerialPort.init(portName, 9600, itas109::Parity(0), itas109::DataBits(8), itas109::StopBits(0));
	m_SerialPort.open();

	if (m_SerialPort.isOpened())
	{
		GetDlgItem(IDC_BUTTON_OPENCOMM)->SetWindowText(_T("关闭串口"));

	}
	else
	{
		AfxMessageBox(_T("串口未被连接!"));
	}
}

12、在对话框中添加一个按钮IDC_BUTTON_SEND,,双击添加响应函数如下。该函数用来发送数据。temp用来设置发送内容,HexorNot 用来设置是否按照十六进制发送。

void CCSerialPortTestDlg::OnBnClickedButtonSend()
{
	// TODO: 在此添加控件通知处理程序代码
	bool HexorNot = true;//是否按照十六进制发送
	CString temp;
	GetDlgItem(IDC_BUTTON_OPENCOMM)->GetWindowText(temp);
	if (temp ==_T("打开串口"))///没有打开串口
	{
		AfxMessageBox(_T("请首先打开串口"));
		return;
	}
	temp.Format(_T("发送内容"));
	size_t len = _tcsclen(temp) + 1;
	char* m_str = NULL;
	size_t* converted = 0;
	m_str = new char[len];
#ifdef UNICODE
	wcstombs_s(converted, m_str, len, temp.GetBuffer(0), _TRUNCATE);
#else
	m_str = temp.GetBuffer(0);
#endif
	if (HexorNot) {
		CString strOrdered = GetOrderedStr(temp);
		for (int i = 0; i < strOrdered.GetLength(); i += 2)
		{
			CString strTemp = strOrdered.Mid(i, 2);
			int num = WideCharToMultiByte(CP_OEMCP, NULL, strTemp, -1, NULL, 0, NULL, FALSE);
			char *pchar = new char[num];
			WideCharToMultiByte(CP_OEMCP, NULL, strTemp, -1, pchar, num, NULL, FALSE);
			m_str[i / 2] = strtol(pchar, NULL, 16);
		}

		int len = strOrdered.GetLength() / 2;
		m_SerialPort.writeData(m_str, len);
	}
	else
	{
		m_SerialPort.writeData(m_str, len);
	}
}

13、在项目的Dlg类里面添加如下函数。

CString CCSerialPortTestDlg::GetOrderedStr(CString m_strSend)
{
	CString str;

	int i = 0;
	int length = m_strSend.GetLength();
	for (i = 0; i < length - 1; i++)//"31 32 33 回车 34"   "34 31 327"    "34 31 32 7"    "32 33 3 34"
	{
		if (m_strSend.Mid(i, 1) != " " && m_strSend.Mid(i, 1) != "\r")
		{
			if (m_strSend.Mid(i + 1, 1) != " " && m_strSend.Mid(i + 1, 1) != "\r")
			{
				CString strTemp;
				strTemp = m_strSend.Mid(i, 2);
				str = str + strTemp;
				i++;
			}
			else
			{
				str = str + "0" + m_strSend.Mid(i, 1);
			}
		}

		if (m_strSend.Mid(i, 1) == "\r" && m_strSend.Mid(i + 1, 1) == "\n") //碰到回车,也就是\n\r,则直接跳过\n\r这两个字符! 
			i++;
	}

	if (i == m_strSend.GetLength() - 1 && m_strSend.Mid(i, 1) != " ")
		str = str + "0" + m_strSend.Mid(i, 1);  //该行防止"34 31 32 7"中7丢失

	return str;
}

 13、上面完成了串口的打开,关闭,和发送。如果想接收信息,在OnInitialDialog函数里面,添加这句:

m_SerialPort.readReady.connect(this, &CCSerialPortTestDlg::OnReceive);

在OnReceive函数里面str1变量即为接收到的信息。串口一旦收到消息,里即为str1赋值。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值