標(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
|