久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

標(biāo)題: Visual C++ MFC數(shù)據(jù)采集與通信及圖形顯示應(yīng)用程序的設(shè)計 [打印本頁]

作者: zhaoqingpeng    時間: 2018-11-30 17:25
標(biāo)題: Visual C++ MFC數(shù)據(jù)采集與通信及圖形顯示應(yīng)用程序的設(shè)計
2、設(shè)計任務(wù)書
設(shè)計MFC應(yīng)用程序,實現(xiàn)圖形顯示、數(shù)據(jù)采集和數(shù)據(jù)通信功能。程序設(shè)計可以選用下列兩種結(jié)構(gòu):
(1)基于對話框的MFC應(yīng)用程序;
(2)基于文檔/視圖的MFC應(yīng)用程序;
設(shè)計應(yīng)用程序界面時,可根據(jù)選用的程序結(jié)構(gòu),通過控件/菜單實現(xiàn)相關(guān)的控制功能。
2.1設(shè)計任務(wù)一:圖形顯示程序設(shè)計
1、根據(jù)功能要求設(shè)計軟件界面,設(shè)計圖形顯示區(qū)域的坐標(biāo)系統(tǒng)和坐標(biāo)變換公式,要求圖形顯示區(qū)域能夠顯示不少于200點數(shù)據(jù);
2、選用適當(dāng)?shù)睦L圖工具(包括畫筆、畫刷和字體等)和繪圖函數(shù)繪制圖形顯示區(qū)域;
3、使用隨機(jī)數(shù)函數(shù)rand()產(chǎn)生數(shù)據(jù),實現(xiàn)多點數(shù)據(jù)采集功能,每次采集一屏數(shù)據(jù),手動刷新;
4、使用隨機(jī)數(shù)函數(shù)rand()產(chǎn)生數(shù)據(jù),實現(xiàn)單點數(shù)據(jù)采集功能,每次采集一個數(shù)據(jù),引入WM_TIMER消息,實現(xiàn)定時采集并刷新。數(shù)據(jù)點數(shù)超過數(shù)據(jù)顯示區(qū)域范圍時,曲線自動左移,實現(xiàn)滾動顯示;
2.2設(shè)計任務(wù)二:數(shù)據(jù)采集程序設(shè)計
5、在項目中引入數(shù)據(jù)源設(shè)備DLL庫文件;
6、設(shè)計數(shù)據(jù)源設(shè)備控制模塊,包括設(shè)備打開、參數(shù)設(shè)置和設(shè)備關(guān)閉等模塊;
7、使用數(shù)據(jù)源設(shè)備DLL接口,實現(xiàn)單點數(shù)據(jù)采集功能,采集正弦波、方波和三角波等信號,每次采集一個數(shù)據(jù),引入WM_TIMER消息,實現(xiàn)定時采集并刷新;
2.3設(shè)計任務(wù)三:串口通信程序設(shè)計
8、在項目中引入MSCOMM串口通信控件,設(shè)計串口控制功能模塊,包括“打開串口”、“關(guān)閉串口”、“參數(shù)設(shè)置”和串口數(shù)據(jù)接收處理模塊;
9、根據(jù)MODBUS通信協(xié)議,實現(xiàn)軟件和模擬流量計的通信接口模塊,包括數(shù)據(jù)包組包、數(shù)據(jù)包解包和CRC校驗等模塊;
10、通過串口通信方式,采集模擬流量計的質(zhì)量流量數(shù)據(jù),引入WM_TIMER消息,實現(xiàn)定時采集并顯示質(zhì)量流量參數(shù)曲線。



3、軟件設(shè)計
經(jīng)過小組討論,確定了程序整體結(jié)構(gòu),選擇基于對話框的MFC應(yīng)用程序,應(yīng)用各種控件實現(xiàn)程序設(shè)計要求。
3.1圖形顯示程序設(shè)計
1、根據(jù)功能要求設(shè)計軟件界面,設(shè)計圖形顯示區(qū)域的坐標(biāo)系統(tǒng)和坐標(biāo)變換公式,要求圖形顯示區(qū)域能夠顯示不少于200點數(shù)據(jù);
設(shè)計方案1:坐標(biāo)系統(tǒng):邏輯坐標(biāo)系統(tǒng);設(shè)備坐標(biāo)系統(tǒng)(屏幕坐標(biāo)系統(tǒng)、窗口坐標(biāo)系統(tǒng)、用戶區(qū)坐標(biāo)系統(tǒng))。繪圖區(qū)域定位坐標(biāo)為六行十列,繪出一份從(0,0)到(520,320)的矩形網(wǎng)格,網(wǎng)格大小為50*50,坐標(biāo)功能實現(xiàn)在OnPanint()函數(shù)中,通過不斷刷新來實現(xiàn)數(shù)據(jù)的刷新。并且定義了一個m_npoint【】數(shù)組來儲存數(shù)據(jù)實現(xiàn)曲線數(shù)據(jù)點的儲存。
2、選用適當(dāng)?shù)睦L圖工具(包括畫筆、畫刷和字體等)和繪圖函數(shù)繪制圖形顯示區(qū)域;
設(shè)計方案2:
CPen類的成員函數(shù)CreatePen()用于創(chuàng)建畫筆,其原型為:
       BOOL CreatePen (int nPenStyle,
       int nWidth, COLORREF crColor);
1個參數(shù)是畫筆樣式,各種虛線只有當(dāng)線寬為1時有效。第2個參數(shù)為線寬,第3個參數(shù)為線的顏色,可使用RGB()宏指定。
創(chuàng)建畫刷的成員函數(shù)的原型為:
       BOOL CreateSolidBrush ( COLORREF crColor );
參數(shù)crColor指定了畫刷的顏色。除此而外,還可以創(chuàng)建一個陰影風(fēng)格的畫刷:
       BOOL CreateHatchBrush ( int nIndex,COLORREF crColor );
其中參數(shù)nIndex指定了陰影風(fēng)格。
繪圖用到紅色、綠色和藍(lán)色三種顏色寬度為3的線。
1)繪制直線
   CDC::MoveTo(int x, int y)
    將畫筆移動到當(dāng)前位置,即坐標(biāo)(x, y)處,并沒有畫線。
   CDC::LineTo(int x, int y)
   畫筆從當(dāng)前位置繪制一條子線到(x, y)點,但不包含(x, y)點。
(3) 繪制矩形
        CDC::Rectangle(int x1, int y1, int x2, int y2)
        參數(shù)x1、y1表示矩形左上角坐標(biāo),參數(shù)x2、y2表示矩形右下角坐標(biāo)。
  (6) 繪制橢圓函數(shù)
     CDC::Ellipse(int x1, int y1, int x2, int y2)
     參數(shù)x1、y1是繪制橢圓外接矩形左上角的坐標(biāo),x2、y2是外接矩形的右下角坐標(biāo)。當(dāng)繪制的外接矩形長和寬相同,即繪制的是圓。
3、使用隨機(jī)數(shù)函數(shù)rand()產(chǎn)生數(shù)據(jù),實現(xiàn)多點數(shù)據(jù)采集功能,每次采集一屏數(shù)據(jù),手動刷新;
設(shè)計方案3:圖形刷新是繪圖過程中必須考慮的重要問題,包括:刷新請求、對刷新請求的響應(yīng)、刷新方法。當(dāng)用戶區(qū)的內(nèi)容需要刷新時,系統(tǒng)向應(yīng)用程序消息隊列發(fā)送WM_PAINT消息。當(dāng)用戶拖動最小化窗口時系統(tǒng)調(diào)用此函數(shù)取得光標(biāo),操作界面為左側(cè)是網(wǎng)格,右側(cè)為多點采集的點擊窗口,點擊一次即對數(shù)據(jù)進(jìn)行采集,點擊刷新則刷新一次重新采集數(shù)據(jù)。

4、使用隨機(jī)數(shù)函數(shù)rand()產(chǎn)生數(shù)據(jù),實現(xiàn)單點數(shù)據(jù)采集功能,每次采集一個數(shù)據(jù),引入WM_TIMER消息,實現(xiàn)定時采集并刷新。數(shù)據(jù)點數(shù)超過數(shù)據(jù)顯示區(qū)域范圍時,曲線自動左移,實現(xiàn)滾動顯示;
設(shè)計方案4:定時器:可以幫助開發(fā)者或者用戶定時完成某項任務(wù)。在使用定時器時,我們可以給系統(tǒng)傳入一個時間間隔數(shù)據(jù),然后系統(tǒng)就會在每個此時間間隔后觸發(fā)定時處理程序,實現(xiàn)周期性的自動操作。例如,我們可以在數(shù)據(jù)采集系統(tǒng)中,為定時器設(shè)置定時采集時間間隔為1個小時,那么每隔1個小時系統(tǒng)就會采集一次數(shù)據(jù),這樣就可以在無人操作的情況下準(zhǔn)確的進(jìn)行操作。
MFC定時器:VS2010編程中,我們可以使用MFC的CWnd類提供的成員函數(shù)SetTimer實現(xiàn)定時器功能,也可以使用Windows API函數(shù)SetTimer來實現(xiàn)。兩者使用方法實際上很類似,但也有不同。CWnd類的SetTimer成員函數(shù)只能在CWnd類或其派生類中調(diào)用,而API函數(shù)SetTimer則沒有這個限制,這是一個很重要的區(qū)別。
單點采集及顯示:在定時器的ontimer()函數(shù)中,當(dāng)數(shù)據(jù)點沒超出顯示范圍時,利用隨機(jī)函數(shù)rand()產(chǎn)生數(shù)據(jù)依次儲存到m_point[]數(shù)組中,在onpaint()函數(shù)中,利用ployline()函數(shù)連接m_point()中的點,定義一個m_nPointNum變量,從1變到99,因此連接m_nPointNum個點,實現(xiàn)信號的單點采集。
滾動顯示:當(dāng)數(shù)據(jù)點超出顯示區(qū)域后,也就是m_nPointNum變量等于100時,m_point[]數(shù)組中的每一個數(shù)代替后一個數(shù)也就是m_Point[k].y = m_Point[k+1].y,然后只剩下一個m_point[99],令其等于新產(chǎn)生的隨機(jī)變量,實現(xiàn)滾動顯示。
單點采集開始后,添加控件函數(shù)Invalidate()通知處理程序代碼并且刷新窗口,當(dāng)采集點數(shù)超過屏幕時則顯示范圍左移,以此實現(xiàn)滾動顯示。

3.2數(shù)據(jù)采集程序設(shè)計
5、在項目中引入數(shù)據(jù)源設(shè)備DLL庫文件;
設(shè)計方案5:DLL(Dynamic Link Library)文件為動態(tài)鏈接庫文件,又稱“應(yīng)用程序拓展”,是軟件文件類型。在Windows中,許多應(yīng)用程序并不是一個完整的可執(zhí)行文件,它們被分割成一些相對獨立的動態(tài)鏈接庫,即DLL文件,放置于系統(tǒng)中。當(dāng)我們執(zhí)行某一個程序時,相應(yīng)的DLL文件就會被調(diào)用。一個應(yīng)用程序可使用多個DLL文件,一個DLL文件也可能被不同的應(yīng)用程序使用,這樣的DLL文件被稱為共享DLL文件。
lib庫:一種是靜態(tài)lib(static Lib),也就是最常見的lib庫,在編譯時直接將代碼加入程序當(dāng)中。靜態(tài)lib中,一個lib文件實際上是任意個obj文件的集合,obj文件是cpp文件編譯生成的。
另一種lib包含了函數(shù)所在的DLL文件和文件中函數(shù)位置的信息(入口),代碼由運行時加載在進(jìn)程空間中的DLL提供。也就是平時編寫dll時附帶產(chǎn)生的lib,其中Lib只是Dll的附帶品,是DLL導(dǎo)出的函數(shù)列表文件而已。
共同點:兩者都是二進(jìn)制文件,都是在鏈接時調(diào)用,使用static lib的exe可以直接運行,使用另一種lib的exe需要對應(yīng)的dll才能運行。
編譯之后生成一個mylib.lib的庫文件,引用庫文件如下:
1)右擊工程-->屬性(alt+F7)-->C/C++-->附加包含目錄--->包含所需要的頭文件;
2)右擊工程-->屬性(alt+F7)-->鏈接器-->常規(guī)--->附加目錄--->包含lib庫所在的目錄;
3)右擊工程-->屬性(alt+F7)-->輸入--->附加依賴項--->lib庫名。
這樣就能引用該lib內(nèi)的函數(shù)了。
dll的調(diào)用:
1)dll的顯示調(diào)用:前提是我們必須知道函數(shù)名、返回值、參數(shù)列表。此時不需要相應(yīng)的頭文件,也不需要lib文件。只需要對應(yīng)的dll就可以了。
這種情況下:HINSTANCE hInstance = LoadLibrary("mydll1.dll");會出現(xiàn)”2 IntelliSense: "const char *" 類型的實參與 "LPCWSTR" 類型的形參不兼容 “問題。解決辦法:工程--->屬性--->常規(guī)-->字符集--->使用多字節(jié)字符集就可以了。
2)dll的隱式調(diào)用:
這是相應(yīng)的lib庫就派上用場了,其用法static library用法一致。
總結(jié):顯示調(diào)用和隱式調(diào)用這兩種方法各有千秋,顯示調(diào)用優(yōu)點是只要接口參數(shù)列表沒有發(fā)生改變,修改了函數(shù)實現(xiàn)的細(xì)節(jié)也沒關(guān)系,所調(diào)用的exe程序不用重新編譯只需替換新版的dll就可以。在大的項目中只用比較方便,但調(diào)用過程相對復(fù)雜需要使用一系列的windows函數(shù)還有函數(shù)指針等。對于隱式調(diào)用和static library用法一致比較容易理解,缺點是只要修改了任意內(nèi)容相應(yīng)的exe都需要重新編譯。
6、設(shè)計數(shù)據(jù)源設(shè)備控制模塊,包括設(shè)備打開、參數(shù)設(shè)置和設(shè)備關(guān)閉等模塊;
設(shè)計方案6:數(shù)據(jù)源設(shè)備的操作界面為,左側(cè)為數(shù)據(jù)網(wǎng)格,右側(cè)為包括“設(shè)備打開”、“設(shè)備關(guān)閉”、“數(shù)據(jù)采集”、“停止”、“方波”、“三角波”、“正弦波”和“刷新”的界面,各個控件皆為按鈕控件。設(shè)備打開直接調(diào)用DLL庫中的OpenDevice()函數(shù),設(shè)備關(guān)閉直接調(diào)用DLL庫中的CloseDevice()函數(shù),參數(shù)設(shè)置需要用滾動條的采集點和滾動參數(shù)調(diào)用到DLL庫中的SetSignalPara()函數(shù),實現(xiàn)三個不同信號的參數(shù)設(shè)置,包括幅值,頻率,相位設(shè)置。
7、使用數(shù)據(jù)源設(shè)備DLL接口,實現(xiàn)單點數(shù)據(jù)采集功能,采集正弦波、方波和三角波等信號,每次采集一個數(shù)據(jù),引入WM_TIMER消息,實現(xiàn)定時采集并刷新;
設(shè)計方案7:三種信號的數(shù)據(jù)采集均為單點采集,切換采集信號類型的操作方式:設(shè)備打開后選擇波類型,然后開始數(shù)據(jù)采集。切換其他波時需先進(jìn)行“停止”,再清屏刷新,不然最新產(chǎn)生的波形會在之前產(chǎn)生的波形之后顯示,點擊其他波形后再點擊數(shù)據(jù)采集,從而進(jìn)行切換采集數(shù)據(jù)類型的操作。切換數(shù)據(jù)類型的方法是改變參數(shù)m_flag的值,然后通過ontimer()函數(shù)生成新的信號并且儲存,不斷刷新Onpaint()函數(shù)實現(xiàn)。
3.3串口通信程序設(shè)計
8、在項目中引入MSCOMM串口通信控件,設(shè)計串口控制功能模塊,包括“打開串口”、“關(guān)閉串口”、“參數(shù)設(shè)置”和串口數(shù)據(jù)接收處理模塊;
設(shè)計方案8:MSCOMM控件:屬性描述 CommPort 設(shè)置并返回通訊端口號。 Settings 以字符串的形式設(shè)置并返回波特率、奇偶校驗、數(shù)據(jù)位、停止位。 PortOpen 設(shè)置并返回通訊端口的狀態(tài)。也可以打開和關(guān)閉端口。 Input 從接收緩沖區(qū)返回和刪除字符。 Output 向傳輸緩沖區(qū)寫一個字符串。
“啟動串口”“關(guān)閉串口”“參數(shù)設(shè)置”均位于操作界面的左側(cè),“串口數(shù)據(jù)接收模塊”位于操作界面的右上方,各類流量計的參數(shù)顯示在相應(yīng)的參數(shù)區(qū)域內(nèi),“實時曲線”則位于操作界面的右下方,
9、根據(jù)MODBUS通信協(xié)議,實現(xiàn)軟件和模擬流量計的通信接口模塊,包括數(shù)據(jù)包組包、數(shù)據(jù)包解包和CRC校驗等模塊;
設(shè)計方案9:Modbus是一種串行通信協(xié)議,是Modicon公司(現(xiàn)在的施耐德電氣 Schneider Electric)于1979年為使用可編程邏輯控制器(PLC)通信而發(fā)表。Modbus已經(jīng)成為工業(yè)領(lǐng)域通信協(xié)議的業(yè)界標(biāo)準(zhǔn)(De facto),并且現(xiàn)在是工業(yè)電子設(shè)備之間常用的連接方式。
使用RING BUFF,接收部分就接收不分析數(shù)據(jù),然后外面單獨解碼,可以再加上超時RESET。或者直接用dll或庫里的函數(shù)的參數(shù),程序調(diào)用函數(shù)時,直接把通信內(nèi)容放參數(shù)里。
CRC校驗原理:
其根本思想就是先在要發(fā)送的幀后面附加一個數(shù)(這個就是用來校驗的校驗碼,但要注意,這里的數(shù)也是二進(jìn)制序列的,下同),生成一個新幀發(fā)送給接收端。當(dāng)然,這個附加的數(shù)不是隨意的,它要使所生成的新幀能與發(fā)送端和接收端共同選定的某個特定數(shù)整除(注意,這里不是直接采用二進(jìn)制除法,而是采用一種稱之為“模2除法”)。到達(dá)接收端后,再把接收到的新幀除以(同樣采用“模2除法”)這個選定的除數(shù)。因為在發(fā)送端發(fā)送數(shù)據(jù)幀之前就已通過附加一個數(shù),做了“去余”處理(也就已經(jīng)能整除了),所以結(jié)果應(yīng)該是沒有余數(shù)。如果有余數(shù),則表明該幀在傳輸過程中出現(xiàn)了差錯。
2除法:
2除法與算術(shù)除法類似,但每一位除的結(jié)果不影響其它位,即不向上一位借位,所以實際上就是異或。在循環(huán)冗余校驗碼(CRC)的計算中有應(yīng)用到模2除法。
CRC校驗步驟:
CRC校驗中有兩個關(guān)鍵點,一是預(yù)先確定一個發(fā)送送端和接收端都用來作為除數(shù)的二進(jìn)制比特串(或多項式),可以隨機(jī)選擇,也可以使用國際標(biāo)準(zhǔn),但是最高位和最低位必須為1;二是把原始幀與上面計算出的除數(shù)進(jìn)行模2除法運算,計算出CRC碼。
具體步驟:
1)選擇合適的除數(shù);
2)看選定除數(shù)的二進(jìn)制位數(shù),然后再要發(fā)送的數(shù)據(jù)幀上面加上這個位數(shù)-1位的0,然后用新生成的幀以模2除法的方式除上面的除數(shù),得到的余數(shù)就是該幀的CRC校驗碼。注意,余數(shù)的位數(shù)一定只比除數(shù)位數(shù)少一位,也就是CRC校驗碼位數(shù)比除數(shù)位數(shù)少一位,如果前面位是0也不能省略;
3)將計算出來的CRC校驗碼附加在原數(shù)據(jù)幀后面,構(gòu)建成一個新的數(shù)據(jù)幀進(jìn)行發(fā)送;最后接收端在以模2除法方式除以前面選擇的除數(shù),如果沒有余數(shù),則說明數(shù)據(jù)幀在傳輸?shù)倪^程中沒有出錯。
先將一個float型轉(zhuǎn)化為內(nèi)存存儲格式的步驟:
1)先將這個實數(shù)的絕對值化為二進(jìn)制格式;
2)將這個二進(jìn)制格式實數(shù)的小數(shù)點左移或右移n位,直到小數(shù)點移動到第一個有效數(shù)字的右邊;
3)從小數(shù)點右邊第一位開始數(shù)出二十三位數(shù)字放入第22到第0位;
4)如果實數(shù)是正的,則在第31位放入“0”,否則放入“1”;
5)如果n是左移得到的,說明指數(shù)是正的,第30位放入“1”。如果n是右移得到的或n=0,則第30位放入“0”;
6)如果n是左移得到的,則將n減去1后化為二進(jìn)制,并在左邊加“0”補足七位,放入第29到第23位。
如果n是右移得到的或n=0,則將n化為二進(jìn)制后在左邊加“0”補足七位,再各位求反,再放入第29到第23位。
再將一個內(nèi)存存儲的float二進(jìn)制格式轉(zhuǎn)化為十進(jìn)制:
1)將第22位到第0位的二進(jìn)制數(shù)寫出來,在最左邊補一位“1”,得到二十四位有效數(shù)字。將小數(shù)點點在最左邊那個“1”的右邊;
2)取出第29到第23位所表示的值n。當(dāng)30位是“0”時將n各位求反。當(dāng)30位是“1”時將n增1;
3)將小數(shù)點左移n位(當(dāng)30位是“0”時)或右移n位(當(dāng)30位是“1”時),得到一個二進(jìn)制表示的實數(shù);
4)將這個二進(jìn)制實數(shù)化為十進(jìn)制,并根據(jù)第31位是“0”還是“1”加上正號或負(fù)號即可。
10、通過串口通信方式,采集模擬流量計的質(zhì)量流量數(shù)據(jù),引入WM_TIMER消息,實現(xiàn)定時采集并顯示質(zhì)量流量參數(shù)曲線。
設(shè)計方案10:
將采集到的數(shù)據(jù)中反映質(zhì)量流量的數(shù)據(jù)存入一一個BYTE類型的數(shù)組,轉(zhuǎn)換為float類型后,進(jìn)行參數(shù)曲線繪制,由于顯示區(qū)域顯示數(shù)值最大為300,而采集數(shù)據(jù)值的范圍約為0 3600,所以將采集數(shù)據(jù)乘系數(shù)-0.05并且起點加上310的偏移量,以便于在圖形顯示區(qū)進(jìn)行顯示。

4、軟件開發(fā)實現(xiàn)
4.1圖形顯示程序?qū)崿F(xiàn)代碼說明
1、根據(jù)功能要求設(shè)計軟件界面,設(shè)計圖形顯示區(qū)域的坐標(biāo)系統(tǒng)和坐標(biāo)變換公式,要求圖形顯示區(qū)域能夠顯示不少于200點數(shù)據(jù);
代碼段1:本段代碼實現(xiàn)了繪制網(wǎng)格線的功能
代碼:
        CPaintDC dc(this);
        CPen PenGrid;
        CPen PenLine;
        CPen *pOldPen = NULL;
        dc.Rectangle(0,0,520,320);
        PenGrid.CreatePen(PS_DASH,1,RGB(255,0,0));
        pOldPen = dc.SelectObject(&PenGrid);
        for(int k=0; k<7;k++) //  畫方格線
        {
                dc.MoveTo(10,10+50*k);
                dc.LineTo(510,10+50*k);
        }
        for(int k=0; k<11; k++)
        {
                dc.MoveTo(10+50*k,10);
                dc.LineTo(10+50*k,310);
        }
2、選用適當(dāng)?shù)睦L圖工具(包括畫筆、畫刷和字體等)和繪圖函數(shù)繪制圖形顯示區(qū)域;
代碼段1:本段代碼實現(xiàn)了選線型的功能
代碼:
        UpdateData(TRUE);//DDX 控件--〉變量  
        switch(m_nLineStyle)  //選線型
        {
        case 0:
                PenLine.CreatePen(PS_SOLID,3,
                        RGB(m_Red.GetScrollPos(),
                            m_Green.GetScrollPos(),
                                m_Blue.GetScrollPos()));
                break;
        case 1:
                PenLine.CreatePen(PS_DASH,1,
                        RGB(m_Red.GetScrollPos(),
                            m_Green.GetScrollPos(),
                                m_Blue.GetScrollPos()));
                break;
        case 2:
                PenLine.CreatePen(PS_DOT,1,
                        RGB(m_Red.GetScrollPos(),
                            m_Green.GetScrollPos(),
                                m_Blue.GetScrollPos()));
                break;
        }
3、使用隨機(jī)數(shù)函數(shù)rand()產(chǎn)生數(shù)據(jù),實現(xiàn)多點數(shù)據(jù)采集功能,每次采集一屏數(shù)據(jù),手動刷新;
代碼段1:本段代碼實現(xiàn)了多點采集數(shù)據(jù)的功能
代碼:
void CDemoDlg::OnClickedRefresh()   //多點采集 手動刷新
{
        // TODO: 在此添加控件通知處理程序代碼
        m_flag=0;
        for(int k=0; k<100;k++)
        {
                m_Point[k].x = 10+5*k;
                m_Point[k].y = 10+rand()%300;
        }
        Invalidate();// 發(fā)送WM_PAINT消息
}
void CDemoDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)//顏色設(shè)置滑動塊
{
        // TODO: 在此添加消息處理程序代碼和/或調(diào)用默認(rèn)值
        UINT Pos;
        switch(nSBCode)
        {
        case SB_THUMBTRACK://拖動滑動塊
                pScrollBar->SetScrollPos(nPos);
                break;
        case SB_LINELEFT:
                Pos = pScrollBar->GetScrollPos();
                pScrollBar->SetScrollPos(Pos-10);
                break;
        case SB_LINERIGHT:
                Pos = pScrollBar->GetScrollPos();
                pScrollBar->SetScrollPos(Pos+10);
                break;
        case SB_PAGELEFT:
                Pos = pScrollBar->GetScrollPos();
                pScrollBar->SetScrollPos(Pos-30);
                break;
        case SB_PAGERIGHT:
                Pos = pScrollBar->GetScrollPos();
                pScrollBar->SetScrollPos(Pos+30);
                break;
        }
        Invalidate();// 發(fā)送WM_PAINT消息
        CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
4、使用隨機(jī)數(shù)函數(shù)rand()產(chǎn)生數(shù)據(jù),實現(xiàn)單點數(shù)據(jù)采集功能,每次采集一個數(shù)據(jù),引入WM_TIMER消息,實現(xiàn)定時采集并刷新。數(shù)據(jù)點數(shù)超過數(shù)據(jù)顯示區(qū)域范圍時,曲線自動左移,實現(xiàn)滾動顯示;
代碼段1:本段代碼實現(xiàn)了單點采集數(shù)據(jù)的功能
代碼:
void CDemoDlg::OnClickedShownow()   //實現(xiàn)單點采集
{   m_flag=1;
        SetTimer(1,50,NULL);
        m_nRunSta = 1;
}
void CDemoDlg::OnBnClickedShowstop()   //停止采集
{
        KillTimer(1);
        m_nRunSta = 0;// TODO: 在此添加控件通知處理程序代碼
}
void CDemoDlg::OnTimer(UINT nIDEvent)   //單點采集定時循環(huán)
{
      if(m_nPointNum<100)
            {
                m_Point[m_nPointNum].x = 10+5*m_nPointNum;
                m_Point[m_nPointNum].y = 10+rand()%300;
                m_nPointNum++;
             }
              else    //點數(shù)超過屏幕顯示范圍左移
             {
                for(int k=0; k<99; k++)
                {
                        m_Point[k].y = m_Point[k+1].y;
                }
                m_Point[99].y = 10+rand()%300;
        }
        Invalidate();  // 通知刷新窗口
    CDialog::OnTimer(nIDEvent);
}
if(m_flag==1)   //單點采集
        {
        dc.Polyline(m_Point,m_nPointNum);
        }

4.2數(shù)據(jù)采集程序?qū)崿F(xiàn)代碼說明
5、在項目中引入數(shù)據(jù)源設(shè)備DLL庫文件;
代碼段1:本段代碼實現(xiàn)了引入頭文件的功能
    代碼:#include "MyDLL.h"
// DemoDlg.cpp : 實現(xiàn)文件
//
#include "stdafx.h"
#include "Demo.h"
#include "DemoDlg.h"
#include "afxdialogex.h"
#include "MyDLL.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
DLL文件:
extern "C"
{
        int  OpenDevice();/// 打開設(shè)備
        /// 返回值:0-成功 其他-失敗
        void  SetSignalPara(int pSigType, double pAmp, double pFreq, double pPhase0);/// 設(shè)置信號參數(shù)
        /// pSigType:信號類型,0-正弦信號;1-方波信號;2-三角波信號
        /// pAmp:信號幅值
        /// pFreq:信號頻率,單位:HZ
        /// pPhase0:信號初始相位,單位:弧度        

    void  SetSWDuty(double pDuty);/// 設(shè)置方波占空比/// pDuty:方波占空比,取值范圍0.00-1.00

        void  SetSampPara(double pSampFreq);/// 設(shè)置采樣參數(shù)        /// pSampFreq:采樣頻率,單位:點/秒

        int ReadOneData(double *pData);/// 采集正弦信號數(shù)據(jù)(單點)
        /// pData:數(shù)據(jù)緩存區(qū)地址
        /// 返回值:0-成功 其他-失敗

        int ReadData(int Num, double *pData);/// 采集正弦信號數(shù)據(jù)(多點)
        /// Num:數(shù)據(jù)點數(shù)
        /// pData:數(shù)據(jù)緩存區(qū)地址
        /// 返回值:0-成功 其他-失敗

        int CloseDevice(void);/// 關(guān)閉設(shè)備
        /// 返回值:0-成功 其他-失敗
}
6、設(shè)計數(shù)據(jù)源設(shè)備控制模塊,包括設(shè)備打開、參數(shù)設(shè)置和設(shè)備關(guān)閉等模塊;
代碼段1:本段代碼實現(xiàn)了設(shè)備打開和關(guān)閉的功能
    void CDemoDlg::OnClickedRun()
{   
        OpenDevice();
    AfxMessageBox(_T("設(shè)備打開成功"));
        // TODO: 在此添加控件通知處理程序代碼
}
void CDemoDlg::OnBnClickedClose()
{
        // TODO: 在此添加控件通知處理程序代碼
        CloseDevice();
        AfxMessageBox(_T("設(shè)備關(guān)閉成功"));
}
代碼段2:實現(xiàn)了參數(shù)設(shè)置功能
//參數(shù)設(shè)置初始化
        m_fuzhi.SetScrollRange(0,150);
        m_fuzhi.SetScrollPos(150);
        m_pinlv.SetScrollRange(10,150);
        m_pinlv.SetScrollPos(10);
        m_xiangwei.SetScrollRange(0,150);
        m_xiangwei.SetScrollPos(0);

void CDemoDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)    //滾動條拖動處理參數(shù)
{
        // TODO: 在此添加消息處理程序代碼和/或調(diào)用默認(rèn)值
        UINT Pos;
        switch(nSBCode)
        {
        case SB_THUMBTRACK://拖動滑動塊
                pScrollBar->SetScrollPos(nPos);
                break;
        case SB_LINELEFT:
                Pos = pScrollBar->GetScrollPos();
                pScrollBar->SetScrollPos(Pos-10);
                break;
        case SB_LINERIGHT:
                Pos = pScrollBar->GetScrollPos();
                pScrollBar->SetScrollPos(Pos+10);
                break;
        case SB_PAGELEFT:
                Pos = pScrollBar->GetScrollPos();
                pScrollBar->SetScrollPos(Pos-30);
                break;
        case SB_PAGERIGHT:
                Pos = pScrollBar->GetScrollPos();
                pScrollBar->SetScrollPos(Pos+30);
                break;
        }
        Invalidate();// 發(fā)送WM_PAINT消息
        CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}

SetSignalPara(0,m_fuzhi.GetScrollPos(),m_pinlv.GetScrollPos(),m_xiangwei.GetScrollPos())  //參數(shù)代入到信號類型采集函數(shù)中,實現(xiàn)參數(shù)的變化呈現(xiàn)

7、使用數(shù)據(jù)源設(shè)備DLL接口,實現(xiàn)單點數(shù)據(jù)采集功能,采集正弦波、方波和三角波等信號,每次采集一個數(shù)據(jù),引入WM_TIMER消息,實現(xiàn)定時采集并刷新;
代碼段1:本段代碼實現(xiàn)了正弦波、方波和三角波的單點信號采集
    代碼:
void CDemoDlg::OnTimer(UINT nIDEvent)    //定時單點采集
{
        if(m_flag==0)          //正弦信號單點采集
     { if(m_nPointNum<100)
            {
                        SetSignalPara(0,1, 30, 0);
                        double dblData[100];
                ReadData(100,dblData);
                m_Point[m_nPointNum].y = 160-150*dblData[m_nPointNum];
                m_nPointNum++;
             }
              else
             {
                for(int k=0; k<99; k++)
                {
                        m_Point[k].y = m_Point[k+1].y;
                }
                SetSignalPara(0,1, 30, 0);
                        double dblData[10000];
                ReadData(10000,dblData);
                m_Point[99].y = 160-150*dblData[m_k];
                m_k++;
        }
        Invalidate();  // 通知刷新窗口
}
    else if(m_flag==1)          //方波信號單點采集
     {
                 if(m_nPointNum<100)
            {
                        SetSignalPara(1,1, 30, 0);
                        SetSWDuty(0.5);
                        double dblData[100];
                ReadData(100,dblData);
                m_Point[m_nPointNum].y = 160-150*dblData[m_nPointNum];
                m_nPointNum++;
             }
              else
             {
                for(int k=0; k<99; k++)
                {
                        m_Point[k].y = m_Point[k+1].y;
                }
                    SetSignalPara(1,1, 30, 0);
                    SetSWDuty(0.5);
                        double dblData[10000];
                ReadData(10000,dblData);
                m_Point[99].y = 160-150*dblData[m_k];
                m_k++;
        }
        Invalidate();  // 通知刷新窗口
}
        else if(m_flag==2)          //三角波信號單點采集
     {
                 if(m_nPointNum<100)
            {
                        SetSignalPara(2,1,30,0);
                        double dblData[10000];
                ReadData(10000,dblData);
                m_Point[m_nPointNum].y = 160-150*dblData[m_nPointNum];
                m_nPointNum++;
             }
              else
             {
                for(int k=0; k<99; k++)
                {
                        m_Point[k].y = m_Point[k+1].y;
                }
                    SetSignalPara(2,1, 30, 0);
                        double dblData[10000];
                ReadData(1000,dblData);
                m_Point[99].y = 160-150*dblData[m_k];
                m_k++;
        }
        Invalidate();  // 通知刷新窗口
}
    CDialog::OnTimer(nIDEvent);
}  //    //單點

void CDemoDlg::OnClickedShownow()   //數(shù)據(jù)開始采集
{  
        SetTimer(1,50,NULL);
}
void CDemoDlg::OnBnClickedShowstop()   //停止采集
{
        KillTimer(1);
}
        dc.Polyline(m_Point,m_nPointNum);  //實現(xiàn)單點的曲線繪制
4.3串口通信程序?qū)崿F(xiàn)代碼說明
8、在項目中引入MSCOMM串口通信控件,設(shè)計串口控制功能模塊,包括“打開串口”、“關(guān)閉串口”、“參數(shù)設(shè)置”和串口數(shù)據(jù)接收處理模塊;
代碼段1:本段代碼實現(xiàn)了設(shè)置串口參數(shù)的功能
    void CCommDlg::InitComm(int iComport,int bps)
{
        m_Comm.SetCommPort(iComport);
        m_Comm.SetInBufferSize(1024);
        m_Comm.SetOutBufferSize(1024);
        if(!m_Comm.GetPortOpen())
        {
                m_Comm.SetPortOpen(TRUE);
        }
        m_Comm.SetInputMode(1);                       
        CString strparm;
        strparm.Format("%d,n,8,1",bps);
        m_Comm.SetSettings(strparm);
        m_Comm.SetRThreshold(1);      
      
        m_Comm.SetInBufferCount(0);      
      
}
代碼段2:本段代碼實現(xiàn)了串口開關(guān)的功能
void CCommDlg::OnStopreceive()
{
   if(m_Comm.GetPortOpen())
   {
       m_Comm.SetPortOpen(FALSE);
           AfxMessageBox("關(guān)閉串口成功");
   }
   else
   {
            AfxMessageBox("串口未打開 ");
   }
}
void CCommDlg::OnStartreceive()
{
        CCommApp* pApp = (CCommApp*)AfxGetApp();
        UpdateData(TRUE);
        pApp->m_nPort = atoi(m_Port);
        int n = pApp->m_nPort;
        int bps =  atoi(m_bps);;
    InitComm(n, bps);
        if(m_Comm.GetPortOpen())
        {
                AfxMessageBox("打開串口成功");
        }
        else
        {
                AfxMessageBox("打開失敗");
        }
9、根據(jù)MODBUS通信協(xié)議,實現(xiàn)軟件和模擬流量計的通信接口模塊,包括數(shù)據(jù)包組包、數(shù)據(jù)包解包和CRC校驗等模塊;
代碼段1:本段代碼實現(xiàn)了數(shù)據(jù)傳送的功能
void CCommDlg::OnSend()
{
        TODO: Add your control notification handler code here
InitComm();
        UpdateData(TRUE);
        int Count=m_Send.GetLength();
        CByteArray m_Array;
        m_Array.RemoveAll();
        m_Array.SetSize(Count);
    for(int i=0;i<Count;i++)
                m_Array.SetAt(i,m_Send);
        m_Comm.SetOutput(COleVariant(m_Array));      
        UpdateData(FALSE);
}
代碼段2:本段代碼實現(xiàn)了CRC檢驗功能
WORD CRC16(BYTE *ptr, int len)
{
        WORD wcrc = 0xFFFF; // 預(yù)置16位crc寄存器,初值全部為1
        BYTE temp; // 定義中間變量
        int i = 0, j = 0; // 定義計數(shù)
        for (i = 0; i < len; i++) // 循環(huán)計算每個數(shù)據(jù)
        {
                temp = *ptr & 0x00FF; // 將八位數(shù)據(jù)與crc寄存器亦或
                ptr++; // 指針地址增加,指向下個數(shù)據(jù)
                wcrc ^= temp; // 將數(shù)據(jù)存入crc寄存器
                for (j = 0; j < 8; j++) // 循環(huán)計算數(shù)據(jù)的
                {
                        if (wcrc & 0x0001) // 判斷右移出的是不是1,如果是1則與多項式進(jìn)行異或。
                        {
                                wcrc >>= 1; // 先將數(shù)據(jù)右移一位
                                wcrc ^= 0xA001; // 與上面的多項式進(jìn)行異或
                        }
                        else // 如果不是1,則直接移出
                        {
                                wcrc >>= 1;//直接移出
                        }
                }
        }
        return (unsigned int)(wcrc);
}
代碼段3:本段代碼實現(xiàn)了float字節(jié)轉(zhuǎn)換類型功能
static int m_nFLMode1 = 1; //浮點數(shù)字節(jié)序
float TransferFloat(BYTE *pBytes)
{
        float fltRetVal = 0.00;
        BYTE *p = (BYTE*)&fltRetVal;
        static BYTE nIdx[4][4] = { { 0, 1, 2, 3 }, { 1, 0, 3, 2 }, { 2, 3, 0, 1 }, { 3, 2, 1, 0 } };
        for (int k = 0; k < sizeof(float); k++)
        {
                p[nIdx[m_nFLMode1][k]] = *pBytes++;
        }
        return fltRetVal;
}
10、通過串口通信方式,采集模擬流量計的質(zhì)量流量數(shù)據(jù),引入WM_TIMER消息,實現(xiàn)定時采集并顯示質(zhì)量流量參數(shù)曲線。
代碼段1:本段代碼實現(xiàn)了繪制網(wǎng)格線的功能
  CGdiObject* pOldPen = pDC->SelectObject(pPenLine);   
        int ipontstart = 10;
        rect = CRect(rect.left+ipontstart, rect.top+ipontstart,rect.right-ipontstart,rect.bottom-ipontstart);
        for (i = 0; i <= max_nums_x; i++)
        {
                 pDC->MoveTo(ipontstart + 1.0*rect.Width() /max_nums_x * i,ipontstart + rect.Height());
                 pDC->LineTo(ipontstart + 1.0*rect.Width() /max_nums_x * i,ipontstart);
        }
                for ( i = 0; i <= max_nums_y ; i++)
        {
                pDC->MoveTo(ipontstart ,ipontstart +1.0*rect.Height()/max_nums_y*i);
                pDC->LineTo(ipontstart+ rect.Width() , ipontstart +1.0*rect.Height()/max_nums_y*i);
        }
      
      
      
    pOldPen = pDC->SelectObject(pPenBlue);
            int lenwith = rect.Width()/max_nums_x;
    for ( i = 1; i < m_pointnumshava; i++)
    {
                int lentemp = m_fIntensity[i-1]/max_ydata*rect.Height();
代碼段2:本段代碼實現(xiàn)了繪制流量曲線的功能
void CCommDlg::OnTimer(UINT nIDEvent)
{
        // TODO: Add your message handler code here and/or call default
        if (nIDEvent ==1)
        {
                //發(fā)送命令
                if(m_Comm.GetPortOpen() ==FALSE) return;
                UCHAR Sendbuf[8] = {0x01, 0x03 ,0x13, 0xBA,0x00,0x0F,0x20,0xAF};
                CByteArray m_Array;//CByteArray構(gòu)造一個空的字節(jié)數(shù)組
                m_Array.RemoveAll();
                m_Array.SetSize(sizeof(Sendbuf));
                for(int i=0;i<sizeof(Sendbuf);i++)
                        m_Array.SetAt(i,Sendbuf);
                //發(fā)送
                m_Comm.SetOutput(COleVariant(m_Array));//向緩沖區(qū)寫數(shù)據(jù)流
                Sleep(500);
                UpdateData(TRUE);
                //處理顯示原始數(shù)據(jù)
                VARIANT m_input;
                int count = m_Comm.GetInBufferCount();  
                if(count< 35) return;
                if( count >= 35) count = 35;
                UCHAR * porgdata;
                if(count > 0)
                //得到接收數(shù)據(jù)
                m_input = m_Comm.GetInput();//從緩沖區(qū)取走一串字符
                porgdata = (unsigned char*)m_input.parray->pvData;
                CString strshouw;
                m_Receive = "";
                for (int i = 0; i < count ; i++)
                {
                        strshouw.Format("%02x ",porgdata);
                        m_Receive +=strshouw;
                }
                // 顯示數(shù)據(jù)      
                UpdateData(FALSE);
                if(porgdata[0] != 0x01) return;
                if(porgdata[1] != 0x03) return;
               
                //判斷校驗
               
                WORD crc16 =CRC16(porgdata,33);
                WORD crc162;
                memcpy(&crc162,porgdata+33,2);
                if(crc162 != crc16)
                        return;
                //顯示數(shù)據(jù)
                int off = 3;
                float retVal1 = TransferFloat(porgdata+off); //質(zhì)量流量
                off+=4;
                float retVal2 = TransferFloat(porgdata+off); //體積流量
                off+=4;
                float retVal3 = TransferFloat(porgdata+off); //密度
                off+=4;
                float retVal4 = TransferFloat(porgdata+off); //溫度
                off+=4;
                float retVal5 = TransferFloat(porgdata+off); //累積和1
                off+=4;
                float retVal6 = TransferFloat(porgdata+off); //累積和2
                off+=4;
                float retVal7 = TransferFloat(porgdata+off); //累積和3
                off+=4;
                WORD status =0 ;
                memcpy(&status,porgdata+off,2);
                CString strtemp;
                strtemp.Format("%.3f",retVal1);
                GetDlgItem(IDC_EDIT1)->SetWindowText(strtemp);
                strtemp.Format("%.3f",retVal2);
                GetDlgItem(IDC_EDIT2)->SetWindowText(strtemp);
                strtemp.Format("%.3f",retVal3);
                GetDlgItem(IDC_EDIT3)->SetWindowText(strtemp);
                strtemp.Format("%.3f",retVal4);
                GetDlgItem(IDC_EDIT4)->SetWindowText(strtemp);
                strtemp.Format("%.3f",retVal5);
                GetDlgItem(IDC_EDIT5)->SetWindowText(strtemp);
                strtemp.Format("%.3f",retVal6);
                GetDlgItem(IDC_EDIT6)->SetWindowText(strtemp);
                strtemp.Format("%.3f",retVal7);
                GetDlgItem(IDC_EDIT7)->SetWindowText(strtemp);
                strtemp.Format("%d",status);
                GetDlgItem(IDC_EDIT8)->SetWindowText(strtemp);
                drawChart(retVal1);
        }
      
        CDialog::OnTimer(nIDEvent);
}
5、軟件測試
5.1圖形顯示程序測試
1、根據(jù)功能要求設(shè)計軟件界面,設(shè)計圖形顯示區(qū)域的坐標(biāo)系統(tǒng)和坐標(biāo)變換公式,要求圖形顯示區(qū)域能夠顯示不少于200點數(shù)據(jù);
2、選用適當(dāng)?shù)睦L圖工具(包括畫筆、畫刷和字體等)和繪圖函數(shù)繪制圖形顯示區(qū)域;
3、使用隨機(jī)數(shù)函數(shù)rand()產(chǎn)生數(shù)據(jù),實現(xiàn)多點數(shù)據(jù)采集功能,每次采集一屏數(shù)據(jù),手動刷新;
4、使用隨機(jī)數(shù)函數(shù)rand()產(chǎn)生數(shù)據(jù),實現(xiàn)單點數(shù)據(jù)采集功能,每次采集一個數(shù)據(jù),引入WM_TIMER消息,實現(xiàn)定時采集并刷新。數(shù)據(jù)點數(shù)超過數(shù)據(jù)顯示區(qū)域范圍時,曲線自動左移,實現(xiàn)滾動顯示;
測試結(jié)果如下:
圖5.1為初次運行未進(jìn)行任何操作時軟件界面。功能區(qū)為數(shù)據(jù)采集方式設(shè)置,分別為單點采集、多點采集,以及隨機(jī)函數(shù)rand()曲線的顯示方式,分別為實線、虛線和點線式。下方為曲線顏色設(shè)置,初始參數(shù)為紅色 RGB(255,0,0)
選擇單點采集【RGB(255,255,0)】時數(shù)據(jù)采集如圖5.2所示,多點采集【RGB(255,255,0)】時數(shù)據(jù)采集如圖5.3所示,并以多點采集為例,分別改變函數(shù)曲線的顯示屬性。實線顯示【RGB(255,0,255)】圖5.3,虛線顯示【RGB(0,0,255)】圖5.4,點線顯示【RGB(255,0,0)】圖5.5,并通過改變RGB值來改變曲線顏色。
測試結(jié)論:圖形顯示程序初步實現(xiàn)了設(shè)計任務(wù)中的所有要求,并能方便的改變顯示數(shù)據(jù)的曲線顏色、采樣方式等屬性。
圖5-1
圖5-2
圖5-3
圖5-4
圖5-5
5.2數(shù)據(jù)采集程序測試
5、在項目中引入數(shù)據(jù)源設(shè)備DLL庫文件;
6、設(shè)計數(shù)據(jù)源設(shè)備控制模塊,包括設(shè)備打開、參數(shù)設(shè)置和設(shè)備關(guān)閉等模塊;
7、使用數(shù)據(jù)源設(shè)備DLL接口,實現(xiàn)單點數(shù)據(jù)采集功能,采集正弦波、方波和三角波等信號,每次采集一個數(shù)據(jù),引入WM_TIMER消息,實現(xiàn)定時采集并刷新;
測試結(jié)果如下:
圖5.6為初次運行未進(jìn)行任何操作時軟件界面。功能區(qū)為信號發(fā)生設(shè)置、采集設(shè)置和顯示設(shè)置。首先打開設(shè)備,如圖5.7,選擇數(shù)據(jù)采集并分別方波、正弦波和三角波信號,如圖5.8-5.10所示,可以根據(jù)采集需求切換函數(shù)曲線顏色、線型。
測試結(jié)論:程序可以實現(xiàn)單點采集功能,并分別采集正弦波、方波和三角波信號。并能實現(xiàn)刷新功能。
圖5.6
圖5.7
圖5.8
圖5.9
圖5.10
5.3串口通信程序?qū)崪y試
8、在項目中引入MSCOMM串口通信控件,設(shè)計串口控制功能模塊,包括“打開串口”、“關(guān)閉串口”、“參數(shù)設(shè)置”和串口數(shù)據(jù)接收處理模塊;
9、根據(jù)MODBUS通信協(xié)議,實現(xiàn)軟件和模擬流量計的通信接口模塊,包括數(shù)據(jù)包組包、數(shù)據(jù)包解包和CRC校驗等模塊;
10、通過串口通信方式,采集模擬流量計的質(zhì)量流量數(shù)據(jù),引入WM_TIMER消息,實現(xiàn)定時采集并顯示質(zhì)量流量參數(shù)曲線。
測試結(jié)果如下:
如圖5.11所示,模擬流量計界面分為參數(shù)設(shè)置、數(shù)據(jù)顯示和開


作者: missingxu    時間: 2022-4-1 08:22
Hello, MFC 控制的源工程文件方便發(fā)一下學(xué)習(xí)嗎?謝謝!




歡迎光臨 (http://m.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 成人一级视频 | 久久久亚洲精品视频 | 亚洲精品乱码 | 黄色小说视频网站 | 国产一区免费视频 | 日韩精品影视 | 免费看av的网址 | 欧美777| 黄色小视频免费看 | 日韩精品网站 | 九九在线 | 成人黄色录像 | 欧美一级二级三级 | 日本国产精品 | 国产色视频一区二区三区qq号 | 日本黄色片视频 | 一区二区三区在线播放 | 一级黄色免费视频 | aaa国产精品 | 国产精品久久久久久久久久久久午夜片 | 91成人精品一区在线播放 | 日韩精品毛片 | 久久艹国产 | 成人免费高清视频 | 国产激情久久 | 国产视频一区二区在线 | 日韩 国产 欧美 | 久久免费福利视频 | 日韩中文字幕第一页 | 国产视频一区二区在线播放 | 日韩一级黄色片 | 欧美黄色片 | 岛国在线视频 | 欧美日韩亚洲一区二区 | 亚洲激情第一页 | 玖玖在线播放 | 超碰av在线播放 | 亚洲第一毛片 | 久草福利在线观看 | 一级黄色录像视频 | ass亚洲尤物裸体pics |