Mscomm32使用记录

最近需要给一个肌电模块做一个信号接收和看波形的GUI,没学过C#也不想用processing之类的工具,想着用mfc做一个

出来。需求是通过串口接收数据。  

 首先下载Mscomm.ocx和Mscomm.dep两个文件,放入SysWOW64文件夹(32位系统放sys32不用多说)。接着需要以管理员权限进cmd,

命令regsvr32mscomm32.ocx进行注册。可以直接找SysWOW64文件夹下的cmd.exe打开,对win7来说方便一些。

    mfc的GUI还是挺好写的。核心是在控件工具箱中右键->选择项->COM组件->MicrosoftCommunications Control勾选后确定

 

这样,工具箱中就出现了一个小电话

就是我们要用的串口控制控件。拖进对话框里,看着很碍眼,但其实运行时是透明的。给他添加变量,类默认选择CMscomm1。各种读写和打开关闭串口的函数都在这个类里。

    CMscomm1中的成员函数分为两类,一类put前缀,一类get前缀。put前缀指发送,设置等主动功能,get指读取,查看等操作。例如put_PortOpen(int n)函数是打开串口COMn(听说n>10会出bug),get_PortOpen()是返回打开的串口号。

   重点并不在于CMscomm1的函数怎么用,最坑的地方是读写数据的格式。get_Input()函数读回来的格式是VARIANT,这种神奇的格式可以代表char,string,int,short,long以及他们的一二级指针和数组类型。这大概是为了让c和matlab,python这些类型不强的语言交互吧…但是mfc自己用起来相当智熄。  

 
VARIANT get_Input()

{

 VARIANTresult;

 InvokeHelper(0x1a,DISPATCH_PROPERTYGET, VT_VARIANT, (void*)&result, NULL);

 returnresult;
}

 

 

因为VARIANT变量不是c标准库中的类型,因此调试的时候会涉及一大堆奇怪的dll(还有各种连接符号服务器…),对我这种渣渣来说基本是没法看懂他的单步过程的。所以格式转换就非常玄学。

    VARIANT这种类型,从其定义来看,能看懂他的初衷。他是一个结构体,其中有许多类型的成员变量。大概就是variant.iVal代表对应的short,variant.intVal代表对应的int,variant.cVal代表对应的char等等。

   我的目的是将get_Input()的结果转换为CString输出到一个Edit框中,而向PC发串口消息的下位机是以BYTE类型发送的数字(也就是16位ASCII码的二进制电平)。在网上找了一些别人的代码,主要有两种。一种是用safearray进行中继,转换为BYTE数组。

 

variant_inp= m_ctrlComm.get_Input();

safearray_inp = variant_inp;

len= safearray_inp.GetOneDimSize();

for(k = 0; k < len; k++)

{

safearray_inp.GetElement(&k,&temp);

strTemp.Format(_T("%c"),temp);

RX_Display+= strTemp;

}

 

 

但是实际运行时,走到safearray_inp=variant_inp这步之后就直接跳出了,在len=下的断点根本断不到。可能冷门的类型是缺一些调试文件吧。最后RX_Display的监视结果是无法读取。

   另一种转换方式稍微靠谱一些

 

variant_inp= m_ctrlComm.get_Input();

char *ch = (char*)(unsigned char*)variant_inp.parray->pvdata;

 

 

但是Format转出来,不论是用%d%c%s要不然是一些韩文,奇怪的汉字,要不然就是一串数字(其中有一种可以把发送的第七个BYTE正确传输。。。也就是发送0000004可以收到4)。最后各种组合尝试了一遍,发现这样能够正确传输一个BYTE

 

variant_inp= m_ctrlComm.get_Input();

char*ch = (char*)variant_inp.parray;

RX_Display.Format(_T("%s"),ch);

 

 

但是这样只能收到一串数,没法满足我发送两位数三位数的需求。最后只能通过订传输协议解决

 

variant_inp= m_ctrlComm.get_Input();

char*ch = (char*)variant_inp.parray;

RX_Display.Format(_T("%s"),ch);

RX_Display= RX_Display.Mid(RX_Display.Find('<') + 1);

RX_Display= RX_Display.Left(RX_Display.Find('>'));

 

 

让RX_Display把<>中的数字取出来,但会造成一些数据的丢失。

 

**1月28日补充:今天打开程序想添加发送功能,结果发现前面改着改着又接不到数据了。折腾了一小时,总算恢复正常。需要补充一条:在使用本文最后给出的方法接收数据时,一定要在串口初始化时,设置put_InputMode(0),也就是用文本方式接收数据,否则接收不到正常的东西。put_InputMode这句也可以不写,默认是文本方式

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/Dio980/article/details/79170307