日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Win32 API串口编程

發布時間:2023/12/10 编程问答 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Win32 API串口编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在工業控制中,工控機(一般都基于Windows平臺)經常需要與智能儀表通過串口進行通信。串口通信方便易行,應用廣泛。
一般情況下,工控機和各智能儀表通過RS485總線進行通信。RS485的通信方式是半雙工的,只能由作為主節點的工控PC機依次輪詢網絡上的各智能控制單元子節點。每次通信都是由PC機通過串口向智能控制單元發布命令,智能控制單元在接收到正確的命令后作出應答。
  在Win32下,可以使用兩種編程方式實現串口通信,其一是使用ActiveX控件,這種方法程序簡單,但欠靈活。其二是調用Windows的API函數,這種方法可以清楚地掌握串口通信的機制,并且自由靈活。本文我們只介紹API串口通信部分。
  串口的操作可以有兩種操作方式:同步操作方式和重疊操作方式(又稱為異步操作方式)。同步操作時,API函數會阻塞直到操作完成以后才能返回(在多線程方式中,雖然不會阻塞主線程,但是仍然會阻塞監聽線程);而重疊操作方式,API函數會立即返回,操作在后臺進行,避免線程的阻塞。

無論那種操作方式,一般都通過四個步驟來完成:
(1) 打開串口
(2) 配置串口
(3) 讀寫串口
(4) 關閉串口

(1) 打開串口

  Win32系統把文件的概念進行了擴展。無論是文件、通信設備、命名管道、郵件槽、磁盤、還是控制臺,都是用API函數CreateFile來打開或創建的。該函數的原型為:

HANDLE CreateFile( LPCTSTR lpFileName,

????????????????? DWORD dwDesiredAccess,

????????????????? DWORD dwShareMode,

????????????????? LPSECURITY_ATTRIBUTES lpSecurityAttributes,

????????????????? DWORD dwCreationDistribution,

DWORD dwFlagsAndAttributes,

HANDLE hTemplateFile);

lpFileName:將要打開的串口邏輯名,如“COM1”;

dwDesiredAccess:指定串口訪問的類型,可以是讀取、寫入或二者并列;

dwShareMode:指定共享屬性,由于串口不能共享,該參數必須置為0;

lpSecurityAttributes:引用安全性屬性結構,缺省值為NULL;

dwCreationDistribution:創建標志,對串口操作該參數必須置為OPEN_EXISTING;

dwFlagsAndAttributes:屬性描述,用于指定該串口是否進行異步操作,該值為FILE_FLAG_OVERLAPPED,表示使用異步的I/O;該值為0,表示同步I/O操作;

hTemplateFile:對串口而言該參數必須置為NULL;

?

同步I/O方式打開串口的示例代碼:

?????? HANDLE hCom; //全局變量,串口句柄

?????? hCom=CreateFile("COM1",//COM1口

????????????? GENERIC_READ|GENERIC_WRITE, //允許讀和寫

????????????? 0, //獨占方式

????????????? NULL,

????????????? OPEN_EXISTING, //打開而不是創建

????????????? 0, //同步方式

????????????? NULL);

?????? if(hCom==(HANDLE)-1)

?????? {

????????????? AfxMessageBox("打開COM失敗!");

????????????? return FALSE;

?????? }

?????? return TRUE;

?

重疊I/O打開串口的示例代碼:

?????? HANDLE hCom; //全局變量,串口句柄

?????? hCom =CreateFile("COM1", //COM1口

???????????? GENERIC_READ|GENERIC_WRITE, //允許讀和寫

???????????? 0, //獨占方式

???????????? NULL,

???????????? OPEN_EXISTING, //打開而不是創建

???????????? FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重疊方式

???????????? NULL);

?????? if(hCom ==INVALID_HANDLE_VALUE)

?????? {

????????????? AfxMessageBox("打開COM失敗!");

????????????? return FALSE;

?????? }

?????? ?? return TRUE;

?

(2)、配置串口

  在打開通訊設備句柄后,常常需要對串口進行一些初始化配置工作。這需要通過一個DCB結構來進行。DCB結構包含了諸如波特率、數據位數、奇偶校驗和停止位數等信息。在查詢或配置串口的屬性時,都要用DCB結構來作為緩沖區。
  一般用CreateFile打開串口后,可以調用GetCommState函數來獲取串口的初始配置。要修改串口的配置,應該先修改DCB結構,然后再調用SetCommState函數設置串口。
  DCB結構包含了串口的各項參數設置,下面僅介紹幾個該結構常用的變量:

?

typedef struct _DCB

{

DWORD BaudRate;

//波特率,指定通信設備的傳輸速率。這個成員可以是實際波特率值或者下面的常量值之一:

CBR_110,CBR_300,CBR_600,CBR_1200,CBR_2400,CBR_4800,CBR_9600,CBR_19200, CBR_38400, CBR_56000, CBR_57600, CBR_115200, CBR_128000, CBR_256000, CBR_14400

?

DWORD fParity; // 指定奇偶校驗使能。若此成員為1,允許奇偶校驗檢查

BYTE ByteSize; // 通信字節位數,4—8

BYTE Parity; //指定奇偶校驗方法。此成員可以有下列值:

EVENPARITY 偶校驗???? NOPARITY 無校驗

MARKPARITY 標記校驗?? ODDPARITY 奇校驗

BYTE StopBits; //指定停止位的位數。此成員可以有下列值:

ONESTOPBIT 1位停止位?? TWOSTOPBITS 2位停止位

ONE5STOPBITS?? 1.5位停止位

?? ………

} DCB;

?

winbase.h文件中定義了以上用到的常量。如下:

#define NOPARITY??????????? 0

#define ODDPARITY?????????? 1

#define EVENPARITY????????? 2

#define ONESTOPBIT????????? 0

#define ONE5STOPBITS??????? 1

#define TWOSTOPBITS???????? 2

#define CBR_110???????????? 110

#define CBR_300???????????? 300

#define CBR_600???????????? 600

#define CBR_1200??????????? 1200

#define CBR_2400??????????? 2400

#define CBR_4800??????????? 4800

#define CBR_9600??????????? 9600

#define CBR_14400?????????? 14400

#define CBR_19200?????????? 19200

#define CBR_38400?????????? 38400

#define CBR_56000?????????? 56000

#define CBR_57600????????? 57600

#define CBR_115200????????? 115200

#define CBR_128000????????? 128000

#define CBR_256000????????? 256000

?

GetCommState函數可以獲得COM口的設備控制塊,從而獲得相關參數:

?

BOOL GetCommState(

?? HANDLE hFile, //標識通訊端口的句柄

?? LPDCB lpDCB //指向一個設備控制塊(DCB結構)的指針

);

?

SetCommState函數設置COM口的設備控制塊:

?

BOOL SetCommState(

?? HANDLE hFile,

?? LPDCB lpDCB

);

  除了在BCD中的設置外,程序一般還需要設置I/O緩沖區的大小和超時。Windows用I/O緩沖區來暫存串口輸入和輸出的數據。如果通信的速率較高,則應該設置較大的緩沖區。調用SetupComm函數可以設置串行口的輸入和輸出緩沖區的大小。

?

BOOL SetupComm(

??? HANDLE hFile,????? // 通信設備的句柄

??? DWORD dwInQueue,??? // 輸入緩沖區的大小(字節數)

??? DWORD dwOutQueue // 輸出緩沖區的大小(字節數)

?? );

?

在用ReadFile和WriteFile讀寫串行口時,需要考慮超時問題。超時的作用是在指定的時間內沒有讀入或發送指定數量的字符,ReadFile或WriteFile的操作仍然會結束。

要查詢當前的超時設置應調用GetCommTimeouts函數,該函數會填充一個COMMTIMEOUTS結構。調用SetCommTimeouts可以用某一個COMMTIMEOUTS結構的內容來設置超時。
讀寫串口的超時有兩種:間隔超時和總超時。間隔超時是指在接收時兩個字符之間的最大時延。總超時是指讀寫操作總共花費的最大時間。寫操作只支持總超時,而讀操作兩種超時均支持。用COMMTIMEOUTS結構可以規定讀寫操作的超時。
COMMTIMEOUTS結構的定義為:

typedef struct _COMMTIMEOUTS {
??? DWORD ReadIntervalTimeout; //讀間隔超時
??? DWORD ReadTotalTimeoutMultiplier; //讀時間系數
??? DWORD ReadTotalTimeoutConstant; //讀時間常量
??? DWORD WriteTotalTimeoutMultiplier; // 寫時間系數
??? DWORD WriteTotalTimeoutConstant; //寫時間常量
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;

COMMTIMEOUTS結構的成員都以毫秒為單位。總超時的計算公式是:
??

總超時=時間系數×要求讀/寫的字符數+時間常量


例如,要讀入10個字符,那么讀操作的總超時的計算公式為:
讀總超時=ReadTotalTimeoutMultiplier×10+ReadTotalTimeoutConstant
可以看出:間隔超時和總超時的設置是不相關的,這可以方便通信程序靈活地設置各種超時。

如果所有寫超時參數均為0,那么就不使用寫超時。如果ReadIntervalTimeout為0,那么就不使用讀間隔超時。如果ReadTotalTimeoutMultiplier 和 ReadTotalTimeoutConstant 都為0,則不使用讀總超時。如果讀間隔超時被設置成MAXDWORD并且讀時間系數和讀時間常量都為0,那么在讀一次輸入緩沖區的內容后讀操作就立即返回,而不管是否讀入了要求的字符。

在用重疊方式讀寫串口時,雖然ReadFile和WriteFile在完成操作以前就可能返回,但超時仍然是起作用的。在這種情況下,超時規定的是操作的完成時間,而不是ReadFile和WriteFile的返回時間。

配置串口的示例代碼:

??????SetupComm(hCom,1024,1024); //輸入緩沖區和輸出緩沖區的大小都是1024
??????

COMMTIMEOUTS TimeOuts;

?????? //設定讀超時
?????? TimeOuts.ReadIntervalTimeout=1000;
?????? TimeOuts.ReadTotalTimeoutMultiplier=500;
?????? TimeOuts.ReadTotalTimeoutConstant=5000;

?????? //設定寫超時
?????? TimeOuts.WriteTotalTimeoutMultiplier=500;
?????? TimeOuts.WriteTotalTimeoutConstant=2000;
??????

SetCommTimeouts(hCom,&TimeOuts); //設置超時

?????? DCB dcb;
?????? GetCommState(hCom,&dcb);
?????? dcb.BaudRate=9600; //波特率為9600
?????? dcb.ByteSize=8; //每個字節有8位
?????? dcb.Parity=NOPARITY; //無奇偶校驗位
?????? dcb.StopBits=TWOSTOPBITS; //兩個停止位
?????? SetCommState(hCom,&dcb);
?????? PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);

在讀寫串口之前,還要用PurgeComm()函數清空緩沖區,該函數原型:

BOOL PurgeComm(
??? HANDLE hFile,????? //串口句柄
??? DWORD dwFlags // 需要完成的操作
?? );????

參數dwFlags指定要完成的操作,可以是下列值的組合:

PURGE_TXABORT???????? 中斷所有寫操作并立即返回,即使寫操作還沒有完成。
PURGE_RXABORT???????? 中斷所有讀操作并立即返回,即使讀操作還沒有完成。
PURGE_TXCLEAR???????? 清除輸出緩沖區
PURGE_RXCLEAR???????? 清除輸入緩沖區

(3)、讀寫串口

我們使用ReadFile和WriteFile讀寫串口,下面是兩個函數的聲明:

BOOL ReadFile(
??? HANDLE hFile,????? //串口的句柄
??? // 讀入的數據存儲的地址,
??? // 即讀入的數據將存儲在以該指針的值為首地址的一片內存區
??? LPVOID lpBuffer,
??? DWORD nNumberOfBytesToRead,????? // 要讀入的數據的字節數
??? // 指向一個DWORD數值,該數值返回讀操作實際讀入的字節數
??? LPDWORD lpNumberOfBytesRead,??
??? // 重疊操作時,該參數指向一個OVERLAPPED結構,同步操作時,該參數為NULL。
??? LPOVERLAPPED lpOverlapped
?? );????

BOOL WriteFile(
??? HANDLE hFile,????? //串口的句柄
??? // 寫入的數據存儲的地址,
??? // 即以該指針的值為首地址的nNumberOfBytesToWrite
??? // 個字節的數據將要寫入串口的發送數據緩沖區。
??? LPCVOID lpBuffer,????
??? DWORD nNumberOfBytesToWrite,???? //要寫入的數據的字節數
??? // 指向指向一個DWORD數值,該數值返回實際寫入的字節數
??? LPDWORD lpNumberOfBytesWritten,
??? // 重疊操作時,該參數指向一個OVERLAPPED結構,
??? // 同步操作時,該參數為NULL。
??? LPOVERLAPPED lpOverlapped
?? );

在用ReadFile和WriteFile讀寫串口時,既可以同步執行,也可以重疊執行。在同步執行時,函數直到操作完成后才返回。這意味著同步執行時線程會被阻塞,從而導致效率下降。在重疊執行時,即使操作還未完成,這兩個函數也會立即返回,費時的I/O操作在后臺進行。
ReadFile和WriteFile函數是同步還是異步由CreateFile函數決定,如果在調用CreateFile創建句柄時指定了FILE_FLAG_OVERLAPPED標志,那么調用ReadFile和WriteFile對該句柄進行的操作就應該是重疊的;如果未指定重疊標志,則讀寫操作應該是同步的。ReadFile和WriteFile函數的同步或者異步應該和CreateFile函數相一致。
ReadFile函數只要在串口輸入緩沖區中讀入指定數量的字符,就算完成操作。而WriteFile函數不但要把指定數量的字符拷入到輸出緩沖區,而且要等這些字符從串行口送出去后才算完成操作。
如果操作成功,這兩個函數都返回TRUE。需要注意的是,當ReadFile和WriteFile返回FALSE時,不一定就是操作失敗,線程應該調用GetLastError函數分析返回的結果。例如,在重疊操作時如果操作還未完成函數就返回,那么函數就返回FALSE,而且GetLastError函數返回ERROR_IO_PENDING。這說明重疊操作還未完成。

同步方式讀寫串口比較簡單,下面先例舉同步方式讀寫串口的代碼:

//同步讀串口
char str[100];
DWORD wCount;//讀取的字節數
BOOL bReadStat;
bReadStat=ReadFile(hCom,str,100,&wCount,NULL);
if(!bReadStat)
{
?????? AfxMessageBox("讀串口失敗!");
?????? return FALSE;
}
return TRUE;

//同步寫串口

?????? char lpOutBuffer[100];
?????? DWORD dwBytesWrite=100;
?????? COMSTAT ComStat;
?????? DWORD dwErrorFlags;
?????? BOOL bWriteStat;
?????? ClearCommError(hCom,&dwErrorFlags,&ComStat);
?????? bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,& dwBytesWrite,NULL);
?????? if(!bWriteStat)
?????? {
???????????? AfxMessageBox("寫串口失敗!");
?????? }
?????? PurgeComm(hCom, PURGE_TXABORT|
????????????? PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);

在重疊操作時,操作還未完成函數就返回。

重疊I/O非常靈活,它也可以實現阻塞(例如我們可以設置一定要讀取到一個數據才能進行到下一步操作)。有兩種方法可以等待操作完成:一種方法是用象WaitForSingleObject這樣的等待函數來等待OVERLAPPED結構的hEvent成員;另一種方法是調用GetOverlappedResult函數等待,后面將演示說明。
下面我們先簡單說一下OVERLAPPED結構和GetOverlappedResult函數:
OVERLAPPED結構
OVERLAPPED結構包含了重疊I/O的一些信息,定義如下:

typedef struct _OVERLAPPED { // o
??? DWORD Internal;
??? DWORD InternalHigh;
??? DWORD Offset;
??? DWORD OffsetHigh;
??? HANDLE hEvent;
} OVERLAPPED;

在使用ReadFile和WriteFile重疊操作時,線程需要創建OVERLAPPED結構以供這兩個函數使用。線程通過OVERLAPPED結構獲得當前的操作狀態,該結構最重要的成員是hEvent。hEvent是讀寫事件。當串口使用異步通訊時,函數返回時操作可能還沒有完成,程序可以通過檢查該事件得知是否讀寫完畢。
當調用ReadFile, WriteFile 函數的時候,該成員會自動被置為無信號狀態;當重疊操作完成后,該成員變量會自動被置為有信號狀態。

GetOverlappedResult函數
BOOL GetOverlappedResult(
??? HANDLE hFile,????? // 串口的句柄
??? // 指向重疊操作開始時指定的OVERLAPPED結構
??? LPOVERLAPPED lpOverlapped,??
??? // 指向一個32位變量,該變量的值返回實際讀寫操作傳輸的字節數。
??? LPDWORD lpNumberOfBytesTransferred,

??? // 該參數用于指定函數是否一直等到重疊操作結束。
??? // 如果該參數為TRUE,函數直到操作結束才返回。
??? // 如果該參數為FALSE,函數直接返回,這時如果操作沒有完成,
??? // 通過調用GetLastError()函數會返回ERROR_IO_INCOMPLETE。

??? BOOL bWait

?? );????

該函數返回重疊操作的結果,用來判斷異步操作是否完成,它是通過判斷OVERLAPPED結構中的hEvent是否被置位來實現的

?

異步讀串口的示例代碼:

char lpInBuffer[1024];
DWORD dwBytesRead=1024;
COMSTAT ComStat;
DWORD dwErrorFlags;
OVERLAPPED m_osRead;
memset(&m_osRead,0,sizeof(OVERLAPPED));
m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
ClearCommError(hCom,&dwErrorFlags,&ComStat);
dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);
if(!dwBytesRead)
? return FALSE;
BOOL bReadStatus;
bReadStatus=ReadFile(hCom,lpInBuffer,
??????????????????????????????????? dwBytesRead,&dwBytesRead,&m_osRead);

if(!bReadStatus) //如果ReadFile函數返回FALSE
{
?????? if(GetLastError()==ERROR_IO_PENDING)
?????? //GetLastError()函數返回ERROR_IO_PENDING,表明串口正在進行讀操作
?????? {
????????????? WaitForSingleObject(m_osRead.hEvent,2000);
??????????? //使用WaitForSingleObject函數等待,直到讀操作完成或延時已達到2秒鐘
??????????? //當串口讀操作進行完畢后,m_osRead的hEvent事件會變為有信號
????????????? PurgeComm(hCom, PURGE_TXABORT|
???????????????????? PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
????????????? return dwBytesRead;
?????? }
?????? return 0;
}
PurgeComm(hCom, PURGE_TXABORT|
??????????????? PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
return dwBytesRead;

對以上代碼再作簡要說明:在使用ReadFile 函數進行讀操作前,應先使用ClearCommError函數清除錯誤。ClearCommError函數的原型如下:

BOOL ClearCommError(
??? HANDLE hFile,????? // 串口句柄
??? LPDWORD lpErrors,???? // 指向接收錯誤碼的變量
??? LPCOMSTAT lpStat????? // 指向通訊狀態緩沖區
?? );?????

該函數獲得通信錯誤并報告串口的當前狀態,同時,該函數清除串口的錯誤標志以便繼續輸入、輸出操作。
參數lpStat指向一個COMSTAT結構,該結構返回串口狀態信息。 COMSTAT結構 COMSTAT結構包含串口的信息,結構定義如下:

typedef struct _COMSTAT { // cst
??? DWORD fCtsHold : 1;?? // Tx waiting for CTS signal
??? DWORD fDsrHold : 1;?? // Tx waiting for DSR signal
??? DWORD fRlsdHold : 1; // Tx waiting for RLSD signal
??? DWORD fXoffHold : 1; // Tx waiting, XOFF char rec''d
??? DWORD fXoffSent : 1; // Tx waiting, XOFF char sent
??? DWORD fEof : 1;?????? // EOF character sent
??? DWORD fTxim : 1;????? // character waiting for Tx
??? DWORD fReserved : 25; // reserved
??? DWORD cbInQue;??????? // bytes in input buffer
??? DWORD cbOutQue;?????? // bytes in output buffer
} COMSTAT, *LPCOMSTAT;

本文只用到了cbInQue成員變量,該成員變量的值代表輸入緩沖區的字節數。

最后用PurgeComm函數清空串口的輸入輸出緩沖區。

這段代碼用WaitForSingleObject函數來等待OVERLAPPED結構的hEvent成員,下面我們再演示一段調用GetOverlappedResult函數等待的異步讀串口示例代碼:

char lpInBuffer[1024];
DWORD dwBytesRead=1024;
?????? BOOL bReadStatus;
?????? DWORD dwErrorFlags;
?????? COMSTAT ComStat;
OVERLAPPED m_osRead;
?????? ClearCommError(hCom,&dwErrorFlags,&ComStat);
?????? if(!ComStat.cbInQue)
????????????? return 0;
?????? dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);
?????? bReadStatus=ReadFile(hCom, lpInBuffer,dwBytesRead,
????????????? &dwBytesRead,&m_osRead);
?????? if(!bReadStatus) //如果ReadFile函數返回FALSE
?????? {
????????????? if(GetLastError()==ERROR_IO_PENDING)
????????????? {
???????????????????? GetOverlappedResult(hCom,
??????????????????????????? &m_osRead,&dwBytesRead,TRUE);
?????????? // GetOverlappedResult函數的最后一個參數設為TRUE,
?????????? //函數會一直等待,直到讀操作完成或由于錯誤而返回。
???????????????????? return dwBytesRead;
????????????? }
????????????? return 0;
?????? }
?????? return dwBytesRead;

異步寫串口的示例代碼:

char buffer[1024];
DWORD dwBytesWritten=1024;
?????? DWORD dwErrorFlags;
?????? COMSTAT ComStat;
OVERLAPPED m_osWrite;
?????? BOOL bWriteStat;
?????? bWriteStat=WriteFile(hCom,buffer,dwBytesWritten,
????????????? &dwBytesWritten,&m_OsWrite);
?????? if(!bWriteStat)
?????? {
????????????? if(GetLastError()==ERROR_IO_PENDING)
????????????? {
???????????????????? WaitForSingleObject(m_osWrite.hEvent,1000);
???????????????????? return dwBytesWritten;
????????????? }
????????????? return 0;
?????? }
?????? return dwBytesWritten;

(4)、關閉串口

利用API函數關閉串口非常簡單,只需使用CreateFile函數返回的句柄作為參數調用CloseHandle即可:

BOOL CloseHandle(
??? HANDLE hObject; //handle to object to close
);

串口編程的一個實例

為了讓您更好地理解串口編程,下面我們分別編寫兩個例程(見附帶的源碼部分),這兩個例程都實現了工控機與百特顯示儀表通過RS485接口進行的串口通信。其中第一個例程采用同步串口操作,第二個例程采用異步串口操作。
我們只介紹軟件部分,RS485接口接線方法不作介紹,感興趣的讀者可以查閱相關資料。

例程1

打開VC++6.0,新建基于對話框的工程RS485Comm,在主對話框窗口IDD_RS485COMM_DIALOG上添加兩個按鈕,ID分別為IDC_SEND和IDC_RECEIVE,標題分別為“發送”和“接收”;添加一個靜態文本框IDC_DISP,用于顯示串口接收到的內容。

在RS485CommDlg.cpp文件中添加全局變量:

HANDLE hCom; //全局變量,串口句柄

在RS485CommDlg.cpp文件中的OnInitDialog()函數添加如下代碼:

?????? // TODO: Add extra initialization here
?????? hCom=CreateFile("COM1",//COM1口
????????????? GENERIC_READ|GENERIC_WRITE, //允許讀和寫
????????????? 0, //獨占方式
????????????? NULL,
????????????? OPEN_EXISTING, //打開而不是創建
????????????? 0, //同步方式
????????????? NULL);
?????? if(hCom==(HANDLE)-1)
?????? {
????????????? AfxMessageBox("打開COM失敗!");
????????????? return FALSE;
?????? }
?????? SetupComm(hCom,100,100); //輸入緩沖區和輸出緩沖區的大小都是100
?????? COMMTIMEOUTS TimeOuts;

?????? //設定讀超時
?????? TimeOuts.ReadIntervalTimeout=MAXDWORD;
?????? TimeOuts.ReadTotalTimeoutMultiplier=0;
?????? TimeOuts.ReadTotalTimeoutConstant=0;

?????? //在讀一次輸入緩沖區的內容后讀操作就立即返回,
?????? //而不管是否讀入了要求的字符。

?????? //設定寫超時
?????? TimeOuts.WriteTotalTimeoutMultiplier=100;
?????? TimeOuts.WriteTotalTimeoutConstant=500;
?????? SetCommTimeouts(hCom,&TimeOuts); //設置超時

?????? DCB dcb;
?????? GetCommState(hCom,&dcb);
?????? dcb.BaudRate=9600; //波特率為9600
?????? dcb.ByteSize=8; //每個字節有8位
?????? dcb.Parity=NOPARITY; //無奇偶校驗位
?????? dcb.StopBits=TWOSTOPBITS; //兩個停止位
?????? SetCommState(hCom,&dcb);
?????? PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);

分別雙擊IDC_SEND按鈕和IDC_RECEIVE按鈕,添加兩個按鈕的響應函數:

?

void CRS485CommDlg::OnSend()
{
?????? // TODO: Add your control notification handler code here
?????? // 在此需要簡單介紹百特公司XMA5000的通訊協議:
?????? //該儀表RS485通訊采用主機廣播方式通訊。
?????? //串行半雙工,幀11位,1個起始位(0),8個數據位,2個停止位(1)
?????? //如:讀儀表顯示的瞬時值,主機發送:DC1 AAA BB ETX
?????? //其中:DC1是標準ASCII碼的一個控制符號,碼值為11H(十進制的17)
?????? //在XMA5000的通訊協議中,DC1表示讀瞬時值
?????? //AAA是從機地址碼,也就是XMA5000顯示儀表的通訊地址
?????? //BB為通道號,讀瞬時值時該值為01
?????? //ETX也是標準ASCII碼的一個控制符號,碼值為03H
?????? //在XMA5000的通訊協議中,ETX表示主機結束符
?????? char lpOutBuffer[7];
?????? memset(lpOutBuffer,''\0'',7); //前7個字節先清零
?????? lpOutBuffer[0]=''\x11''; //發送緩沖區的第1個字節為DC1
?????? lpOutBuffer[1]=''0''; //第2個字節為字符0(30H)
?????? lpOutBuffer[2]=''0''; //第3個字節為字符0(30H)
?????? lpOutBuffer[3]=''1''; // 第4個字節為字符1(31H)
?????? lpOutBuffer[4]=''0''; //第5個字節為字符0(30H)
?????? lpOutBuffer[5]=''1''; //第6個字節為字符1(31H)
?????? lpOutBuffer[6]=''\x03''; //第7個字節為字符ETX
?????? //從該段代碼可以看出,儀表的通訊地址為001????
?????? DWORD dwBytesWrite=7;
?????? COMSTAT ComStat;
?????? DWORD dwErrorFlags;
?????? BOOL bWriteStat;
?????? ClearCommError(hCom,&dwErrorFlags,&ComStat);
?????? bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,& dwBytesWrite,NULL);
?????? if(!bWriteStat)
?????? {
????????????? AfxMessageBox("寫串口失敗!");
?????? }
}

void CRS485CommDlg::OnReceive()
{
?????? // TODO: Add your control notification handler code here
?????? char str[100];
?????? memset(str,''\0'',100);
?????? DWORD wCount=100;//讀取的字節數
?????? BOOL bReadStat;
?????? bReadStat=ReadFile(hCom,str,wCount,&wCount,NULL);
?????? if(!bReadStat)
????????????? AfxMessageBox("讀串口失敗!");
?????? PurgeComm(hCom, PURGE_TXABORT|
????????????? PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
?????? m_disp=str;
?????? UpdateData(FALSE);
?????
}

您可以觀察返回的字符串,其中有和儀表顯示值相同的部分,您可以進行相應的字符串操作取出儀表的顯示值。
打開ClassWizard,為靜態文本框IDC_DISP添加CString類型變量m_disp,同時添加WM_CLOSE的相應函數:
void CRS485CommDlg::OnClose()
{
?????? // TODO: Add your message handler code here and/or call default
??? CloseHandle(hCom);????? //程序退出時關閉串口
?????? CDialog::OnClose();
}

程序的相應部分已經在代碼內部作了詳細介紹。連接好硬件部分,編譯運行程序,細心體會串口同步操作部分。

例程2

打開VC++6.0,新建基于對話框的工程RS485Comm,在主對話框窗口IDD_RS485COMM_DIALOG上添加兩個按鈕,ID分別為IDC_SEND和IDC_RECEIVE,標題分別為“發送”和“接收”;添加一個靜態文本框IDC_DISP,用于顯示串口接收到的內容。在RS485CommDlg.cpp文件中添加全局變量:

?????? HANDLE hCom; //全局變量,

串口句柄在RS485CommDlg.cpp文件中的OnInitDialog()函數添加如下代碼:

?????? hCom=CreateFile("COM1",//COM1口
????????????? GENERIC_READ|GENERIC_WRITE, //允許讀和寫
????????????? 0, //獨占方式
????????????? NULL,
????????????? OPEN_EXISTING, //打開而不是創建
????????????? FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重疊方式
????????????? NULL);

?????? if(hCom==(HANDLE)-1)
?????? {
????????????? AfxMessageBox("打開COM失敗!");
????????????? return FALSE;
?????? }

?????? SetupComm(hCom,100,100); //輸入緩沖區和輸出緩沖區的大小都是100
?????? COMMTIMEOUTS TimeOuts;

?????? //設定讀超時
?????? TimeOuts.ReadIntervalTimeout=MAXDWORD;
?????? TimeOuts.ReadTotalTimeoutMultiplier=0;
?????? TimeOuts.ReadTotalTimeoutConstant=0;
?????//在讀一次輸入緩沖區的內容后讀操作就立即返回,//而不管是否讀入了要求的字符。
?????? //設定寫超時
?????? TimeOuts.WriteTotalTimeoutMultiplier=100;
?????? TimeOuts.WriteTotalTimeoutConstant=500;
?????? SetCommTimeouts(hCom,&TimeOuts); //設置超時

?????? DCB dcb;
?????? GetCommState(hCom,&dcb);
?????? dcb.BaudRate=9600; //波特率為9600
?????? dcb.ByteSize=8; //每個字節有8位
?????? dcb.Parity=NOPARITY; //無奇偶校驗位
?????? dcb.StopBits=TWOSTOPBITS; //兩個停止位
?????? SetCommState(hCom,&dcb);
?????? PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);

分別雙擊IDC_SEND按鈕和IDC_RECEIVE按鈕,添加兩個按鈕的響應函數:

void CRS485CommDlg::OnSend()
{
?????? // TODO: Add your control notification handler code here
?????? OVERLAPPED m_osWrite;
?????? memset(&m_osWrite,0,sizeof(OVERLAPPED));
?????? m_osWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
?????? char lpOutBuffer[7];
?????? memset(lpOutBuffer,''\0'',7);
?????? lpOutBuffer[0]=''\x11'';
?????? lpOutBuffer[1]=''0'';
?????? lpOutBuffer[2]=''0'';
?????? lpOutBuffer[3]=''1'';
?????? lpOutBuffer[4]=''0'';
?????? lpOutBuffer[5]=''1'';
?????? lpOutBuffer[6]=''\x03'';
?????? DWORD dwBytesWrite=7;
?????? COMSTAT ComStat;
?????? DWORD dwErrorFlags;
?????? BOOL bWriteStat;
?????? ClearCommError(hCom,&dwErrorFlags,&ComStat);
?????? bWriteStat=WriteFile(hCom,lpOutBuffer,
????????????? dwBytesWrite,& dwBytesWrite,&m_osWrite);
?????? if(!bWriteStat)
?????? {
????????????? if(GetLastError()==ERROR_IO_PENDING)
????????????? {
???????????????????? WaitForSingleObject(m_osWrite.hEvent,1000);
????????????? }
?????? }
}

void CRS485CommDlg::OnReceive()
{
?????? // TODO: Add your control notification handler code here
?????? OVERLAPPED m_osRead;
?????? memset(&m_osRead,0,sizeof(OVERLAPPED));
?????? m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
?????? COMSTAT ComStat;
?????? DWORD dwErrorFlags;
?????? char str[100];
?????? memset(str,''\0'',100);
?????? DWORD dwBytesRead=100;//讀取的字節數
?????? BOOL bReadStat;
?????? ClearCommError(hCom,&dwErrorFlags,&ComStat);
?????? dwBytesRead=min(dwBytesRead, (DWORD)ComStat.cbInQue);
?????? bReadStat=ReadFile(hCom,str,
????????????? dwBytesRead,&dwBytesRead,&m_osRead);
?????? if(!bReadStat)
?????? {
????????????? if(GetLastError()==ERROR_IO_PENDING)
?????????? //GetLastError()函數返回ERROR_IO_PENDING,表明串口正在進行讀操作
????????????? {
???????????????????? WaitForSingleObject(m_osRead.hEvent,2000);
??????????? //使用WaitForSingleObject函數等待,直到讀操作完成或延時已達到2秒鐘
????????????????? //當串口讀操作進行完畢后,m_osRead的hEvent事件會變為有信號
????????????? }
?????? }
?????? PurgeComm(hCom, PURGE_TXABORT|
????????????? PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
?????? m_disp=str;
?????? UpdateData(FALSE);
}

打開ClassWizard,為靜態文本框IDC_DISP添加CString類型變量m_disp,同時添加WM_CLOSE的相應函數:

void CRS485CommDlg::OnClose()
{
????? // TODO: Add your message handler code here and/or call default
??? CloseHandle(hCom);????? //程序退出時關閉串口
?????? CDialog::OnClose();
}
您可以仔細對照這兩個例程,細心體會串口同步操作和異步操作的區別。 好了,就到這吧,祝您好運。

?

?

?

串口:枚舉串口四法

串口作為最基本的電腦通信?I/O?接口,其使用雖然在?PC?上越來越少,但是在工業儀器領域仍然用的相當普遍,由于筆者工作中需要用到串口,而且發現枚舉串口至今仍未搞得很清楚,為此自己先整理下,希望大俠和同行們對我不懂和錯誤的地方指點一下。

?

1?、查詢注冊表

查詢注冊表的方法是網上見到的比較常見的方法,該方法就是使用編程方法讀取注冊表內信息,相當于用戶通過在運行框內輸入?”regedit”(或?regedit32?)直接打開注冊表,查看“?HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM?”項來獲取串口信息。以下是源代碼:

CString???strSerialList[256];??//?臨時定義?256?個字符串組,因為系統最多也就?256?個

HKEY hKey;

LPCTSTR data_Set="HARDWARE\\DEVICEMAP\\SERIALCOMM\\";

long ret0 = (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, data_Set, 0, KEY_READ, &hKey));

if(ret0 != ERROR_SUCCESS)

{

return -1;

}

int i = 0;

CHAR Name[25];

UCHAR szPortName[25];

LONG Status;

DWORD dwIndex = 0;

DWORD dwName;

DWORD dwSizeofPortName;

DWORD Type;

dwName = sizeof(Name);

dwSizeofPortName = sizeof(szPortName);

do

{

Status = RegEnumValue(hKey, dwIndex++, Name, &dwName, NULL, &Type,

??????szPortName, &dwSizeofPortName);

if((Status == ERROR_SUCCESS)||(Status == ERROR_MORE_DATA))

{

strSerialList[i] = CString(szPortName);???????//?串口字符串保存

i++;//?串口計數

???}

} while((Status == ERROR_SUCCESS)||(Status == ERROR_MORE_DATA));

RegCloseKey(hKey);

以上方法同樣也可以實現對并口的查詢,只要將?"HARDWARE \\ DEVICEMAP\\ SERIALCOMM\\"?用?"HARDWARE\\DEVICEMAP\\PARALLEL PORTS\\"?代替就行了。

比較:該方法時間最省,筆者在自己電腦上試過,在?1ms?(少于?1ms?的我也不知道怎么編程計時)內即可完成;同時也可解決?usb?轉串口設備的問題,比較實用,唯一缺點是,如果用戶在裝某些軟硬件時在注冊表中注冊了虛擬串口之類的,用此法枚舉得到的該類串口實際上是不能當串口用的。

?

2?、使用?EnumPort?方法

該方法調用?EnumPort?()?API?函數,該函數本身就是枚舉電腦端口用的,它枚舉的并非只有串口,所以必須對其所得串口進行分析選擇,以下是源代碼:

???????int m_nSerialPortNum(0);//?串口計數

???????CString??????????strSerialList[256];??//?臨時定義?256?個字符串組

???????LPBYTE pBite??= NULL;

???????DWORD pcbNeeded = 0;??// bytes received or required

???????DWORD pcReturned = 0;??// number of ports received

???????m_nSerialPortNum = 0;

???????//?獲取端口信息,能得到端口信息的大小?pcbNeeded

???????EnumPorts(NULL, 2, pBite, 0, &pcbNeeded, &pcReturned);

???????pBite = new BYTE[pcbNeeded];

???????//?枚舉端口,能得到端口的具體信息?pBite?以及端口的的個數?pcReturned

???????EnumPorts(NULL, 2, pBite, pcbNeeded, &pcbNeeded, &pcReturned);

???????PORT_INFO_2 *pPort;

???????pPort = (PORT_INFO_2*)pBite;

???????for ( i = 0; i < pcReturned; i++)

???????{

??????????????CString str = pPort[i].pPortName;

??????????????//?串口信息的具體確定

??????????????if (str.Left(3) == "COM")

??????????????{??????????????????

?????????????????????strSerialList[m_nSerialPortNum] = str.Left(strlen(str) - 1);

?????????????????????//CString temp = str.Right(strlen(str) - 3);//?下面兩行注釋獲取串口序號用

?????????????????????//m_nSerialPortNo[m_nSerialPortNum] = atoi(temp.Left(strlen(temp) - 1));

?????????????????????m_nSerialPortNum++;????????????????

??????????????}

???????}

以上方法除了串口,還可以枚舉所有的并口和打印機等接口,而且能找到虛擬串口(這些串口有些未使用時,在注冊表和硬件設備管理器中是不能取得的)。但是該方法稍微耗時些,筆者在自己電腦上試過,大概需要幾十?ms?,主要問題是該方法有些?usb?串口并不能查到,所以該方法并不可靠。

?

3?、依次打開串口的方法

該方法就是中規中矩的依次打開串口,看打開是否成功來判斷串口的有無,該方法源代碼如下:

???????int m_nSerialPortNum(0);//?串口數

???????CString??????????strSerialList[256];??//?臨時定義?30?個字符串組

???????int nCom = 0;

???????int count = 0;

???????HANDLE hCom;

???????do {

??????????????nCom++;

??????????????strCom.Format("COM%d", nCom);

??????????????hCom = CreateFile(strCom, 0, 0, 0,

?????????????????????OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

??????????????if(INVALID_HANDLE_VALUE == hCom )

?????????????????????break;

??????????????strSerialList[m_nSerialPortNum] = strCom;

??????????????m_nSerialPortNum++;?????????

??????????????CloseHandle(hCom);

???????} while(1);

以上方法枚舉的都是當前可用的串口,如果有一個串口當前被占用則其后的串口也將無法枚舉得到,當然以上方法也可以改成調用?for?循環讓其枚舉打開?256?個串口的方法以避免上述情況,不過該方法比前兩種更耗時(一般查找一個串口就要?15ms?左右),不過可以枚舉得到所有當前可打開的串口,當然不能枚舉得到一些虛擬串口。

?

4?、使用?SetupAPI?函數集的方法

此種方法是我所見過最簡單的方法,之所以簡單是因為已經有人將復雜的代碼封裝起來了,我只需像傻子一樣調用就可以完成工作了,下面給出本人調用該方法的例子代碼:

???????int m_nSerialPortNum(0);//?串口計數

???????CString??????????strSerialList[256];??//?臨時定義?256?個字符串組

???????CArray<SSerInfo,SSerInfo&> asi;

???????EnumSerialPorts(asi,TRUE);//?參數為?TRUE?時枚舉當前可以打開的串口,?
//?否則枚舉所有串口

???????m_nSerialPortNum = asi.GetSize();

???????for (int i=0; i<asi.GetSize(); i++)

???????{

??????????????CString str = asi[i].strFrien dlyName;

???????}

補充說明一下,使用該方法只要在你的程序中,添加“?EnumSerial.cpp?”和“?EnumSerial.h?”兩個文件,并且將?Setupapi.lib?包含進你的工程文件中就行了,該方法時間上來說可能和第三種方法差不多,但該方法獲取的串口完完全全就是硬件設備管理器中的串口。

總結

以上是生活随笔為你收集整理的Win32 API串口编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

天天干天天碰 | 天天射天天干天天插 | 伊人狠狠操 | 91网免费看 | 菠萝菠萝蜜在线播放 | 久久久久电影网站 | 日韩精品在线观看视频 | 色噜噜狠狠狠狠色综合久不 | 久草在线观看视频免费 | 久久久在线免费观看 | 狠狠ri| 麻豆网站免费观看 | 欧美性色黄大片在线观看 | 国产片免费在线观看视频 | 四虎在线免费观看 | 久久视频免费 | 天天操天天射天天操 | 精品亚洲午夜久久久久91 | 亚洲伊人婷婷 | 久久九九免费 | 成人国产亚洲 | 开心丁香婷婷深爱五月 | 久久第四色 | 在线观看亚洲成人 | 悠悠av资源片 | 成年人视频在线免费 | 亚洲免费激情 | 亚洲日本国产精品 | 欧美精品久久人人躁人人爽 | 在线观看成人 | 黄色免费网站 | 97视频在线观看网址 | 欧美久久久久久久 | 婷婷福利影院 | 久草a在线 | 国产福利在线免费观看 | 中文字幕在线免费播放 | 久久天天躁夜夜躁狠狠85麻豆 | 国产xx视频| 日韩丝袜视频 | 欧美日韩视频在线 | 国产成人精品免高潮在线观看 | 精品久久91 | 黄网站免费久久 | 国产一区二区高清不卡 | 九九视频精品在线 | 久久久久久久久毛片精品 | 超碰电影在线观看 | 天堂激情网 | 国产精品欧美一区二区三区不卡 | 亚洲最快最全在线视频 | 中文字幕区 | 国产精品无| 黄色影院在线免费观看 | 中文字幕在线观 | 一本一本久久a久久精品综合妖精 | 蜜臀av性久久久久蜜臀av | 三级av中文字幕 | 欧美一级久久 | 亚洲蜜桃在线 | 美女黄频视频大全 | 精品综合久久 | 久久免费黄色大片 | 国产一区麻豆 | 久久久久久高潮国产精品视 | 亚洲精品中文字幕视频 | 亚洲第一区精品 | 成人av影视观看 | 青青河边草观看完整版高清 | 日韩性色 | 成人亚洲精品久久久久 | 人人超碰免费 | 91女神的呻吟细腰翘臀美女 | www视频在线播放 | 国产字幕在线播放 | 国产精品网红福利 | 日韩美在线 | 久草在线这里只有精品 | 日韩在线视频观看免费 | 四虎在线视频免费观看 | 国产精品婷婷 | 亚洲欧美精品一区 | 激情视频免费观看 | 成人久久国产 | 国产成人精品综合久久久 | 日韩在线观看你懂的 | 久久国产色| 一二区av| 欧美成人一区二区 | 国产第一二区 | 一区二区三区免费网站 | 亚洲h在线播放在线观看h | 色偷偷男人的天堂av | 久久呀| 国产精品资源在线观看 | 国内外成人在线视频 | 国产亚洲欧美在线视频 | 在线视频在线观看 | 亚洲香蕉视频 | 成片视频在线观看 | 国产一级特黄电影 | 欧美做受69 | 成全免费观看视频 | 欧美三人交 | 9草在线 | 插婷婷 | 国产亚洲va综合人人澡精品 | 四虎成人精品在永久免费 | 国产在线不卡视频 | www.五月激情.com | 国产视频一区二区在线播放 | 国产中文字幕在线视频 | 黄网站免费大全入口 | 在线观看你懂的网站 | 毛片网在线观看 | 国产福利不卡视频 | 黄色av电影一级片 | 手机在线看a | 亚洲精品乱码久久久久久蜜桃欧美 | 亚洲综合色播 | 91色在线观看 | 激情 亚洲| 久久精品黄 | av高清在线观看 | 亚洲最大av网站 | 中文字幕免费久久 | 一级片视频在线 | 911精品美国片911久久久 | 国产精品久久久久久久久久久不卡 | 嫩草伊人久久精品少妇av | 亚洲第一色 | 色欧美视频 | 国产69精品久久99的直播节目 | 91黄在线看| 日韩国产欧美在线视频 | 中文字幕在线观看播放 | 成人精品在线 | 97色视频在线 | 欧美性久久久久久 | 日韩中字在线观看 | 98超碰在线观看 | 99re中文字幕 | 久久视频在线观看中文字幕 | 国产一区二区日本 | 91av视频在线免费观看 | 国产成人一区二区三区影院在线 | 欧美一区二区精美视频 | 中文字幕在线免费观看 | 激情五月在线观看 | 亚洲高清视频在线观看免费 | 久久av免费电影 | www成人精品 | 久草在线资源观看 | 久久精品99国产精品酒店日本 | 500部大龄熟乱视频使用方法 | 玖玖999| 国产在线不卡视频 | 成人黄色在线播放 | 国产一级久久久 | 免费日韩一区二区 | 91色偷偷| 天天躁天天操 | 狠狠的操你 | x99av成人免费| 国产精品青草综合久久久久99 | 国产精品一区二区久久久久 | 免费在线播放黄色 | 综合在线观看色 | 欧美日韩中文另类 | 欧美另类v | 欧美精品资源 | 久久曰视频 | 日日综合 | 久久久久久久久久久国产精品 | 精品国产乱码一区二区三区在线 | 国产视频在线观看一区二区 | 国产成人不卡 | 成人av网页 | 久草 | 久久婷婷国产 | 中文字幕乱码在线播放 | 国产伦精品一区二区三区在线 | 色婷婷在线视频 | www..com毛片 | 欧洲视频一区 | 国产专区精品视频 | 国产字幕在线观看 | 黄色毛片观看 | 亚洲激情电影在线 | 天堂av在线免费 | 成人91在线观看 | 欧美一级电影在线观看 | 国产成人av电影在线观看 | 国产va饥渴难耐女保洁员在线观看 | 国产精品久久久网站 | 国产美女免费观看 | 日韩av片免费在线观看 | 欧美va天堂va视频va在线 | 激情综合站 | 三上悠亚一区二区在线观看 | 欧美a级免费视频 | 久久国产精品免费看 | 岛国一区在线 | 国内一级片在线观看 | 顶级欧美色妇4khd | 激情欧美丁香 | 夜夜操天天干 | 欧美国产三区 | 欧美一级片免费播放 | 婷婷久久综合九色综合 | av成人在线看 | 日韩视频精品在线 | 日本中文一区二区 | 伊人婷婷久久 | 亚洲成人精品久久 | 欧美国产在线看 | 日韩视频免费观看高清 | 天堂资源在线观看视频 | 久草新在线 | 999久久久| 公与妇乱理三级xxx 在线观看视频在线观看 | 久久99影院| 久久国产香蕉视频 | 天天射天 | 国产区在线看 | 麻豆一区在线观看 | 综合网av| 日韩在线观看精品 | 亚洲午夜av久久乱码 | 久久国产剧场电影 | 日日添夜夜添 | 99久久日韩精品视频免费在线观看 | 欧美日韩一区二区在线观看 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 四虎国产视频 | 天天草综合网 | 久久精品人人做人人综合老师 | 91免费高清 | 亚洲国产精品激情在线观看 | 99热99热| 91大神在线观看视频 | 在线你懂 | 伊人天天色 | 国产成人精品av在线观 | 欧美国产日韩在线视频 | 久久久私人影院 | 亚洲精品在线视频播放 | 97超碰在线免费观看 | 一区二区欧美激情 | 91九色丨porny丨丰满6 | 日韩三级久久 | 日韩av网站在线播放 | 国产精品一区二区久久精品爱微奶 | 日韩理论电影网 | 日韩中文字幕电影 | 精品91在线 | 免费在线一区二区 | 91麻豆免费看 | 亚州欧美视频 | 国产精品黄色影片导航在线观看 | 久久久久久蜜桃一区二区 | 免费能看的黄色片 | 久久人人爽人人爽人人片av免费 | 丁香高清视频在线看看 | 欧美亚洲精品一区 | www.天天干| 黄污污网站 | 一区二区三区日韩视频在线观看 | 成年美女黄网站色大片免费看 | 人人爱爱 | 亚洲第一区在线观看 | 国产黄影院色大全免费 | 日韩女同av| 国产91学生| 色狠狠久久av五月综合 | 在线91观看 | 国内精品久久久 | 午夜成人免费电影 | 欧美激情精品久久久久 | 日批网站免费观看 | 精品爱爱 | 色综合久久久久久久久五月 | 国产精品av免费观看 | 亚洲码国产日韩欧美高潮在线播放 | 久久蜜桃av | 麻豆视频在线观看免费 | 九九视频在线播放 | 九9热这里真品2 | 在线亚洲成人 | 亚洲国产精品影院 | 成人一级黄色片 | 久久免视频 | 在线观看成人毛片 | 中文字幕91在线 | 成人午夜电影在线播放 | 欧美午夜视频在线 | 亚洲午夜久久久影院 | 最近中文字幕久久 | 亚洲全部视频 | 国产成人精品亚洲精品 | 99精品久久久久久久久久综合 | 中文字幕免费在线 | 日本天天色 | 成人超碰97 | 在线观看蜜桃视频 | 日韩黄色在线观看 | 91看片在线看片 | 天天综合导航 | 久久婷婷色综合 | 久久在线视频在线 | 久久亚洲免费视频 | 亚洲欧美国内爽妇网 | 97成人精品视频在线观看 | 四虎影视国产精品免费久久 | 麻豆精品视频 | 天天爱天天草 | 久久免费视频7 | 五月天激情综合网 | 天天视频亚洲 | 色七七亚洲影院 | 99久久www| 成片人卡1卡2卡3手机免费看 | 国产成人久久精品一区二区三区 | 日韩激情视频在线观看 | 91桃色国产在线播放 | 亚洲日本va中文字幕 | 久久久国产一区二区三区 | 亚洲精品视频在线观看免费视频 | 美女久久网站 | 二区三区在线观看 | 91成人精品一区在线播放69 | 亚洲视频精品在线 | 亚洲美女在线一区 | 久久色中文字幕 | 亚洲黄色在线观看 | 狠狠狠狠狠狠狠干 | 国产精品视频永久免费播放 | 日韩精品欧美专区 | 人人涩| 91精品国产乱码 | 手机看片久久 | 天天鲁天天干天天射 | 91精品办公室少妇高潮对白 | 操操操综合 | 97国产情侣爱久久免费观看 | 久久黄色片 | 日韩欧美在线中文字幕 | 色吊丝在线永久观看最新版本 | 免费看av在线 | av黄色免费在线观看 | 精品视频国产一区 | 91天天操| 国产一级免费av | 狠狠搞,com | 人人草在线观看 | 国产区在线视频 | 一区二区三区福利 | 久久成人免费电影 | 亚洲在线色 | 久影院| 国产馆在线播放 | 中文av在线免费观看 | 亚洲视频分类 | 精品视频免费久久久看 | 天天玩天天操天天射 | 免费观看性生交 | 1024久久| 五月婷婷开心 | 精品国产亚洲日本 | 成人黄色资源 | 欧美色久 | 国产又粗又硬又长又爽的视频 | 日本九九视频 | 久久久蜜桃 | 色吊丝在线永久观看最新版本 | 国产一级在线观看 | 毛片美女网站 | 日韩黄视频 | 久久深夜福利免费观看 | 国产精品久久嫩一区二区免费 | 五月天激情综合网 | av在线一 | 国产在线第三页 | 97成人免费| 亚洲撸撸 | 亚洲精品视频一二三 | 视频在线精品 | 欧美亚洲国产一卡 | 亚洲美女免费精品视频在线观看 | 成人免费看视频 | 中文字幕在线观看第二页 | 日韩成人看片 | 亚洲综合一区二区精品导航 | 色综合在 | 日日摸日日添夜夜爽97 | 麻花豆传媒mv在线观看网站 | 91视频一8mav | 日韩高清一二三区 | 97**国产露脸精品国产 | www.777奇米 | 亚洲一级片在线看 | 亚洲va欧美va人人爽春色影视 | 免费在线观看国产黄 | 9999在线| 欧美日韩精品在线观看 | 亚洲精品一区二区在线观看 | 日本中文字幕在线电影 | 在线观看黄色免费视频 | 欧美精品三级在线观看 | 国产成人亚洲在线观看 | 日韩专区中文字幕 | 91久久国产综合精品女同国语 | 五月婷婷操 | 91精品国自产在线 | 丰满少妇在线观看网站 | 99视频这里有精品 | 久久久久久久久影视 | av一本久道久久波多野结衣 | 久操免费视频 | 久久久久网址 | 日韩欧美在线高清 | 国产免费三级在线观看 | 日韩免费一级a毛片在线播放一级 | 99久久婷婷国产综合亚洲 | 国产不卡在线观看 | 国内精品久久久久久久久久 | 日韩a级黄色 | 亚洲欧美视频 | 91大神dom调教在线观看 | 欧美日韩在线视频一区二区 | 91福利小视频 | 亚洲另类在线视频 | 狠狠躁天天躁综合网 | 天天操天天色天天 | 最新国产视频 | 亚洲一区视频免费观看 | 96av在线视频 | 国产精品视频99 | 91看片淫黄大片91 | 日韩一区二区三区观看 | 亚洲国产视频在线 | 日日夜操| 成人av亚洲 | 爱色婷婷 | 在线看av网址| 国产精品永久久久久久久久久 | 综合天堂av久久久久久久 | 亚洲欧美成aⅴ人在线观看 四虎在线观看 | www久久久 | 亚洲国产日韩欧美 | 国产高清不卡一区二区三区 | 99精品热| 一二三区视频在线 | 精品一区二区日韩 | 91黄色免费看| 久久福利影视 | 日韩电影在线观看一区二区 | 国产精品va | 精品国产自在精品国产精野外直播 | www五月天婷婷 | www.亚洲精品 | 国产99久久久精品视频 | 精品久久电影 | 中文在线字幕免费观 | www.狠狠操.com | 中文字幕精品一区 | 久久久久视 | 成人四虎影院 | av高清影院| 亚洲一级二级 | 一区二区久久久久 | 在线观看亚洲精品视频 | 久久99视频精品 | 最新色站 | 九九免费在线看完整版 | 亚洲激情校园春色 | 久久人人爽人人片av | 伊人五月天婷婷 | av成年人电影 | 日韩久久久久久久久久久久 | 国产手机在线 | 久久综合久色欧美综合狠狠 | 日韩精品在线免费观看 | 久久成人免费视频 | 人人干97| 国产1区2区3区精品美女 | 日韩三级视频在线看 | 久久香蕉电影网 | 91福利社在线观看 | 91九色成人蝌蚪首页 | 91精品亚洲影视在线观看 | 国产精品18久久久久久久久久久久 | 国产精品久久久久一区二区三区 | av免费观看网址 | 一区二区三区四区在线 | 色播五月激情综合网 | 久久人人艹 | 日韩中文字幕免费在线播放 | 色综合久久久久综合体 | 婷婷去俺也去六月色 | 成人国产网址 | 网站你懂的 | 国产精品久久久久毛片大屁完整版 | 人人射av| 亚洲一二三区精品 | 久久亚洲二区 | 91在线91拍拍在线91 | 狠狠色丁香久久婷婷综合五月 | 五月天久久婷 | 999超碰| 久久久久久免费 | 国产成a人亚洲精v品在线观看 | 久久久鲁| 69国产成人综合久久精品欧美 | 精品一区二区av | 成人av影视观看 | 在线激情影院一区 | 91在线操 | 狠狠狠色丁香婷婷综合久久88 | 国产午夜精品一区二区三区嫩草 | 国产精品门事件 | 超碰97中文 | 探花系列在线 | 国产成人无码AⅤ片在线观 日韩av不卡在线 | 欧美精品免费一区二区 | 成人黄色毛片 | 黄色片软件网站 | 91探花在线 | 日韩va亚洲va欧美va久久 | 成人免费一区二区三区在线观看 | 天天射天天干 | 日韩视频免费观看高清完整版在线 | av在线com| 国产精品国产亚洲精品看不卡 | 欧美国产精品一区二区 | 久久免费视频8 | 天天色.com| 99看视频在线观看 | 日韩精品91偷拍在线观看 | 亚洲天堂自拍视频 | 国产91精品久久久久久 | 亚洲涩涩涩涩涩涩 | 特级西西444www大胆高清无视频 | 成人黄视频 | 99精品毛片 | 亚洲成人黄色av | 亚洲精品午夜aaa久久久 | 经典三级一区 | 日日草视频 | 五月婷婷,六月丁香 | 日韩美女黄色片 | 玖玖视频 | 色多多在线观看 | .国产精品成人自产拍在线观看6 | 99在线视频观看 | 青青河边草免费观看完整版高清 | 6080yy午夜一二三区久久 | 日本久久精品视频 | 9久久精品 | 国产高清视频在线播放一区 | av丝袜在线 | 五月天色站 | 99久久综合国产精品二区 | 丁香色婷| 中文字幕久久久精品 | 欧美成年人在线视频 | 亚洲不卡在线 | 日韩精品在线免费观看 | 国产综合片 | 五月婷婷电影网 | 在线观看www91 | 欧美韩国日本在线 | 91麻豆免费版 | 日日添夜夜添 | 五月天婷婷综合 | 午夜精品一区二区三区在线观看 | 国产小视频在线看 | 992tv在线观看网站 | 毛片1000部免费看 | 尤物九九久久国产精品的分类 | 91自拍视频在线观看 | 久久视频一区二区 | 日本中文字幕在线观看 | 国产一区二区播放 | 97视频人人澡人人爽 | 欧美激情视频免费看 | av不卡中文 | 亚洲精欧美一区二区精品 | 91视频在线自拍 | 国语自产偷拍精品视频偷 | 中文字幕免费不卡视频 | 麻豆久久一区二区 | 国产淫a | 国产v在线播放 | 国产精品一区二区久久 | 日日爱av | 亚洲国产剧情 | 亚洲综合五月 | av免费观看高清 | av免费看在线 | 国产999久久久 | 成年人在线观看视频免费 | 在线播放日韩 | 一区三区视频在线观看 | www.色就是色 | 在线观看免费观看在线91 | 国产精品久久久久999 | 亚洲欧美日韩国产一区二区 | 国产精品色视频 | 久插视频 | 午夜色影院 | 五月激情五月激情 | 在线看日韩 | 一区二区电影在线观看 | av在线网站大全 | 亚洲综合日韩在线 | 久久毛片视频 | 欧美污网站 | 精品国内自产拍在线观看视频 | 久久日韩精品 | 91天天操| 综合在线色 | 在线观看国产亚洲 | 麻豆手机在线 | 在线免费观看欧美日韩 | 日韩av在线高清 | 国产人成精品一区二区三 | 成人黄色在线视频 | 成人三级网址 | www五月天婷婷 | 国产精品免费久久 | 丰满少妇一级片 | 亚洲男男gaygayxxxgv | 97超碰国产精品女人人人爽 | 黄污视频网站大全 | 亚洲成人二区 | 五月开心婷婷网 | 日韩在线播放视频 | 久久电影国产免费久久电影 | 手机在线黄色网址 | 91正在播放 | 国产人在线成免费视频 | 欧美坐爱视频 | 99九九视频 | 超碰97人人射妻 | 天天综合网天天 | 精品嫩模福利一区二区蜜臀 | 国产视频精选 | 干 操 插| 国产女人40精品一区毛片视频 | 五月婷婷综合激情网 | 国产精品久久久久一区二区三区共 | 黄色av三级在线 | 91成熟丰满女人少妇 | 国产精品嫩草影院9 | 丁香婷婷激情国产高清秒播 | 三级动态视频在线观看 | 91九色在线 | 亚洲一区黄色 | 午夜视频日本 | 欧美日韩一区二区在线观看 | 一区二区三区免费在线观看视频 | 亚洲免费在线观看视频 | 天堂va在线高清一区 | 午夜视频在线瓜伦 | 在线观看国产一区 | 区一区二在线 | 色婷婷久久 | 久久视频这里只有精品 | 国产1区2区3区精品美女 | 免费看搞黄视频网站 | 丰满少妇在线观看 | 四虎视频 | 国产精品 日韩精品 | 99久久精品国 | 日本久久精 | 996久久国产精品线观看 | 日韩视频在线观看视频 | 视频一区在线免费观看 | www.狠狠插.com | 成人免费视频a | 九九色视频 | 亚洲精品视频在线免费 | 午夜精品久久久久久久99无限制 | 国产精品综合久久久久 | 99在线热播精品免费 | 天天操婷婷 | 中文字幕在线观看免费高清电影 | 97国产精品久久 | 色综合 久久精品 | 狠狠狠狠狠狠天天爱 | 中文字幕在线一区观看 | 国产精品不卡在线观看 | 天天艹天天干天天 | 在线观看国产www | 天天鲁天天干天天射 | jizzjizzjizz亚洲 | 欧美在线观看视频一区二区 | 亚洲a成人v | 国产永久免费高清在线观看视频 | 97超碰在线久草超碰在线观看 | h动漫中文字幕 | 又紧又大又爽精品一区二区 | 999成人| 国产中文字幕91 | 国内精品久久久久久久影视简单 | 天天做天天爱天天综合网 | 亚洲免费精品视频 | 最近中文国产在线视频 | 国产 日韩 在线 亚洲 字幕 中文 | 亚洲精品成人 | 日日夜夜狠狠干 | 91av精品 | 欧美一二三视频 | 亚洲精品国产第一综合99久久 | 美女视频黄免费的 | 在线亚洲欧美日韩 | 精品国产一区二区三区免费 | 国产理论在线 | 免费观看丰满少妇做爰 | 91精品免费在线观看 | 97视频在线观看网址 | 在线观看国产 | 美女久久网站 | 亚洲精品视频在线免费播放 | 免费观看一区二区三区视频 | 中文av在线天堂 | 亚洲精品视频二区 | 成人精品国产 | 久久优| 久久免费福利视频 | 成人动态视频 | 久久国产系列 | www.狠狠操 | 干 操 插 | 欧美午夜理伦三级在线观看 | 超碰人人干人人 | 成片视频在线观看 | 91精品国产网站 | 69精品| 免费看三级网站 | 国产日女人| 91夜夜夜| 免费看搞黄视频网站 | 麻豆91在线 | 小草av在线播放 | 91视频免费看 | 国产精品va在线播放 | 国产精品99久久久久久久久久久久 | 色妞色视频一区二区三区四区 | 久草电影在线 | 亚洲国产字幕 | 欧美a级片免费看 | 一区二区三区四区五区在线 | 久久精品99国产精品日本 | 国产视频午夜 | 西西444www大胆高清图片 | 久久精品婷婷 | 看片黄网站 | 国产一区不卡在线 | 亚洲三级在线免费观看 | 九九热免费视频在线观看 | 手机成人在线电影 | 久久亚洲婷婷 | 亚洲精品乱码久久久久久按摩 | 久久免费看毛片 | 天天爽综合网 | 午夜12点 | 一区二区三区精品在线视频 | 中文字幕在线观看2018 | 中文国产在线观看 | 欧美日韩国产亚洲乱码字幕 | 色婷婷综合久久久久中文字幕1 | 香蕉视频在线观看免费 | 日韩av资源站 | 狠狠狠的干 | 国产亚洲一区 | 人人干人人草 | 四虎www.| 大荫蒂欧美视频另类xxxx | 国产亚洲视频在线免费观看 | 在线免费av电影 | 在线观看黄色的网站 | 91av免费在线观看 | 国产老熟 | 色综合天天色综合 | 91在线看黄 | 九九在线免费视频 | 日韩二区精品 | www.夜夜 | 96视频在线 | 精品国产免费av | 天天躁日日躁狠狠躁 | 欧美做受xxx | av3级在线 | 国产成人333kkk | 色综合久久天天 | 国产在线视频在线观看 | 91久久丝袜国产露脸动漫 | 欧美精品久久 | 国内精品久久久久影院优 | 人人讲 | 人人草人| 一区二区三区日韩在线观看 | av在线播放网址 | 国产精品一二三 | 97免费在线视频 | 在线观看精品一区 | 中文av影院| 丁香免费视频 | 色国产精品 | 亚洲国产中文字幕在线观看 | 国产色视频一区二区三区qq号 | 中文字幕色站 | 亚洲国产成人av网 | 久久久久黄 | 最近中文字幕免费 | 亚州国产精品久久久 | 久久经典国产视频 | 亚洲精品国偷拍自产在线观看蜜桃 | 黄色大全免费观看 | 麻花传媒mv免费观看 | 一区二区视频在线观看免费 | 久草在线视频网 | 日日夜夜精品视频 | 97在线视频网站 | 最新一区二区三区 | 久久麻豆精品 | 亚洲精品免费观看视频 | 久久99国产精品免费网站 | 色九九在线 | 91传媒在线 | 人人草在线视频 | av在线最新 | 国产美女视频 | 亚洲精品乱码久久久久久蜜桃91 | 欧美日韩国产在线精品 | 久草视频在线看 | 天天操天天干天天干 | 久久久久久久久久电影 | 天天色天天射综合网 | 欧美精品免费在线观看 | 人人干天天干 | a在线免费 | 色婷婷骚婷婷 | 中文字幕亚洲欧美日韩 | 久久久在线视频 | 69人人| 中文字幕免费成人 | 久久精品视频观看 | 国产成人精品综合久久久 | 综合网婷婷 | 国产在线观看你懂得 | 丁香六月欧美 | 黄色成人在线观看 | 免费观看成人av | 黄色av网站在线免费观看 | 亚洲欧美日韩精品久久久 | 欧美激情xxxx | 91网页版在线观看 | 色婷婷综合成人av | 婷婷六月天天 | 激情网五月婷婷 | 国产成人精品一区二区三区免费 | 日韩欧美在线免费观看 | 蜜臀久久99精品久久久酒店新书 | 精品视频免费观看 | 九九有精品 | 午夜国产一区二区三区四区 | 欧美精品在线观看免费 | 日韩在线观看第一页 | 一区二区三区四区五区六区 | 欧美日韩视频精品 | 免费在线观看日韩视频 | 日本3级在线观看 | 欧美日韩国语 | 国产色女 | 久久精品79国产精品 | 久久艹国产 | 国产成人精品av在线 | av日韩av | 国产美女在线免费观看 | 在线观看成人网 | 91成人免费在线 | 91成人午夜 | 国产夫妻av在线 | 国产亚洲精品美女久久 | 欧美 亚洲 另类 激情 另类 | 黄色福利网站 | 国产精品日韩在线播放 | 天堂成人在线 | 欧美a视频 | 黄色一级网 | 中文国产成人精品久久一 | 欧美a级在线播放 | 国产一卡二卡在线 | 亚洲电影成人 | 欧美激情精品 | 久久天天躁夜夜躁狠狠85麻豆 | 中文区中文字幕免费看 | 操综合 | 激情丁香综合五月 | 欧美性大战久久久久 | 色综合咪咪久久网 | 日韩av进入 | 久草精品视频在线播放 | 中文字幕亚洲综合久久五月天色无吗'' | 夜夜操狠狠操 | 又黄又爽的免费高潮视频 | 日韩一区二区三区免费视频 | 精品久久久久久久久久久久 | 午夜 在线 | 日韩av一区二区在线播放 | 二区三区视频 | 国产明星视频三级a三级点| 成人小电影在线看 | 色综合久久久久网 | 成人小视频免费在线观看 | 国产色在线视频 | 又黄又爽免费视频 | 欧美日韩国产一二 | 日韩精品一区二区免费 | 国产精品video | 亚洲最大激情中文字幕 | 在线观看日本韩国电影 | 中文字幕在线观看免费高清完整版 | 四虎欧美 | 99久久99久久精品国产片 | 婷婷综合电影 | 欧美极品一区二区三区 | 国产一二区视频 | 91热精品 | 91福利在线导航 | 中文字幕在线观看视频网站 | 色开心| 亚洲人人网 | 成人视屏免费看 | 91中文在线视频 | 激情欧美xxxx| 在线观看福利网站 | 一区免费观看 | 国产精品无av码在线观看 | 成人在线一区二区三区 | 青青草国产精品视频 | 在线高清一区 | 欧美日韩裸体免费视频 | 热久久99这里有精品 | 91亚洲精品久久久 | 久草在线精品观看 | 中文字幕免费在线 | 久久婷婷视频 | 五月婷婷影院 | 欧美日韩中文字幕综合视频 | 91中文字幕在线视频 | 午夜久久影院 | 玖玖在线免费视频 | 国产精品永久久久久久久www | 在线播放亚洲激情 | 日韩三级久久 | 69av在线视频 | 国产99久久久国产精品免费二区 | 欧美做受xxx| 亚洲视频2| 中文字幕精品一区二区精品 | 日韩久久精品一区二区 | 欧美日韩性视频 | 日韩中文在线观看 | 一级免费黄色 | 激情开心网站 | 亚州精品天堂中文字幕 | 91手机在线看片 | 韩国av在线播放 | 在线 精品 国产 | 天天色.com| 久草在线欧美 | 探花视频在线观看 | 91视频成人免费 | 国产激情免费 | av一级网站 | 国产精品99久久久精品 | 国产黑丝一区二区 | 国产精品一区二区视频 | 色婷婷影视 | 久久国产精品第一页 | 免费看黄电影 | 国产不卡高清 | 国产成人在线播放 | 五月天天在线 | 亚洲视频www| 天堂av影院 | 国产电影黄色av | 在线看片中文字幕 | 日韩av中文字幕在线 | 国产精品久久久久久久久岛 | 日韩av网站在线播放 | 99久热在线精品视频成人一区 | 曰韩精品 | 国产日韩三级 |