【Modbus通信实验二】VC++编写串口调试助手

编写串口调试助手并能在虚拟机中实现虚拟端口通信。步骤如下:

  1. 项目中引入Microsoft Communications Control组件,并编写串口初始化函数。
    【Modbus通信实验二】VC++编写串口调试助手_第1张图片
void CMODBUSDlg::initcomm()
{
	//串口状态,避免重复打开串口
	CommOpenFlag = FALSE;
	//设置串口端口号:需要在设备管理器中查看!
	m_mscomm_motor.SetCommPort(3);
	//设置接收模式为中断模式
	m_mscomm_motor.SetInputMode(1);
	//设置串口接收发送缓冲区大小
	m_mscomm_motor.SetInBufferSize(1024);
	m_mscomm_motor.SetOutBufferSize(1024);
	//设置串口波特率,位,校验方式
	m_mscomm_motor.SetSettings("9600, n, 8, 1");
}

m_mscomm_motor为设置的变量名,SetCommPort()传入的变量为端口号需要参考设备管理器中的可用虚拟端口号(COM3或COM5)。
【Modbus通信实验二】VC++编写串口调试助手_第2张图片

  1. 添加按钮“打开串口”的并编写相应代码。
void CMODBUSDlg::OnButOpenComm() 
{
	if (!m_mscomm_motor.GetPortOpen()) //如果串口没有被打开
	{
		//打开串口
		m_mscomm_motor.SetPortOpen(TRUE);
		//设置中断阈值
		m_mscomm_motor.SetRThreshold(1);  //
		m_mscomm_motor.SetInputLen(0);
		m_mscomm_motor.GetInput();
		CommOpenFlag = true;
		AfxMessageBox("打开串口成功");
	}
	else   //如果串口已经被占用则输出FALSE
	{
		CommOpenFlag = false;
		AfxMessageBox("打开串口失败,检查串口是否被占用");
	}
}
  1. 添加按钮“发送数据”并编写相应代码。发送的数据后要添加2个字节的CRC校验码。
void CMODBUSDlg::OnButCommSend() 
{
	CByteArray sendArray;
	unsigned char SendBuf[6] = {0x33, 0x44, 0x55, 0x66, 0x00, 0x00};   //前4个字节为报文,后两个字节为CRC16校验码
	unsigned short sendNum  = 6;
	unsigned short countFor = 0;   
	unsigned short CrcResult;
	CrcResult = Modbus.CRC16(SendBuf, 4);
	SendBuf[4] = HIBYTE_NORMAL(CrcResult);
	SendBuf[5] = LOBYTE_NORMAL(CrcResult);
	//对数据进行转换
	sendArray.SetSize(sendNum);
	for (countFor=0; countFor<sendNum; countFor++)
	{
		sendArray.SetAt(countFor, SendBuf[countFor]);
	}
	//将转换完的数据通过串口发送出去
	m_mscomm_motor.SetOutput((COleVariant(sendArray)));
}
  1. 添加文本显示框并实现串口数据接收。
void CMODBUSDlg::OnOnCommMscomm1() 
{
	VARIANT variant_inp;
	COleSafeArray safearray_inp;
	unsigned char receDataTemp[1024];   //BYTE接收缓冲区
	int receDataLen = 0;  //接收数据长度
	long CountFor = 0;    //用于for循环
	if(m_mscomm_motor.GetCommEvent() == 2)           //事件值为2表示接收缓冲区内有字符
	{
		variant_inp   = m_mscomm_motor.GetInput();         //读缓冲区
		safearray_inp = variant_inp;                       //VARIANT型变量转换为ColeSafeArray型变量
		receDataLen   = safearray_inp.GetOneDimSize();     //得到有效数据长度
		for(CountFor=0; CountFor<receDataLen; CountFor++)
		{
			safearray_inp.GetElement(&CountFor,receDataTemp+CountFor);   //转换为BYTE型数组
		}
		//将接收的数据转化为显示的字符串
		CString str, strTemp;
		for (int i=0; i<receDataLen; i++)
		{
			strTemp.Format("%02x ", receDataTemp[i]);
			str += strTemp;
		}
		//为回车、换行
		str +="\r\n";
		//将要显示的变量关联到前台显示界面
		m_display += str;
		//UpdataData(FALSE)为将变量更新到显示界面,UpdataData(TRUE)为将显示界面输入值更新到变量
		UpdateData(FALSE);
	}
}

以下为代码中所使用到的一些特殊数据类型和方法的简单解释:

COleSafeArray

COleSafeArray是一个从OLE VARIANT结构派生而来的类,用于处理任意类型和维数的数组。它可以通过Win32 API包装和一维数组操作来创建、访问和修改安全数组。VARIANT是一个结构体,可以封装不同的数据类型。要使用COleSafeArray,需要包含头文件。

COleSafeArray的GetELement方法

COleSafeArray的GetElement方法是用于获取安全数组中的一个单一元素。它需要一个索引地址(必须是long型)和一个指向接收数据的存储区域的指针作为参数。例如,如果要获取一个一维的COleSafeArray对象中的第三个元素,可以这样写:

COleSafeArray sa;
// 创建和初始化sa
long index = 2; // 索引从0开始,必须是long
VARIANT var;
sa.GetElement(&index, &var); // 获取第三个元素
// 处理var

为什么COleSafeArray的GetElement方法没有返回值

COleSafeArray的GetElement方法没有返回值,是因为它将获取的元素放在第二个参数指向的存储区域中。这样做的好处是,可以避免返回值的类型不匹配或内存泄漏的问题。如果你想要一个返回值,你可以使用COleVariant类来封装COleSafeArray对象,然后使用operator[]来访问元素,例如:

COleSafeArray sa;
// 创建和初始化sa
COleVariant var(sa); // 封装sa
VARIANT elem = var[2]; // 获取第三个元素
// 处理elem

关于缓冲区溢出

http://www.taodudu.cc/news/show-5587470.html?action=onClick

你可能感兴趣的:(C++,Modbus,c++,开发语言)