最近几天,一直在苦恼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赋值。
本文介绍如何利用CSerialPort类实现64位串口通信,并以工业三色报警灯为例,详细讲解了从环境搭建到串口的打开、关闭及数据收发的全过程。
1028

被折叠的 条评论
为什么被折叠?



