《電子技術應用》
您所在的位置:首頁 > 模擬設計 > 設計應用 > Win32串口編程
Win32串口編程
摘要: Win32下串口通信與16位串口通信有很大的區別。在Win32下,可以使用兩種編程方式實現串口通信,其一是調用的Windows的API函數,其二是使用ActiveX控件。
關鍵詞: 接口IC Win32 串口 通信
Abstract:
Key words :

  Win32串口編程

  Win32下串口通信與16位串口通信有很大的區別。在Win32下,可以使用兩種編程方式實現串口通信,其一是調用的Windows的API函數,其二是使用ActiveX控件。使用API 調用,可以清楚地掌握串口通信的機制,熟悉各種配置和自由靈活采用不同的流控進行串口通信。下面介紹串口操作的基本知識。

  打開串口:使用CreateFile()函數,可以打開串口。有兩種方法可以打開串口,一種是同步方式(NonOverlapped),另外一種異步方式(Overlapped)。使用Overlapped打開時,適當的方法是:

  HANDLE hComm;

  hComm = CreateFile( gszPort,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);

  if (hComm == INVALID_HANDLE_VALUE)

  // error opening port; abort

  配置串口:

  1.DCB配置

  DCB(Device Control Block)結構定義了串口通信設備的控制設置。許多重要設置都是在DCB結構中設置的,有三種方式可以初始化DCB。

 ?。?)通過GetCommState()函數得DCB的初始值,其使用方式為:

  DCB dcb = {0};

  if (!GetCommState(hComm, &dcb))

  // Error getting current DCB settings

  else

  // DCB is ready for use.

 ?。?)用BuildCommDCB()函數初始化DCB結構,該函數填充 DCB的波特率、奇偶校驗類型、數據位、停止位。對于流控成員函數設置了缺省值。其用法是:

  DCB dcb;

  FillMemory(&dcb, sizeof(dcb), 0);

  dcb.DCBlength = sizeof(dcb);

  if (!BuildCommDCB(“9600,n,8,1“, &dcb)) {

  // Couldn‘t build the DCB. Usually a problem

  // with the communications specification string.

  return FALSE;

  }

  else

  // DCB is ready for use.

 ?。?)用SetCommState()函數手動設置DCB初值。用法如下:

  DCB dcb;

  FillMemory(&dcb, sizeof(dcb), 0);

  if (!GetCommState(hComm, &dcb)) // get current DCB

  // Error in GetCommState

  return FALSE;

  // Update DCB rate.

  dcb.BaudRate = CBR_9600 ;

  // Set new state.

  if (!SetCommState(hComm, &dcb))

  // Error in SetCommState.

  Possibly a problem with the communications

  // port handle or a problem with the DCB structure itself.

  手動設置DCB值時,DCB的結構的各成員的含義,可以參看MSDN幫助。

 

  Win32串口編程

  Win32下串口通信與16位串口通信有很大的區別。在Win32下,可以使用兩種編程方式實現串口通信,其一是調用的Windows的API函數,其二是使用ActiveX控件。使用API 調用,可以清楚地掌握串口通信的機制,熟悉各種配置和自由靈活采用不同的流控進行串口通信。下面介紹串口操作的基本知識。

  打開串口:使用CreateFile()函數,可以打開串口。有兩種方法可以打開串口,一種是同步方式(NonOverlapped),另外一種異步方式(Overlapped)。使用Overlapped打開時,適當的方法是:

  HANDLE hComm;

  hComm = CreateFile( gszPort,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);

  if (hComm == INVALID_HANDLE_VALUE)

  // error opening port; abort

  配置串口:

  1.DCB配置

  DCB(Device Control Block)結構定義了串口通信設備的控制設置。許多重要設置都是在DCB結構中設置的,有三種方式可以初始化DCB。

 ?。?)通過GetCommState()函數得DCB的初始值,其使用方式為:

  DCB dcb = {0};

  if (!GetCommState(hComm, &dcb))

  // Error getting current DCB settings

  else

  // DCB is ready for use.

 ?。?)用BuildCommDCB()函數初始化DCB結構,該函數填充 DCB的波特率、奇偶校驗類型、數據位、停止位。對于流控成員函數設置了缺省值。其用法是:

  DCB dcb;

  FillMemory(&dcb, sizeof(dcb), 0);

  dcb.DCBlength = sizeof(dcb);

  if (!BuildCommDCB(“9600,n,8,1“, &dcb)) {

  // Couldn‘t build the DCB. Usually a problem

  // with the communications specification string.

  return FALSE;

  }

  else

  // DCB is ready for use.

 ?。?)用SetCommState()函數手動設置DCB初值。用法如下:

  DCB dcb;

  FillMemory(&dcb, sizeof(dcb), 0);

  if (!GetCommState(hComm, &dcb)) // get current DCB

  // Error in GetCommState

  return FALSE;

  // Update DCB rate.

  dcb.BaudRate = CBR_9600 ;

  // Set new state.

  if (!SetCommState(hComm, &dcb))

  // Error in SetCommState.

  Possibly a problem with the communications

  // port handle or a problem with the DCB structure itself.

  手動設置DCB值時,DCB的結構的各成員的含義,可以參看MSDN幫助。

 

  2.流控設置

  硬件流控:串口通信中的硬件流控有兩種,DTE/DSR方式和RTS/CTS方式,這與DCB結構的初始化有關系,DCB結構中的OutxCtsFlow、 fOutxDsrFlow、fDsrSensitivity、fRtsControl、fDtrControl幾個成員的初始值很關鍵,不同的值代表不同流控,也可以自己設置流控,但建議采用標準流行的流控方式。采用硬件流控時,DTE、DSR、RTS、CTS的邏輯位直接影響到數據的讀寫及收發數據的緩沖區控制。

  軟件流控:串口通信中采用特殊字符XON和XOFF作為控制串口數據的收發。與此相關的DCB成員是:fOut、fInX、XoffChar、XonChar、 XoffLim和XonLim。具體含義參見MSDN幫助。

  串口讀寫操作:串口讀寫有兩種方式:同步方式(NonOverlapped)和異步方式(Overlapped)。同步方式是指必須完成了讀寫操作,函數才返回,這可能造成程序死掉,因為如果在讀寫時發生了錯誤,永遠不返回就會出錯,可能線程將永遠等待在那兒。而異步方式則靈活得多,一旦讀寫不成功,就將讀寫掛起,函數直接返回,可以通過GetLastError函數得知讀寫未成功的原因,所以常常采用異步方式操作。

  讀操作:ReadFile()函數用于完成讀操作。異步方式的讀操作為:

  DWORD dwRead;

  BOOL fWaitingOnRead = FALSE;

  OVERLAPPED osReader = {0};

  // Create the overlapped event. Must be closed before exiting

  // to avoid a handle leak.

  osReader.hEvent = CreateEvent

 ?。∟ULL, TRUE, FALSE, NULL);

  if (osReader.hEvent == NULL)

  // Error creating overlapped event; abort.

  if (!fWaitingOnRead) {

  // Issue read operation.

  if (!ReadFile(hComm, lpBuf, READ_BUF_SIZE,

 ?。wRead, &osReader)) {

  if (GetLastError() != ERROR_IO_PENDING)

  // read not delayed?

  // Error in communications; report it.

  else

  fWaitingOnRead = TRUE;

  }

  else {

  // read completed immediately

  HandleASuccessfulRead(lpBuf, dwRead);

  }

  }

  如果讀操作被掛起,可以調用WaitForSingleObject()函數或WaitForMuntilpleObjects()函數等待讀操作完成或者超時發生,再調用 GetOverlappedResult()得到想要的信息。

  寫操作:與讀操作相似,故不詳述,調用的API函數是: WriteFile函數。

  串口狀態:

 ?。?)通信事件:用SetCommMask()函數設置想要得到的通信事件的掩碼,再調用WaitCommEvent()函數檢測通信事件的發生??稍O置的通信事件標志(即SetCommMask()函數所設置的掩碼)可以有EV_BREAK、EV_CTS、EV_DSR、 EV_ERR、EV_RING、EV_RLSD、EV_RXCHAR、EV_RXFLAG、EV_TXEMPTY。

 

  注意:1對于EV_RING標志的設置,WIN95是不會返回EV_RING事件的,因為WIN95不檢測該事件。2設置EV_RXCHAR,可以檢測到字符到達,但是在綁定此事件和ReadFile()函數一起讀取串口接收數據時,可能會出現錯誤,造成少讀字節數,具體原因查看MSDN幫助。可以采用循環讀的辦法,另外一個比較好的解決辦法是調用ClearCommError()函數,確定在一次讀操作中在緩沖區中等待被讀的字節數。

  (2)錯誤處理和通信狀態:在串口通信中,可能會產生很多的錯誤,使用ClearCommError()函數可以檢測錯誤并且清除錯誤條件。

 ?。?)Modem狀態:用SetcommMask()可以包含很多事件標志,但是這些事件標志只指示在串口線路上的電壓變化情況。而調用 GetCommModemStatus()函數可以獲得線路上真正的電壓狀態。

  擴展函數:如果應用程序想用自己的流控,可以使用 EscapeCommFunction()函數設置DTR和RTS線路的電平。

  通信超時:在通信中,超時是個很重要的考慮因素,因為如果在數據接收過程中由于某種原因突然中斷或停止,如果不采取超時控制機制,將會使得I/O線程被掛起或無限阻塞。串口通信中的超時設置分為兩步,首先設置 COMMTIMEOUTS結構的五個變量,然后調用SetcommTimeouts()設置超時值。對于使用異步方式讀寫的操作,如果操作掛起后,異步成功完成了讀寫,WaitForSingleObject()或 WaitForMultipleObjects()函數將返回WAIT_OBJECT_0,GetOverlappedResult()返回TRUE。其實還可以用GetCommTimeouts()得到系統初始值。

  關閉串口:程序結束或需要釋放串口資源時,應該正確關閉串口,關閉串口比較簡單,使用API調用CloseHandle()關閉串口的句柄就可以了。

  調用方法為:CloseHandle(hComm);

  但是值得注意的是在關閉串口之前必須保證讀寫串口線程已經退出,否則會引起誤操作,一般采用的辦法是使用事件驅動機制,啟動一事件,通知串口讀寫線程強制退出,在線程退出之前,通知主線程可以關閉串口。

  二、實現

  1.程序設計思路

  對于不同的應用程序,雖然界面不同,但是如果采用串口與主機之間的通信,對串口的處理方式大致相似,無非就是通過串口收發數據,對于通過串口接收到的數據,交給上層軟件處理顯示,對于上層要發給串口的數據,進行轉發。但在實際編程中,由于采用的通信方式和流控不同,串口設置也不同,這就涉及到 DCB的初始化問題和讀寫串口等細節問題。串口通信應用程序設計的總體思路(即操作過程)是:首先,確定要打開的串口名、波特率、奇偶校驗方式、數據位、停止位,傳遞給CreateFile()函數打開特定串口;其次,為了保護系統對串口的初始設置,調用 GetCommTimeouts()得到串口的原始超時設置;然后,初始化DCB對象,調用SetCommState() 設置DCB,調用SetCommTimeouts()設置串口超時控制;再次,調用SetupComm()設置串口接收發送數據的緩沖區大小,串口的設置就基本完成,之后就可以啟動讀寫線程了。

  一般來說,串口的讀寫由串口讀寫線程完成,這樣可以避免讀寫阻塞時主程序死鎖。對于全雙工的串口讀寫,應該分別開啟讀線程和寫線程;對于半雙工和單工的,建議只需開啟一個線程即可。在線程中,按照預定好的通信握手方式,正確檢測串口狀態,讀取發送串口數據。

  2.實現細節

  在半雙工的情況下,首先完成必要的串口配置,成功打開串口、DCB設置、超時設置;然后開啟線程,如: CwinThread hSerialThread = (CWinThread*) AfxBeginThread(SerialOperation,hWnd,THREAD_PRIORITY_NORMAL); 其中開啟之線程為SerialOperation,優先級為普通。

  全雙工情況下的串口編程,與單工差不多,區別僅僅在于啟動雙線程,分別為讀線程和寫線程,讀線程根據不同的事件或消息,通過不斷查詢串口所收到的有效數據,完成讀操作;寫線程通過接收主線程的發送數據事件和要發送的數據,向串口發送。

此內容為AET網站原創,未經授權禁止轉載。
热re99久久精品国产66热_欧美小视频在线观看_日韩成人激情影院_庆余年2免费日韩剧观看大牛_91久久久久久国产精品_国产原创欧美精品_美女999久久久精品视频_欧美大成色www永久网站婷_国产色婷婷国产综合在线理论片a_国产精品电影在线观看_日韩精品视频在线观看网址_97在线观看免费_性欧美亚洲xxxx乳在线观看_久久精品美女视频网站_777国产偷窥盗摄精品视频_在线日韩第一页
  • <strike id="ygamy"></strike>
  • 
    
      • <del id="ygamy"></del>
        <tfoot id="ygamy"></tfoot>
          <strike id="ygamy"></strike>
          欧美午夜精品久久久久久久| 欧美大片在线观看一区| 亚洲综合激情| 欧美福利视频一区| 欧美日韩在线播放| 亚洲桃色在线一区| 蜜臀久久99精品久久久久久9| 欧美一区二区免费视频| 国产精品尤物福利片在线观看| 美女脱光内衣内裤视频久久网站| 麻豆国产va免费精品高清在线| 国产精品久久久一区二区三区| 亚洲国产精品美女| 午夜宅男欧美| 欧美精品一线| 红杏aⅴ成人免费视频| 亚洲人被黑人高潮完整版| 久久精品一区二区三区不卡牛牛| 激情av一区| 亚洲欧美日韩国产另类专区| 国内久久婷婷综合| 伊人一区二区三区久久精品| 欧美午夜视频在线| 久久激情五月激情| 欧美一区深夜视频| 国产亚洲va综合人人澡精品| 亚洲综合国产| 国产视频一区免费看| 一区二区三区欧美视频| 国产精品成人一区二区艾草| 欧美日韩亚洲一区二区三区在线观看| 亚洲男女自偷自拍| 9色精品在线| 久久成人这里只有精品| 欧美大片在线看免费观看| 国产精品自拍小视频| 欧美视频在线观看一区二区| 久久精品国产69国产精品亚洲| 欧美日韩在线一区二区| 亚洲欧美亚洲| 国产主播喷水一区二区| 亚洲第一区色| 欧美一区二区三区四区视频| 国产日韩精品一区二区浪潮av| 欧美国产免费| 欧美一区二区在线视频| 国产婷婷精品| 一区免费观看| 99国产欧美久久久精品| 国产免费亚洲高清| 国产精品美腿一区在线看| 一区二区三区视频在线| 国内精品国产成人| 日韩亚洲视频| 国产精品久在线观看| 欧美日韩黄色大片| 欧美日韩喷水| 麻豆91精品91久久久的内涵| 在线看无码的免费网站| 欧美女激情福利| 久久成人精品| 国内精品视频一区| 欧美一区二区三区婷婷月色| 国产精品视频久久一区| 欧美日韩免费高清一区色橹橹| 久久av免费一区| 亚洲国产精品专区久久| 欧美黄色大片网站| 91久久黄色| 一区一区视频| 国产精品久久| 国产精品一区在线观看你懂的| 国产精品免费电影| 黄色日韩精品| 国产尤物精品| 亚洲国产中文字幕在线观看| 国产日韩欧美精品一区| 欧美视频在线免费| 国产亚洲一区在线播放| 中文欧美在线视频| 免费在线播放第一区高清av| 亚洲激情视频| 亚洲高清色综合| 亚洲欧美日韩一区二区三区在线| 亚洲精品美女久久7777777| 99热这里只有成人精品国产| 亚洲视频成人| 欧美精品一二三| 老司机一区二区| 在线精品国精品国产尤物884a| 国产亚洲精品久久久久婷婷瑜伽| 激情懂色av一区av二区av| 亚洲精品视频在线观看免费| 欧美亚洲一区二区在线| 欧美精品成人| 欧美激情第三页| 国产欧美日韩三级| 亚洲视频综合| 欧美午夜精品电影| 国产亚洲欧美另类中文| 亚洲欧洲精品一区二区精品久久久| 亚洲永久精品大片| 亚洲精品小视频在线观看| 欧美日韩一区免费| 欧美二区不卡| 欧美成人激情视频| 国产喷白浆一区二区三区| 亚洲视频一区在线| 麻豆国产va免费精品高清在线| 欧美精品系列| 亚洲一区二区三区视频播放| 久久夜精品va视频免费观看| 亚洲激情亚洲| 欧美日韩精品国产| 极品尤物久久久av免费看| 国产深夜精品| 亚洲第一天堂无码专区| 国产亚洲一区在线| 麻豆精品国产91久久久久久| 亚洲午夜影视影院在线观看| 久久久久久久一区| 亚洲三级视频| 久久久国产精品一区二区中文| 国产精品99久久久久久久女警| 99re6这里只有精品视频在线观看| 国产精品色婷婷| 欧美日韩精品不卡| 欧美激情精品久久久久久蜜臀| 亚洲人成在线免费观看| 亚洲国产美女精品久久久久∴| 国内成人在线| 亚洲精品国产无天堂网2021| 亚洲影院色在线观看免费| 在线免费观看一区二区三区| 国产色综合天天综合网| 欧美一区二区大片| 亚洲黄色免费网站| 欧美不卡视频一区发布| 国产一区高清视频| av成人黄色| 一区二区三区你懂的| 欧美成人激情在线| 国产精品影院在线观看| 国产三区二区一区久久| 国产精品爱啪在线线免费观看| 999亚洲国产精| 亚洲最新色图| 中文欧美字幕免费| 夜夜嗨av一区二区三区四季av| 国产在线一区二区三区四区| 老司机久久99久久精品播放免费| 在线看无码的免费网站| 日韩亚洲欧美精品| 久久国产精品久久精品国产| 久久精品亚洲热| 国产在线播精品第三| 国产精品日韩欧美一区二区三区| 亚洲视频欧美视频| 欧美国产日韩一区二区在线观看| 激情文学综合丁香| 欧美激情五月| 久久久久久亚洲精品杨幂换脸| 欧美日韩麻豆| 新狼窝色av性久久久久久| 国产精品成人一区二区艾草| 国产乱肥老妇国产一区二| 老色鬼久久亚洲一区二区| 99精品欧美一区二区三区综合在线| 91久久国产综合久久蜜月精品| 欧美日韩视频不卡| 国产欧美一区二区三区在线老狼| 国产精品户外野外| 国产精品一级在线| 国产精品看片资源| 国产亚洲欧美日韩在线一区| 国产精品久久久久久久免费软件| 欧美视频中文字幕在线| 美女视频一区免费观看| 国产精品亚洲视频| 亚洲电影av在线| 亚洲欧美日本国产专区一区| 欧美日韩一级视频| 国产精品专区一| 国产精品欧美在线| 欧美日本免费一区二区三区| 亚洲区免费影片| 激情懂色av一区av二区av| 日韩亚洲欧美成人| 久久精品日产第一区二区| 欧美国产1区2区| 国产欧美va欧美不卡在线| 尤物yw午夜国产精品视频| 在线免费高清一区二区三区| 国产精品嫩草99a| 亚洲电影第1页| 国内在线观看一区二区三区| 欧美啪啪一区| 欧美日韩精品免费观看视一区二区| 欧美精品在线免费| 在线观看国产精品淫| 国产精品福利网| 在线成人免费视频| 国产主播一区二区三区| 国产毛片久久| 亚洲人成在线观看一区二区| 韩国成人精品a∨在线观看| 欧美日本国产在线| 久久久999成人| 久久久99精品免费观看不卡| 欧美人在线视频| 国产精品人人爽人人做我的可爱| 欧美成人精品激情在线观看| 影音先锋国产精品| 欧美激情第五页| 亚洲欧美日韩在线一区| 日韩亚洲欧美一区二区三区| 性欧美精品高清| 久久综合网络一区二区| 国产精品揄拍一区二区| 亚洲人精品午夜在线观看| 国产一区二区三区四区老人| 国产夜色精品一区二区av| 国产视频一区二区在线观看| 久久免费视频这里只有精品| 亚洲天堂免费在线观看视频| 激情成人av在线| 欧美专区一区二区三区| 欧美精品一区二区三区视频| 欧美黄色网络| 中文精品视频| 99视频精品全国免费| 欧美在线三级| 欧美国产极速在线| 亚洲国产日韩欧美综合久久| 香蕉av福利精品导航| 国产欧美一区二区精品仙草咪| 亚洲精品视频在线看| 美女被久久久| 99国产精品视频免费观看| 欧美护士18xxxxhd| 最新高清无码专区| 久久久久免费视频| 蜜桃精品一区二区三区| 久久www成人_看片免费不卡| 国产午夜精品全部视频在线播放| 亚洲一区二区三区精品在线| 亚洲视频免费在线观看| 欧美大片在线看| 欧美日韩国产高清视频| 中国成人在线视频| 久久精品亚洲一区二区三区浴池| 久久久久久91香蕉国产| 国产精品成人一区二区| 国产一区二区三区高清播放| 在线欧美不卡| 久久久久久久一区| 亚洲国产精品专区久久| 久久国产视频网站| 中文欧美日韩| 99热在这里有精品免费| 国内久久精品| 狠狠久久亚洲欧美专区| 亚洲一区二区影院| 亚洲欧美久久久久一区二区三区| 欧美日韩一区二区三区免费看| 麻豆精品一区二区av白丝在线| 国产女主播一区二区| 在线亚洲欧美专区二区| 久久先锋资源| 亚洲国产天堂久久综合网| 欧美系列精品| 美女视频黄免费的久久| 欧美理论大片| 亚洲第一二三四五区| 欧美freesex交免费视频| 欧美精品免费在线观看| 亚洲国产精品久久久久久女王| 国产精品v欧美精品v日韩| 影音先锋久久资源网| 国产精品视频不卡| 亚洲图中文字幕| 欧美黄色小视频| 小黄鸭精品aⅴ导航网站入口| 国产偷国产偷亚洲高清97cao| 亚洲国产精品一区二区第一页| 一区二区三区免费看| av成人国产| 一区二区三区在线视频观看| 亚洲欧洲中文日韩久久av乱码| 久久久一本精品99久久精品66| 欧美亚洲三区| 另类国产ts人妖高潮视频| 日韩亚洲国产欧美| 国产精品人人做人人爽| 久久黄金**| 欧美视频精品在线观看| 欧美成人乱码一区二区三区| 亚洲精品一区在线观看香蕉| 久久国产精品亚洲va麻豆| 国产精品自拍三区| 欧美大香线蕉线伊人久久国产精品| 欧美福利在线观看| 欧美日韩在线另类| 欧美一级电影久久| 亚洲影视九九影院在线观看| 欧美亚洲自偷自偷| 欧美日本一区二区三区| 国产亚洲精品一区二区| 久久xxxx精品视频| 美女视频一区免费观看| 一本色道久久88精品综合| 亚洲精选在线| 久久综合精品国产一区二区三区| 曰本成人黄色| 99re66热这里只有精品3直播| 欧美日韩精品一区二区在线播放| 亚洲伦理网站| 日韩五码在线| 欧美日韩免费在线| 久久久久国产精品厨房| 久久夜色精品国产亚洲aⅴ| 欧美日韩国产精品一区| 亚洲成人直播| 日韩视频国产视频| 欧美大片免费久久精品三p| 欧美成黄导航| 国产精品视频一区二区高潮| 亚洲电影有码|