MFC学习——串口通信(MSComm32.ocx控件的使用)

  1. 注册MSComm32.ocx控件

    首先在我使用的是VS2010旗舰版,里面默认是没有该控件的,因此首先要进行注册。

    在网上下载了一个MSComm32.ocx控件,放在C:\Windows\SysWOW64目录下(因为我的是64位的,如果是32位的话就放在C:\Windows\System32下面),然后用管理员身份打开控制台程序cmd.exe(一定要是管理员身份,为此我折腾了好久),然后输入:regsvr32 C:\Windows\SysWOW64\mscomm32.ocx就完成了注册;

  2. 添加mscomm类并使能MSComm32.ocx控件

    1. 右击项目名称:添加->类,选择ActiveX控件中的MFC类;

    2. 在可用控件中选择MSComm32.ocx控件,下方生成类。如下图所示:

      MFC学习——串口通信(MSComm32.ocx控件的使用)_第1张图片

    3. 此时想添加该控件还是不行,因为工具箱里面找不到,所以点击:工具->选择工具箱,将COM组件勾上就可以了如下图所示:MFC学习——串口通信(MSComm32.ocx控件的使用)_第2张图片

      之后工具箱中便出现了该控件,是一个电话的形状。当然,我后来发现,直接在窗体上右击添加ActiveX控件就可以了。。。这个也是小弯路吧。。。。

  3. 设计程序窗体

    框体的设计这一点应该是比较简单的,如下图所示,在这里我也只是用了一些简单的控件:

    MFC学习——串口通信(MSComm32.ocx控件的使用)_第3张图片

    定义每一个控件的ID、属性等等:

    MFC学习——串口通信(MSComm32.ocx控件的使用)_第4张图片

    这里面我只用了发送和退出两个按钮。

    定义各个成员变量,但是串口的变量不能再类向导中直接添加,因为你会发现在成员变量的ID号中根本找不到串口,所以我就是通过右击这个串口控件,选择添加变量来实现的,当然这两种效果是一个样子的~

    MFC学习——串口通信(MSComm32.ocx控件的使用)_第5张图片

    接下来就是为各个控件添加响应了,一般的控件比如按钮,直接双击就可以了,但是这里的串口又特殊了,双击没有用,必须的还是右击选择添加响应。

    就这样整个框体就设计好了~~~

  4. 编辑程序代码

    代码比较简单,这里直接贴出来就行啦,

void CSerialDlg::OnCommMscomm()
{
	// TODO: 在此处添加消息处理程序代码
	VARIANT variant_inp;
	COleSafeArray safearray_inp;
	LONG len,k;
	BYTE rxdata[2048];//设置byte数组
	CString strtemp;
	if(m_ctrlComm.get_CommEvent()==2)//事件2表示接受缓冲区有字符
	{
		variant_inp=m_ctrlComm.get_Input();//读缓冲区
		safearray_inp=variant_inp;//variant数据转换成colesafearray型变量
		len=safearray_inp.GetOneDimSize();//得到有效数据长度
		for(k=0;k<len;k++)
			safearray_inp.GetElement(&k,rxdata+k);//转换为byte型数组
		for(k=0;k<len;k++)//将数组转换成CString型变量
		{
			BYTE bt=*(char *)(rxdata+k);//字符型
			m_strReceive+=(char) bt;//加入接收编辑框相应字符串
		}
	}
	UpdateData(0);//更新编辑框内容
}

void CSerialDlg::OnBnClickedCancel()
{
	// TODO: 在此添加控件通知处理程序代码
	m_ctrlComm.put_PortOpen(0);//关闭串口
	CDialogEx::OnCancel();
}

void CSerialDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData(1);//读取编辑框内容
	m_ctrlComm.put_Output(COleVariant(m_strSend));//发送数据
}

BOOL CSerialDlg::OnInitDialog()
{
	CDialogEx::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: 在此添加额外的初始化代码
	m_ctrlComm.put_CommPort(2);//选择com2口
	m_ctrlComm.put_InputMode(1);//输入方式为二进制方式
	m_ctrlComm.put_InBufferSize(1024);//输入缓冲区大小为1024byte
	m_ctrlComm.put_OutBufferSize(512);//输出缓冲区大小为512byte
	m_ctrlComm.put_Settings(_T("9600,n,8,1"));//设置串口参数:9600波特率,无奇偶校验,8个数据位,1个停止位
	if(!m_ctrlComm.get_PortOpen())
		m_ctrlComm.put_PortOpen(1);//打开串口
	m_ctrlComm.put_RThreshold(1);//每当串口接收缓冲区有多余或等于1个字符时将引发一个接收数据的oncomm事件
	m_ctrlComm.put_InputLen(0);//设置当前接收区数据长度为0
	m_ctrlComm.get_Input();//预读缓冲区以清空残留数据

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

            就这样整个程序就实现了基本的串口通信的功能了~~~


总结:其实写的东西比较少,但是实际过程中遇到的问题十分的多:

第一个就是找不到串口的控件,上了网才知道需要单独的添加(上面提到的);

第二个是第一遍无法执行的问题,我也没有找到问题的解决办法,但是当我把整个项目都删掉重来的时候,发现刚才的问题已经没有了,这个我也不知道怎么办了。。。。。。

第三个是字符串合并的问题,将接收到的ASCII字符转换成CString并拼接起来,我采用的是这样的办法:

for(k=0;k<len;k++)//将数组转换成CString型变量
{
    BYTE bt=*(char *)(rxdata+k);//字符型
    m_strReceive+=(char) bt;//加入接收编辑框相应字符串
}

但是我在网上找到的一份是这样的:

for(k=0;k<len;k++)
{
    BYTE bt=*(char *)(rxdata+k);//字符型
    strtemp.Format((char) bt);//将字符送入临时变量strtemp存放
    m_strreceive+=strtemp;//加入接收编辑框相应字符串
}

本来我是找不出什么区别的,但是一运行就出现了问题,我单步调试就是发生在字符格式化的时候,这一点我又搞不懂了,只能暂时放在这里了,希望哪位看到能给我一个解释,我自己也会再找找原因的。

你可能感兴趣的:(mfc,串口通信)