Mscomm32使用記錄

最近需要給一個肌電模塊做一個信號接收和看波形的GUI,沒學過C#也不想用processing之類的工具,想着用mfc做一個

出來。需求是通過串口接收數據。  

 首先下載Mscomm.ocxMscomm.dep兩個文件,放入SysWOW64文件夾(32位系統放sys32不用多說)。接着需要以管理員權限進cmd

命令regsvr32mscomm32.ocx進行註冊。可以直接找SysWOW64文件夾下的cmd.exe打開,對win7來說方便一些。

    mfcGUI還是挺好寫的。核心是在控件工具箱中右鍵->選擇項->COM組件->MicrosoftCommunications Control勾選後確定


這樣,工具箱中就出現了一個小電話


就是我們要用的串口控制控件。拖進對話框裏,看着很礙眼,但其實運行時是透明的。給他添加變量,類默認選擇CMscomm1。各種讀寫和打開關閉串口的函數都在這個類裏。

    CMscomm1中的成員函數分爲兩類,一類put前綴,一類get前綴。put前綴指發送,設置等主動功能,get指讀取,查看等操作。例如put_PortOpen(int n)函數是打開串口COMn(聽說n>10會出bug),get_PortOpen()是返回打開的串口號。

   重點並不在於CMscomm1的函數怎麼用,最坑的地方是讀寫數據的格式。get_Input()函數讀回來的格式是VARIANT,這種神奇的格式可以代表charstringintshortlong以及他們的一二級指針和數組類型。這大概是爲了讓cmatlabpython這些類型不強的語言交互吧…但是mfc自己用起來相當智熄。  


VARIANT get_Input()

{

 VARIANTresult;

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

 returnresult;
}


因爲VARIANT變量不是c標準庫中的類型,因此調試的時候會涉及一大堆奇怪的dll(還有各種連接符號服務器…),對我這種渣渣來說基本是沒法看懂他的單步過程的。所以格式轉換就非常玄學。

    VARIANT這種類型,從其定義來看,能看懂他的初衷。他是一個結構體,其中有許多類型的成員變量。大概就是variant.iVal代表對應的shortvariant.intVal代表對應的intvariant.cVal代表對應的char等等。

   我的目的是將get_Input()的結果轉換爲CString輸出到一個Edit框中,而向PC發串口消息的下位機是以BYTE類型發送的數字(也就是16ASCII碼的二進制電平)。在網上找了一些別人的代碼,主要有兩種。一種是用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這句也可以不寫,默認是文本方式





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章