技术资讯

网页开发串口通信之MSComm控件的使用方法

TIME:2018-07-20

作为一个MFC编程的菜鸟,以下内容着重在于自己对MScomm控件的使用流程梳理,以此以便自己忘了时有据可查,由于时间关系,未曾过多考虑代码布局,所以代码略显粗糙,忘各位海涵,若能理解使用即可。

一、进行MSComm32.OCX的注册

在win8.1的环境系统中一般情况下是没有MSComm32.OCX这个Active控件的,所以需要单独注册:

方案一: 安装VC++6.0

安装VC++6.0/VB6.0时,如果选择了ACtiveX控件项(自定义安装),MSComm控件就会自动安装在计算机上了,并在系统文件夹下多了3个文件:Mscomm.srg, Mscomm32.ocx,Mscomm32.dep;并且已经在系统中注册了!

方案二:自己下载控件并注册

另一种方法是下载Mscomm.srg, Mscomm32.ocx,Mscomm32.dep三个文件(只有 Mscomm32.ocx应该也可以),并将其放到C/Windows/System32下之后。以管理员身份运行Cmd,在中填入Regsvr32 C:\Windows\System32\Mscomm32.ocx,会出现如下成功信息:


完成上面程序之后,在注册表中确认如下信息:
点击“开始”->"运行",再在中填入regedit命令打开注册表编辑器(管理员身份),找到HKEY_CLASSES_ROOT\Licenses,在其中确认主键
4250E830-6AC2-11cf-8ADB-00AA00C00905是否存在,并且其内容是否为设置为:kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun。如果不存在,手动添加这个主键并修改为前面所述内容!

至此,MScomm32.ocx注册成功!

二、使用MScomm32.ocx进行MFC编程:

1、建立工程

运行VS2010编程环境,建立项目工程,如下图所示:





2、加入MScomm控件在对话框界面

(1)加入MScomm32控件:

在编辑对话框上右键,选择“插入ActiveX控件(X)”,然后在弹出的对话框中选择Microsoft communications control,version 6.0。点击“确定”后在对话框界面左上角会显示一个电话形式的图标,他就是MSComm的控件了,如下面三幅图所示:




(2)加入MScomm控件类:

(1)在项目名称上右键选择添加→类,选择“ACtiveX控件中的MFC类”,如图所示:



(2)在ActiveX控件添加类向导中选择“”文件“”,选择位置“C:\Windows\System32\MSCOMM32.OCX”并打开,在接口选择“IMSComm”生成类,点击完成MSCOM控件类的田添加,会自动命名为mscomm,点击完成,工程中会自动添加“mscomm.h”和“mscomm.cpp”两个文件:



(3)对对话框添加其他控件并进行排版后如图所示:

(3)给MScomm控件添加变量

在MScomm控件(电话标志)上右键添加MScomm变量,如图所示:



(4)给控件添加时间处理程序

在MScomm控件(电话标志)上右键添加MScomm事件处理程序,如图所示:





至此,MScomm的准备工作完成了,下面开始程序部分的编写。

三、相关串口编程

最终完成本程序的类内容包括:
// ADTestDlg 对话框
class ADTestDlg  : public CDialogEx
{
DECLARE_EASYSIZE
// 构造
public:
ADTestDlg (CWnd* pParent = NULL);// 标准构造函数
// 对话框数据
enum { IDD = IDD_AD_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX);// DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButtonOpen();
CMSComm m_MSComm;
CString m_EditSend;
CString m_EditReceive;
afx_msg void OnBnClickedButtonClose();
DECLARE_EVENTSINK_MAP()
void OnCommMscomm_com();
afx_msg void OnEnChangeEditReceve();
afx_msg void OnEnChangeEditSend();
CString m_ComList;
afx_msg void OnBnClickedButtonClrRxbuf();
long m_ReceiveNum;
CComboBox m_ComChoose;
CComboBox m_MaxChoose;
afx_msg void OnBnClickedButtonSetmax();
afx_msg void OnBnClickedButtonSetmaxsend();
afx_msg void OnBnClickedButtonSetmaxrecv();
afx_msg void OnBnClickedButtonAllsend();
afx_msg void OnBnClickedButtonAllreceve();
afx_msg void OnBnClickedButtonSend();
afx_msg void OnBnClickedButtonAutoPick();
int m_IsContinue;
afx_msg void OnBnClickedButtonEndPick();

CEditEx m_ControlA;
long m_SendNum;
afx_msg void OnTimer(UINT_PTR nIDEvent);
// 接收15300的次数
int m_ReceiveCount;
CFile m_FileSave;
void ADTestDlg ::Max2828Operation(int number, int type);
int m_TimerCount;
void ADTestDlg ::SetFrequency(int number, int type);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnBnClickedButtonGetonedata();
int m_GetOneData;
};

本文只贴出相关串口操作的程序,其余时间处理或不相关程序未贴出:

1、打开串口

//双击“打开串口”按钮,添加控件事件处理程序如下:
void ADTestDlg::OnBnClickedButtonOpen()
{
// TODO: 在此添加控件通知处理程序代码
int com_number;
CString str;

str.Empty();

if(m_MSComm.get_PortOpen()) //如果串口是打开的,则行关闭串口
{
m_MSComm.put_PortOpen(FALSE);
}
com_number = m_ComChoose.GetCurSel()+1;
m_MSComm.put_CommPort(com_number); //选择COM

m_MSComm.put_InBufferSize(MAX_BUFFER_SIZE); //接收缓冲区
m_MSComm.put_OutBufferSize(MAX_BUFFER_SIZE);//发送缓冲区
m_MSComm.put_InputLen(0);//设置当前接收区数据长度为0,表示全部读取
m_MSComm.put_InputMode(1);//以二进制方式读写数据
m_MSComm.put_RThreshold(1);//接收缓冲区有1个及1个以上字符时,将引发接收数据的OnComm事件
m_MSComm.put_Settings(_T("115200,n,8,1"));//波特率115200无检验位,8个数据位,1个停止位
if(!m_MSComm.get_PortOpen())//如果串口没有打开则打开
{
m_MSComm.put_PortOpen(TRUE);//打开串口
str.Format(_T("串口%d打开成功"), com_number);
//AfxMessageBox(str);
}
else
{
m_MSComm.put_OutBufferCount(0);
str.Format(_T("串口%d打开失败"), com_number);
AfxMessageBox(str);
}
}

2、关闭串口:

//双击关闭串口”按钮,添加控件事件处理程序如下:
void ADTestDlg::OnBnClickedButtonClose()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
str.Empty();
m_MSComm.put_PortOpen(FALSE);//关闭串口
str.Format(_T("串口%d关闭成功"), m_ComChoose.GetCurSel()+1);
//AfxMessageBox(str);
}

3、接受数据

//当数据来临时,会发出MSComm控制事件,数据就在这个控制时间函数中接受
void CADtestDlg::OnCommMscomm_com()
{
// TODO: 在此处添加消息处理程序代码
//static unsigned int cnt=0;
VARIANT variant_inp;
COleSafeArray safearray_inp;
long len,i;
byte rxdata[MAX_BUFFER_SIZE]={0}; //设置 BYTE 数组
CString strtemp;

strtemp.Empty();

UpdateData(true); //读取编辑框内容
if(m_MSComm.get_CommEvent()==2) //值为 2 表示接收缓冲区内有字符
{
variant_inp=m_MSComm.get_Input(); //读缓冲区消息
safearray_inp=variant_inp; ///变量转换
len=safearray_inp.GetOneDimSize(); //得到有效的数据长度
for(i=0; i<len; i++)
{
safearray_inp.GetElement(&i, rxdata+i);//获得数据
}
for(i=0; i<len; i++) //将数组转换为 CString 型变量
{
strtemp.Format(_T("%2.2X "), *(rxdata+i));//数据转换
m_EditReceive+=strtemp;//更新接受缓冲区
}
m_ReceiveNum += len;
//UpdateData(FALSE); //更新编辑框内容

/*********************以下内容不属于数据接受并部分,可忽略*********************/
if(0==(m_ReceiveNum%15300))
{
if((m_IsContinue && m_ReceiveCount <= 16) || m_GetOneData == 1)
{
//保存文件
CString SaveFilePath,FilePath, FileName;
FilePath.Empty();
FileName.Empty();
if(m_GetOneData == 1)
{
FileName.Format(_T("\\%dData.txt"), m_MaxChoose.GetCurSel()+1);
}
else
{
FileName.Format(_T("\\%d.txt"), m_ReceiveCount);
}
m_ReceiveCount++;
//GetModuleFileName(NULL,FilePath.GetBufferSetLength(MAX_PATH+1),MAX_PATH);
GetCurrentDirectory(MAX_PATH,FilePath.GetBufferSetLength(MAX_PATH+1));
SaveFilePath.Format(_T("%s\\ADdata"), FilePath, FileName);
if(!CreateDirectory(SaveFilePath,NULL))
;
// AfxMessageBox(_T("目录创建失败!"));
SaveFilePath.Format(_T("%s%s"), SaveFilePath, FileName);
if(m_FileSave.Open(SaveFilePath, CFile::modeCreate|CFile::modeReadWrite,NULL))
{
unsigned long NumBytes = (m_EditReceive.GetLength() + 1) * sizeof(TCHAR);
//m_FileSave.Write(&(m_EditReceive.GetBuffer()[0]), m_EditReceive.GetLength()*2);
m_FileSave.Write(m_EditReceive, NumBytes);
//Sleep(5);
//m_FileSave.Write(&(m_EditReceive.GetBuffer()[len]), len);
Sleep(5);
m_FileSave.Close();
}
OnBnClickedButtonClrRxbuf();//清除
}
}
}
UpdateData(FALSE); //更新编辑框内容
}

4、数据发送

void CADtestDlg::OnBnClickedButtonSend()
{
// TODO: 在此添加控件通知处理程序代码

CByteArray HexDataBuf;
int i = 0;
BYTE SendBuf[128]={0};
BYTE GetData[256]={0};
int SendLen = 0;
int GetLen = 0;
CString strTemp =_T("");

UpdateData(TRUE);//获取编辑框内容
if(m_EditSend.IsEmpty())
{
AfxMessageBox(_T("发送数据为空!"));
return;
}
HexDataBuf.RemoveAll();               //清空数组 

GetLen = m_EditSend.GetLength();
for(i=0; i<GetLen; i++)
{
GetData[i] = (BYTE)m_EditSend.GetBuffer()[i];
}
stringtoHex(&GetData[0], GetLen, &SendBuf[0], &SendLen);//将字符串转化为字节数据

HexDataBuf.SetSize(SendLen);            //设置数组大小为帧长度 
for(i=0; i<SendLen; i++)
{
HexDataBuf.SetAt(i,SendBuf[i]);
}
m_MSComm.put_Output(COleVariant(HexDataBuf)); //发送十六进制数据
CADtestDlg::m_SendNum += SendLen;

UpdateData(false); //更新编辑框内容
}

以上程序基本应用可以替代串口调试助手,由于开发目的不在于此

上一篇

SQL Server与MySQL中排序规则与字符集相关知识的一点总结

下一篇

PHP读取CURL模拟登录时格式化生成Cookie文件的方法