编写串口调试助手并能在虚拟机中实现虚拟端口通信。步骤如下:
- 项目中引入Microsoft Communications Control组件,并编写串口初始化函数。
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)。
- 添加按钮“打开串口”的并编写相应代码。
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("打开串口失败,检查串口是否被占用");
}
}
- 添加按钮“发送数据”并编写相应代码。发送的数据后要添加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)));
}
- 添加文本显示框并实现串口数据接收。
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,需要包含<afxdisp.h>头文件。
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