基于MFC的串口通信(Mscomm)

news2024/9/21 2:41:06

1、串口通信的概述:

串口是一种重要的通信资源,例如鼠标口、USB接口都是串口。串行端口是CPU和串行设备间的编码转换器。当数据从CPU经过端口发送出去的时候,字节数据会被转为串行的位,在接收数据时,串行的位被转换为字节数据。

(1)、串口通信的特点:

数据通信多采用串口技术,主要因为串口可以在现有的电话网络上进行数据传输。串口通信是按照数据一位一位的依次传输,所以一根传输线就可以完成数据交换,降低了通信成本。

(2)、串口通信的传输方式

串口通信按照数据流可以分为三种传输方式:单工通信、半双工通信、全双工通信。

单工通信:使用一根导线,数据只能从A发送到B

半双工通信:是用一根导线,数据可以从A发送到B,也可以从B发送到A。但是不能同时进行

全双工通信:俩根导线。允许通信双方在俩个方向同时进行数据传输。

(3)、通信方式

同步通信:接收方不必对每个字节进行起始和停止的操作,传输效率高。传输设备复杂,双方时钟允许误差小。可用于点对点之间的数据传输。

异步通信:以字符为单位进行数据传输,并且每个字符都有起始位和停止位的标记。允许各个字符之间有间隙,俩个字符之间的间隔不固定。异步通信的传输效率低,传输设备简单,并且只适用于点对点的数据传输。

2、利用Mscomm进行串口通信:

(1)、字符格式收发:

1)、初始化框架的ICON和发送EDIT的文本

初始化框架上的内容,应该位于框架类的构造函数中

CComDlg::CComDlg(CWnd* pParent /*=NULL*/)

初始化ICON:m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON_EARTH); // 图标改成地球
    

  初始化发送EIDT的文本:  m_strSend = "My first SerialPortTool!";

2)、初始化下拉列表

初始化下拉列表位于入口函数中

入口函数:

CComDlg::OnInitDialog

初始化串口号,波特率,校验位,数据位,停止位 

    m_cboPort.SetCurSel(0);
    m_cboBaudRate.SetCurSel(4);
    m_cboCheck.SetCurSel(0);
    m_cboDataBit.SetCurSel(3);
    m_cboStopBit.SetCurSel(0);

3)、获取我们界面中的设置到CMscomm类中的对象中

UI的串口设置中的打开按钮,添加打开按钮事件。

UpdateData(TRUE); //将控件中的内容同步到变量中,我们操作控件就相当于操作变量。

    CString strOpen;//strOpen来获得按钮上面的文字内容。
    GetDlgItemText(IDC_BUTTON_OPEN, strOpen);
    
    if(strOpen == "打开")
    {    //1、执行打开串口操作

        m_mscomm.put_InBufferSize(1024); //接收缓冲区  
        m_mscomm.put_OutBufferSize(1024);//发送缓冲区   
        m_mscomm.put_InputLen(0);//设置当前接收区数据长度为0,表示全部读取  
        m_mscomm.put_InputMode(CMscomm::comInputModeBinary);//以二进制方式读写数据   
        m_mscomm.put_RThreshold(1);//接收缓冲区有1个及1个以上字符时,将引发接收数据的OnComm事件
        
        //2、获取我们界面中的设置到CMscomm类中的对象中
        //校验位,犹豫我们拼接字符串,但是校验位比较特殊,很多设备没有校验位所以我们不能直接使用value类型变量
        CString strCheck = getCheck();

        CString strSettings = m_strBaudRate + strCheck + m_strDataBit + m_strStopBit;
        //MessageBox(strSettings);
        //"9600,n,8,1" 和 "9600n81" 均对
        //m_mscomm.put_Settings(_T("9600,n,8,1"));//波特率9600,无检验位,8个数据位,1个停止位  
        m_mscomm.put_Settings(strSettings);

        //端口号
        //put_CommPort参数直接代表串口号为1,m_cboPort.GetCurSel() + 1目的增加了复用性。
        m_mscomm.put_CommPort(m_cboPort.GetCurSel() + 1);//索引从0开始

getCheck()获取当前的校验位

//步骤2、获取校验位
CString CComDlg::getCheck(void)
{
	CString strCheck;

	switch(m_cboCheck.GetCurSel())
	{
	case 0: strCheck = "n"; break;//无校验
	case 1:  strCheck = "o"; break;//基校验
	case 2: strCheck = "e"; break;//偶校验
	case 3: strCheck = "m"; break;
	case 4:strCheck = "s"; break;
	default:break;
	}

	return strCheck;
}

4)、真正打开串口的操作

我们点击打开串口的时候,调用put_PortOpen打开串口,并且要做一个异常捕获。

打击打开串口的操作,我们的打开按钮得更换文本内容为关闭

同时有一个bmp的资源图片也会随着串口的打开和关闭改变图片

try
        {
            m_mscomm.put_PortOpen(TRUE);//put_PortOpen(TRUE),参数为TRUE则打开串口,为FALSE则关闭串口
        }
        catch (CException* e)
        {
            MessageBox("端口不存在!", "打开串口", MB_ICONERROR);
            return;
        }
        
        SetDlgItemText(IDC_BUTTON_OPEN, _T("关闭")); //串口打开之后,设置按钮为“关闭”

        CBitmap bitmap;  // CBitmap对象,用于加载位图    
        HBITMAP hBmp;    // 保存CBitmap加载的位图的句柄   
  
        bitmap.LoadBitmap(IDB_BITMAP_GREEN);  // 将位图IDB_BITMAP1加载到bitmap   
        hBmp = (HBITMAP)bitmap.GetSafeHandle();  // 获取bitmap加载位图的句柄   
        m_picIndicator.SetBitmap(hBmp);    // 设置图片控件m_picIndicator的位图图片为IDB_BITMAP_RED 
    }
    else // 4、此时串口已经处于打开状态 执行关闭串口
    {
        m_mscomm.put_PortOpen(FALSE);//put_PortOpen(TRUE),参数为TRUE则打开串口,为FALSE则关闭串口  
        SetDlgItemText(IDC_BUTTON_OPEN, _T("打开")); //串口打开之后,设置按钮为“关闭”

        CBitmap bitmap;  // CBitmap对象,用于加载位图    
        HBITMAP hBmp;    // 保存CBitmap加载的位图的句柄   
  
        bitmap.LoadBitmap(IDB_BITMAP_RED);  // 将位图IDB_BITMAP1加载到bitmap   
        hBmp = (HBITMAP)bitmap.GetSafeHandle();  // 获取bitmap加载位图的句柄   
        m_picIndicator.SetBitmap(hBmp);    // 设置图片控件m_picIndicator的位图图片为IDB_BITMAP_RED  
    }

5)、发送2进制或者16进制数据

首先当我们点击发送按钮的时候,进行一个异常捕获,如果串口没有打开之间弹出对话框串口未打开,然后我们进行一个勾选框的判断,判断发送的是2进制还是十六进制数据,最后进行数据处理和发送

UpdateData(TRUE); //1、读取编辑框内容 ,内容写到控件中,然后同步到变量中
	//2、什么时候发送,发送的条件就是文本内容是“发送”
	CString strSend;
	GetDlgItemText(IDC_BUTTON_SEND, strSend);
	if(strSend == "发送")
	{	
		//3、执行串口发送操作
		try
		{
			CString strOrdered = "";
			if(1 == m_chkHexSend.GetCheck())//当勾选框被选中的时候
			{	//以十六进制发送
				hexToSend.RemoveAll();//清空数组
				
				//十六进制 41 42 43 41空格为一组,42空格为一组....。
				strOrdered = GetOrderedStr();
				//MessageBox(strOrdered);
				for(int i = 0; i< strOrdered.GetLength(); i += 2)
				{
					CString strTemp = strOrdered.Mid(i, 2);
					char *p = strTemp.GetBuffer(2);
					hexToSend.Add(strtol(p, NULL, 16));
				}
				m_mscomm.put_Output(COleVariant(hexToSend));//发送的二进制转换成16进制
				//4、这里如果串口没有打开直接写数据程序会崩溃,可能有异常直接try catch
			}
			else
			{//没有选中以字符格式发送
				strToSend = m_strSend;
				m_mscomm.put_Output(COleVariant(strToSend));//发送数据
			}

这里我们如果发送的是十六进制数据进行一个消息处理

CString CComDlg::GetOrderedStr()
{
    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丢失
    //至此, "31323334"      "34313207"      "34313207"     "32330334"

    //MessageBox(str);

    return str;
}

6)、接收十六进制或者二进制数据

void CComDlg::OnCommMscomm()
{
	// TODO: 在此处添加消息处理程序代码
	UpdateData(TRUE); 

	static unsigned int cnt=0;  
	VARIANT variant_inp;    
	COleSafeArray safearray_inp;   
	long len,k;    
	byte rxdata[1024]; //设置 BYTE 数组   CString strtemp; //通过声明这样一个字节数组,您可以在后续的代码中使用rxdata来存储从串口读取的二进制数据

	switch(m_mscomm.get_CommEvent())  //1、如果我们读取到事件
	{
	case CMscomm::comEvReceive: //值为 2 表示接收缓冲区内有字符  
		//2、从串口缓冲区读取数据
		m_mscomm.put_InputMode(CMscomm::comInputModeBinary);//规定二进制方式读取数据

		cnt++;   
		variant_inp = m_mscomm.get_Input();   //  variant_inp = m_mscomm.get_Input()这行代码用于从串口读取数据,并将读取的数据存储在variant_inp变量中
		safearray_inp = variant_inp;   //variant_inp中的数据转换为SAFEARRAY类型,并存储在safearray_inp变量中。
		len = safearray_inp.GetOneDimSize(); //得到有效的数据长度   
											 

		//状态栏显示接收到的字符个数
		CString strReceiveNum;
		m_ulReceiveNum += len;
		strReceiveNum.Format("%d", m_ulReceiveNum);
		strReceiveNum = "接收:" + strReceiveNum;
		m_StatusBar.SetText(strReceiveNum, 2, 0);//SBT_POPOUT, SBT_NOBORDERS
		//3、接收数据
		for(k = 0; k < len; k++)    
		{   
			safearray_inp.GetElement(&k, rxdata + k);

			if(1 == m_chkHexReceive.GetCheck()) //接收到的数据以十六进制显示
			{
				//safearray_inp.GetElement(&k, rxdata + k);  
				CString strtemp = "";
				strtemp.Format(_T("%02X"),rxdata[k]);//rxdata[k] 的值以十六进制格式添加到 strtemp 字符串中
				m_strReceive = m_strReceive + strtemp + " "; 
				
			}
			else	//接收到的数据以字符格式显示
			{
				CString strtemp = "";
				//safearray_inp.GetElement(&k, rxdata + k);    
				strtemp.Format("%c",rxdata[k]); //将字符送入临时变量strtemp存放
				m_strReceive = m_strReceive + strtemp;//m_strReceive接收EDIT的变量
			}	
		
		}
		if (1 == m_chkHexReceive.GetCheck()) // 如果以十六进制显示,最后再加上一个换行
		{
			m_strReceive += "\r\n";
		}
		else
		{
			m_strReceive += "\n";
		}
		
		break;
	}

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

	//注意:在更新完编辑框的内容之后,还要设置接收编辑框定位到最后一行
	int nLineCount = m_editReceive.GetLineCount();
	int nLineLength = m_editReceive.LineLength(nLineCount);
	m_editReceive.LineScroll(nLineCount, nLineLength);
	//TRACE("%d", nLineCount);
}

7)、点击十六进制发送的时候,EDIT的内容变成十六进制

//将发送的文本内容直接从二进制编程变成16进制
void CComDlg::OnBnClickedCheckSendHex()
{	
	// TODO: 在此添加控件通知处理程序代码
	UpdateData(TRUE);

	if (1 == m_chkHexSend.GetCheck()) //此时要把字符格式转换成十六进制
	{
		char *p = m_strSend.GetBuffer(m_strSend.GetLength());
		m_strSend.ReleaseBuffer();

		CString str = "";
		int length = m_strSend.GetLength();

		for(int i = 0; i < length; i++)
		{
			CString strTemp;
			strTemp.Format("%02X", p[i]);
			str = str + strTemp + " ";
		}
		m_strSend = str.TrimRight(" ");
	}
	else	//此时要把十六进制转换成字符格式
	{
		int length = m_strSend.GetLength();
		CString str;
		for(int i = 0; i< length; i += 3)
		{
			CString strTemp = m_strSend.Mid(i, 2);
			char *p = strTemp.GetBuffer(2);
			int num = strtol(p, NULL, 16);
			strTemp.Format("%c", num);
			str = str + strTemp;
		}
		m_strSend = str;
	}

	UpdateData(FALSE);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1153489.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Apache Dolphinscheduler如何不重启解决Master服务死循环

个人建议 Apache Dolphinscheduler作为一个开源的调度平台&#xff0c;目前已经更新到了3.X版本&#xff0c;4.0版本也已经呼之欲出。3.0版本作为尝鲜版本&#xff0c;新添加了许多的功能&#xff0c;同时也存在非常多的隐患&#xff0c;本人使用3.0版本作为生产调度也踩了很多…

开放式耳机和骨传导耳机哪个好,开放式耳机和骨传导耳机区别

虽然开放式耳机和骨传导耳机两者都能够听到周边的声音&#xff0c;但开放式耳机和骨传导耳机区别还是挺大的&#xff0c;下面让我来给大家详细的分析一下两者的区别。 1、音频传导方式 开放式耳机&#xff1a;开放式耳机设计允许声音从耳机的驱动单元透过外部空气传播到听觉器…

浅谈搜索展现层场景化技术-tanGo实践

作者 | 搜索技术平台 导读 本文为搜索展现层相关技术&#xff0c;主线会先通过介绍搜索阿拉丁的产品形态&#xff0c;让读者初步了解什么是阿拉丁&#xff0c;及相关展现概念。之后会聚焦场景化产品&#xff0c;场景化是搜索构建沉浸式完美体验&#xff08;重新组合整页阿拉丁和…

Win10系统 如何使用cmd脚本命令,连接到指定WIFI并免手工输入WIFI密码连接?

环境&#xff1a; Win10 专业版 19041 WiFi 名称&#xff1a;LTG 问题描述&#xff1a; Win10系统 如何使用cmd脚本命令&#xff0c;连接到指定WIFI并免手工输入WIFI密码连接&#xff1f; 解决方案&#xff1a; 1.找一台已经连接过LTG这个wifi的电脑&#xff0c;导出.xlm配…

EasyRecovery16专业版激活码序列号

当不小心将回收站的文件删除了怎么办&#xff1f;想找回但是不知道怎么找回需要的数据文件&#xff1f;别担心今天小编就为大家介绍一款非常专业的电脑数据文件恢复工具&#xff0c;easyrecovery14是由Ontrack专为电脑用户推出的一款专业的数据恢复软件&#xff0c;这款软件功能…

opencv 连通域操作示例代码记录connectedComponentsWithStats()函数示例

void CrelaxMyFriendDlg::OnBnClickedOk() {hdc this->GetDC()->GetSafeHdc();// TODO: 在此添加控件通知处理程序代码string imAddr "c:/Users/actorsun/Pictures/";string imAddr1 imAddr"rice.png";Mat relax1, positive;relax1 imread(imAdd…

一文获取鼎捷医疗器械行业数智化合规敏态方案

医疗器械产业是关乎国计民生的重要产业&#xff0c;高端医疗器械更是“国之重器”。为加强医疗器械的监督管理&#xff0c;提升行业质量和安全整体水平&#xff0c;我国出台了《医疗器械监督管理条例》、《医疗器械召回管理办法》、《医疗器械临床试验质量管理规范》、《医疗器…

【单点登陆导致cookie覆盖问题】

背景&#xff1a; 使用oauth2.0单点登陆进去不同服务器的同一系统。 同一浏览器存储的COOKIE名称&#xff0c;COOKIE PATH COOKIE DOMAIN一致&#xff0c;会认为是同一个COOKIE 当单点登陆进去c1平台后&#xff0c;前端浏览器会存入一个cookie,而后当单点登陆进入c2平台后&…

Android DSL

文章目录 Android DSL概述使用DSL构建HTML代码下载 Android DSL 概述 Kotlin DSL&#xff08;领域特定语言&#xff09;是一种使用 Kotlin 语言编写的&#xff0c;用于解决特定问题领域的语言。DSL 使得代码更易读、易写&#xff0c;因为它的语法和领域问题的语法更接近。Kot…

2021-arxiv-LoRA Low-Rank Adaptation of Large Language Models

2021-arxiv-LoRA Low-Rank Adaptation of Large Language Models Paper: https://arxiv.org/abs/2106.09685 Code: https://github.com/microsoft/LoRA 大型语言模型的LoRA低秩自适应 自然语言处理的一个重要范式包括对通用领域数据的大规模预训练和对特定任务或领域的适应。…

elementUI树节点全选,反选,半选状态

// <template>部分 <div class"check-block"><el-divider></el-divider><el-checkbox :indeterminate"indeterminate" v-model"checkAll" change"handleCheckAllChange">全选</el-checkbox><e…

足底筋膜炎怎么治疗最有效

足底筋膜炎的几种症状表现&#xff1a; 1、足跟的内侧足底处的疼痛和压痛。 2、早晨起床后疼痛和僵硬明显&#xff0c;活动后痛感逐渐减轻。 3、光脚或用脚尖跑步、走路都会加剧疼痛。 4、疼痛随着跑步、长时间走路或站立等负重活动而加剧。轻度时可能会以足底僵硬为主&…

可直接在Maya实时表情捕捉的面捕头盔,为3D模型表情制作提速!

面捕表情捕捉头盔可以用于捕捉真人的面部表情&#xff0c;从微小的皱纹到大的脸部肌肉运动&#xff0c;通过面捕头盔&#xff0c;都可以实时转化到虚拟角色上。 在元宇宙浪潮下&#xff0c;围绕虚拟人的应用场景和时长变得愈加多元&#xff0c;人们对虚拟人的精度不再仅限于简…

01.CentOS7静默安装oracle11g

CentOS7静默安装oracle11g 一、下载Oracle11g安装包二、开始安装oracle11g三、配置Oracle监听程序四、添加数据库实例五、设置开机启动六、登录后解除锁定 一、下载Oracle11g安装包 下载链接&#xff1a;https://pan.baidu.com/s/1gcLMFGX7-8ju7OoFOFLzQA 提取码&#xff1a;6…

python_PyQt5日周月K线纵向对齐显示_3_聚焦某段图形

目录 写在前面&#xff1a; 结果显示&#xff1a; 代码&#xff1a; 写在前面&#xff1a; “PyQt5日周月K线纵向对齐显示”&#xff0c;将分三篇博文描述 1 数据处理。将数据处理成适合图形显示的格式。&#xff08;已写&#xff0c;请看往期博文&#xff09; 2 显示工具…

搜维尔科技:Varjo在心理学、医学研究、技术、工程学等领域都在使用

该软件用于心理学、医学研究、可用性、品牌和营销等领域。vajio头显组合到了运动8.0平台中,提供了在高保真虚拟环境中进行的行为研究,否则这些环境的成本太高,不切实际,甚至无法在现实世界中再现。 在心理学、医学研究、可用性、技术、工程学、市场营销等领域工作的学术和商业研…

【项目管理】生命周期风险评估

规划阶段目标&#xff1a;识别系统的业务战略&#xff0c;以支撑系统的安全需求及安全战略 规划阶段评估重点&#xff1a;1、本阶段不需要识别资产和脆弱性&#xff1b;2、应根据被评估对象的应用对象、应用环境、业务状况、操作要求等方面识别威胁&#xff1b; 设计阶段目标…

草莓熊代码

话不多说直接上代码 如果需要exe文件电脑可以不依赖环境直接运行请评论或者私信 注意: 不需要年月日显示 注释 879-894 行不需要雪花显示 注释 895-908 行不需要礼物显示 注释 771 行653行 可以修改 祝你节日快乐内容657行 可以修改 草莓熊 内容修改程序标题 第 16 行# -*- co…

Tower for Mac—Git客户端 支持M1

Tower是一款Mac OS X系统上的Git客户端软件&#xff0c;它提供了丰富的功能和工具&#xff0c;帮助用户更加方便地管理和使用Git版本控制系统。以下是Tower的一些特点&#xff1a; 1. 界面友好&#xff1a;Tower的界面友好&#xff0c;使用户能够轻松地掌握软件的使用方法。 …

使用考试培训系统定制适合不同学生需求的教学内容

考试培训系统是一种方便高效的教育工具&#xff0c;可以根据不同学生的需求定制教学内容。通过使用这个系统&#xff0c;教师可以为学生提供个性化的学习计划&#xff0c;帮助他们提高学习效果。以下将详细介绍如何使用考试培训系统定制适合不同学生需求的教学内容。 考试培训系…