0
点赞
收藏
分享

微信扫一扫

基于MFC的串口通信

忆北文学摄影爱好员 2023-10-29 阅读 48
mfcc++

1、串口通信的概述:

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

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

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

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

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

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

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

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

(3)、通信方式

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

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

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

(1)、字符格式收发:

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

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

2)、初始化下拉列表

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

入口函数:

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

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

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

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的资源图片也会随着串口的打开和关闭改变图片

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));//发送数据
			}

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

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);
}

举报

相关推荐

0 条评论