在VS2008中使用MSComm实现串口通信

时间:2022-09-06 11:01:25

一 MSComm

    MSComm 控件通过串行端口传输和接收数据,为应用程序提供串行通讯功能。MSComm控件在串口编程时非常方便,程序员不必去花时间去了解较为复杂的API函数,而且在VC、VB、Delphi等语言中均可使用。 Microsoft Communications Control(以下简称MSComm)是Microsoft公司提供的简化Windows下串行通信编程的ActiveX控件,它为应用程序提供了通过串行接口收发数据的简便方法。MSComm的API介绍请参考

 

二 使用实例

1 新建一个基于对话框的MFC应用程序工程。

2 添加ActiveX控件。在对话框的空白处点击右键,在弹出的菜单中选择“Insert ActiveX Control”,这时弹出一个对话框,列出了本机已注册的所有控件,选择“Microsoft Communications Control, version 6.0”,点击“ok”。如果在插入控件的过程中出错,请参照http://www.cnblogs.com/edward259/archive/2009/08/21/1551463.html注册MSComm。

3 添加类和关联变量。右击对话框中新加的串口控件(电话图标),选择“Add-->Add Variable”,为该控件关系一个成员变量。

4 添加串口事件消息处理函数。右击对话框中的串口控件图标,在弹出的菜单中选择“Add Event Handler”,保持默认的函数处理程序名称,点击“Add and Edit”,即可完成串口事件消息处理函数的添加。这个函数是用来处理串口消息事件的,例如,每当串口接收到数据,就会产生一个串口接收数据缓冲中有字符的消息事件,这个函数就会执行。

5 初始化串口。假设串口控件的关联变量名为m_sComm,可通过以下代码进行初始化

BOOL CdipdetectionDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// 将“关于...”菜单项添加到系统菜单中。

// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
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: 在此添加额外的初始化代码
if (m_MSComm.get_PortOpen())
{
m_MSComm.put_PortOpen(FALSE);
}

m_MSComm.put_CommPort(6);//注意串口号设置为设备管理器中显示的串口号,不同的机器显示的串口号可能不同
m_MSComm.put_InBufferSize(1024);
m_MSComm.put_OutBufferSize(1024);
m_MSComm.put_InputMode(1);//二进制模式
m_MSComm.put_Settings(_T("9600, n, 8, 1"));
m_MSComm.put_RThreshold(1);//这行code很关键,如果不设置,则在响应函数中接收不到数据(悲剧,当时没注意卡在这好久)
m_MSComm.put_InputLen(0);//一次读取全部数据

if (!m_MSComm.get_PortOpen())
{
m_MSComm.put_PortOpen(TRUE);
}
else
{
MessageBox(_T("Comm6 can not be opened!"));
}

return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}

 

6 发送与接收数据

BEGIN_EVENTSINK_MAP(CdipdetectionDlg, CDialog)
ON_EVENT(CdipdetectionDlg, IDC_MSCOMM, 1, CdipdetectionDlg::OnCommMscomm, VTS_NONE)
END_EVENTSINK_MAP()

void CdipdetectionDlg::OnCommMscomm()
{
// TODO: 在此处添加消息处理程序代码
VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len, k;
char rxdata[15];//数据长度根据自己的实际要求设置

switch (m_MSComm.get_CommEvent())
{
case 1: //发送数据
break;

case 2: //接收数据
variant_inp = m_MSComm.get_Input(); //read data
safearray_inp = variant_inp;
len = safearray_inp.GetOneDimSize();//得到有效数据长度

for (k = 0; k < len; k++)
{
safearray_inp.GetElement(&k, rxdata+k);
}
//接收数据后,根据实际解析rxdata
break;
}
}