在线看毛片视频-国产免费av在线-欧美日韩一区二区三区-国产成人无码av在线播放无广告-亚洲人va欧美va人人爽-国产第一草草-西班牙黄色片-四虎在线网站8848-最新av片免费网站入口-东京热无码中文字幕av专区-日本大人吃奶视频xxxx-欧美精品一区二区三区四区五区-国产片天天弄-国产免费内射又粗又爽密桃视频-欧美爱爱网站-日韩v欧美

當前位置:雨林木風下載站 > 技術開發教程 > 詳細頁面

基于VC的串行通信技術應用案例

基于VC的串行通信技術應用案例

更新時間:2022-04-26 文章作者:未知 信息來源:網絡 閱讀次數:

作者: 李湘江

在工業控制中,串口是常用的計算機與外部串行設備之間的數據傳輸通道,由于串行通信方便易行,所以應用廣泛。

本文將介紹在Windows平臺下串行通信的工作機制和用Visual C++設計串行通信程序的編程方法及通信方式。

VC中實現串行通信的編程技術
以下我們將介紹VC中幾種實現串行通信的編程技術:

利用VC++的標準通信函數

利用VC++的標準通信函數_inp和_outp可實現串口通信。下面是一個串口初始化的程序:

void init_com(PORT)
{char i;
outp(PORT+3,0x80);
outp(PORT,0x0C);
outp(PORT+1,0);
outp(PORT+3 ,0x3a);
outp(PORT+3 ,0x03);
i=inp(PORT+5) && 0xfe;
outp(PORT+5,i);}

使用串行通信控件MSComm

串行通信控件MSCOmm32.OCX提供了使用RS-232來進行數據通信的所有協議,VC為該控件提供了標準的事件處理函數、過程,并通過屬性和方法提供了串行通信的設置。它使用戶能夠方便地訪問Windows串行通信驅動程序的大多數特性,包括輸入、輸出緩沖區的大小及決定何時使用流控制命令掛起數據傳輸等。

在ClassWizard中為新創建的通信控件定義成員對象(CMSComm m_Serial),通過該對象便可以對串口屬性進行設置,MSComm控件共有27個屬性。以下是通過設置控件屬性對串口進行初始化的實例:

BOOL CSampleDlg:: PortOpen()
{ BOOL m_Opened;
......
m_Serial.SetCommPort(2); // 指定串口號
m_Serial.SetSettings("4800,N,8,1");
// 通信參數設置
m_Serial.SetInBufferSize(1024);
// 指定接收緩沖區大小
m_Serial.SetInBufferCount(0);
// 清空接收緩沖區
m_Serial.InputMode(1);
// 設置數據獲取方式
m_Serial.SetInputLen(0);
// 設置讀取方式
m_Opened=m_Serail.SetPortOpen(1);
// 打開指定的串口
return m_Opened;}

打開所需串口后,我們需要考慮串口通信的時機。在接收或發送數據過程中,可能需要監視并響應一些事件和錯誤,所以事件驅動是處理串行端口交互作用的一種非常有效的方法。使用OnComm事件和CommEvent屬性捕捉并檢查通信事件和錯誤的值。發生通信事件或錯誤時將觸發OnComm事件,CommEvent屬性的值將被改變,應用程序通過檢查CommEvent屬性值并作出相應的反應。

使用API函數

控件雖然簡單易用,但由于必須拿到對話框中使用,在一些需要在線程中實現通信的應用場合下,控件的使用顯得捉襟見肘。API是附帶在Windows內部的一個極其重要的組成部分。Windows的32位API主要是一系列很復雜的函數和消息集合。它可以看作是Windows系統為在其下運行的各種開發系統提供的開放式通用功能增強接口。

通信程序在CreateFile處指定串口設備及相關的操作屬性,再返回一個句柄,該句柄將被用于后續的通信操作,并貫穿整個通信過程。串口打開后,其屬性被設置為默認值,根據具體需要,通過調用GetCommState(hComm,&&dcb)讀取當前串口設備控制塊DCB設置,修改后通過SetCommState(hComm,&&dcb)將其寫入。運用ReadFile()與WriteFile()這兩個API函數實現串口讀寫操作,若為異步通信方式,兩函數中最后一個參數為指向OVERLAPPED結構的非空指針,在讀寫函數返回值為FALSE的情況下,調用GetLastError()函數,返回值為ERROR_IO_PENDING,表明I/O操作懸掛,即操作轉入后臺繼續執行。此時,可以用WaitForSingleObject()來等待結束信號并設置最長等待時間,舉例如下:

BOOL bReadStatus;
bReadStatus = ReadFile( m_hIDComDev, buffer,
dwBytesRead, &&dwBytesRead, &&m_OverlappedRead );
if(!bReadStatus){
if(GetLastError()==ERROR_IO_PENDING){
WaitForSingleObject(m_OverlappedRead.hEvent,1000);
return ((int)dwBytesRead);}
return(0);}
return ((int)dwBytesRead);

多線程下實現串行通信
Windows內部的搶先調度程序在活動的線程之間分配CPU時間,Windows區分兩種不同類型的線程,一種是用戶界面線程(User Interface Thread),它包含消息循環或消息泵,用于處理接收到的消息;另一種是工作線程(Work Thread),它沒有消息循環,用于執行后臺任務、監視串口事件的線程即為工作線程。

多線程程序的編寫在端口的配置,連接部分與單線程的相同,在端口配置完畢后,最重要的是根據實際情況,建立多線程之間的同步對象,如信號燈、臨界區和事件等。

一切就緒后即可啟動工作線程,程序如下:

CWinThrea CommThread = AfxBegin
Thread(CommWatchThread, // 線程函數名
(LPVOID) m_pTTYInfo, // 傳遞的參數
THREAD_PRIORITY_ABOVE_NORMAL,
// 設置線程優先級
(UINT) 0, // 最大堆棧大小
(DWORD) CREATE_SUSPENDED , // 創建標志
(LPSECURITY_ATTRIBUTES) NULL);
if(WaitCommEvent(pTTYInfo->idComDev,&&dwEvtMask,NULL))
{
if((dwEvtMask && pTTYInfo->dwEvtMask )== pTTYInfo->dwEvtMask)
{
WaitForSingleObject(pTTYInfo->hPostEvent,0xFFFFFFFF);
ResetEvent(pTTYInfo->hPostEvent);
// 置同步事件對象為非信號態
::PostMessage(CSampleView,ID_COM1_DATA,0,0); // 發送通知消息}}
BEGIN_MESSAGE_MAP(CSampleView, CView)
//{{AFX_MSG_MAP(CSampleView)
ON_MESSAGE(ID_COM1_DATA, OnProcessCom1Data)
ON_MESSAGE(ID_COM2_DATA, OnProcessCom2Data)
.....
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

多線程的實現可以使得各端口獨立,準確地實現串行通信,使串行通信具有更廣泛的靈活性與嚴格性,且充分利用CPU時間。但在具體的實時監控系統中如何協調多個線程、線程之間以何種方式實現同步,這是多線程串行通信程序實現的難點。

串行通信的操作方式
下面我們將介紹串行通信的幾種操作方式:

1.同步方式

同步方式中,讀串口的函數試圖在串口的接收緩沖區中讀取規定數目的數據,直到規定數目的數據全部被讀出或設定的超時時間已到時才返回。例如:

COMMTIMEOUTS timeOver;
memset(&&timeOver,0,sizeof(timeOver));
DWORD timeMultiplier,timeConstant;
timeOver.ReadTotalTimeoutMultiplier=timeMultiplier;
timeOver.ReadTotalTimeoutConstant=timeConstant;
SetCommTimeouts(hComport,&&timeOver);
……
ReadFile(hComport,inBuffer,nWantRead,&&nRealRead,NULL);

COMMTIMEOUTS結構用于設置讀寫函數的等待時間。

在ReadFile函數中hComport為待讀串口句柄;inBuffer為輸入緩沖區大小;nWantRead為每次調用ReadFile時,函數試圖讀出的字節數;nRealRead為實際讀出的字節數;最后一個參數值NULL代表ReadFile將采用同步文件讀寫的方式。

如果所規定的待讀取數據的數目nWantRead較大且設定的超時時間也較長,而接收緩沖區中數據較少,則可能引起線程阻塞。解決這一問題的方法是檢查COMSTAT結構的cbInQue成員,該成員的大小即為接收緩沖區中處于等待狀態的數據的實際個數。如果令nWantRead的值等于COMSTAT.cbInQue,就能較好地防止線程阻塞。

2.查詢方式

查詢方式,即一個進程中的某一線程定時地查詢串口的接收緩沖區,如果緩沖區中有數據,就讀取數據;若緩沖區中沒有數據,該線程將繼續執行,因此會占用大量的CPU時間,它實際上是同步方式的一種派生。例如:

COMMTIMEOUTS timeOver;
memset(&&timeOver,0,sizeof(timeOver));
timeOver.ReadIntervalTimeout=MAXWORD;
SetCommTimeouts(hComport.&&timeOver);
……
ReadFile(hComport.inBuffer.nWantRead.&&nRealRead,NULL);

除了COMMTIMEOUTS結構的變量timeOver設置不同外,查詢方式與同步方式在程序代碼方面很類似,但二者的工作方式卻差別很大。盡管ReadFile采用的也是同步文件讀寫方式,但由于timeOver的區間超過時間設置為MAXWORD,所以ReadFile每次將讀出接收隊列中的所有處于等待狀態的數據,一次最多可讀出nWantRead個字節的數據。

3.異步方式

異步方式中,利用Windows的多線程結構,可以讓串口的讀寫操作在后臺進行,而應用程序的其他部分在前臺執行。例如:

OVERLAPPED wrOverlapped;
COMMTIMEOUTS timeOver;
memset(&&timeOver.0.sizeof(timeOver));
DWORDtimeMultiplier,timeConstant;
timeOver.ReadTotalTimeoutMultiplier=timeMultiplier;
timeOver.ReadTotalTimeoutConstant=timeConstant;
SetCommTimeouts(hComport,&&timeOver);
wrOverlapped.hEvent=CreateEvent(NULL.TRUE,FALSE,NULL);
……
ReadFile(hComport,inBuffer,nWantRead,&&nRealRead,&&wrOverlapped);
GetOverlappedResult(hComport,&&wrOverlapped,&& nRealRead,TRUE);
……
ResetEvent(wrOverlapped.hEvent);

上面代碼中的ReadFile由于采用了異步方式,所以它只返回數據是否已開始讀入的狀態,并不返回實際的讀入數據,即ReadFile中的nRealRead無效。實際讀入的數據是由GetOverlappedResult函數返回的,該函數的最后一個參數值為TRUE,表示它等待異步操作結束后才返回到應用程序,此時,GetOverlappedResult函數與WaitForSingleObject函數等效。

當采用異步方式時,在用CreateFile打開串口設備時,CreateFile函數的參數fdwAttrsAndFlags必須設為FILE_FLAG_ OVERLAPPED。在Windows中,只有在串行設備上才支持異步文件讀寫,并且,GetOverlappedResult函數也只支持串行設備或用DeviceloControl函數打開的文件。

4.事件驅動方式

若對端口數據的響應時間要求較嚴格,可采用事件驅動方式。事件驅動方式通過設置事件通知,當所希望的事件發生時,Windows發出該事件已發生的通知,這與DOS環境下的中斷方式很相似。Windows定義了9種串口通信事件,較常用的有以下三種:

EV_RXCHAR:接收到一個字節,并放入輸入緩沖區;

EV_TXEMPTY:輸出緩沖區中的最后一個字符,發送出去;

EV_RXFLAG:接收到事件字符(DCB結構中EvtChar成員),放入輸入緩沖區。

在用SetCommMask()指定了有用的事件后,應用程序可調用WaitCommEvent()來等待事件的發生。SetCommMask(hComm,0)可使WaitCommEvent()中止。例如:

COMSTAT comStat;
DWORD dwEvent;
SetCommMask(hComport,EV_RXCHAR);
……
if(WaitCommEvent(hComport,&&dwEvent,NULL))
 if((dwEvent&&EV_RXCHAR)&&&&comstat.cbInQue)
   ReadFile(hComport,inBuffer,comstat.cbInQue,&&nRealRead,NULL);

程序中,我們首先用SetCommMask函數設置事件代碼,上面的代碼中為EV_RXCHAR,表示接收到一個字符時觸發這一事件,然后調用WaitCommEvent函數等待該事件的發生。注意,WaitCommEvent函數第3個參數1pOverlapped可以是一個OVERLAPPED結構的變量指針,也可以是NULL,當用NULL時,表示該函數是同步的,否則表示該函數是異步的。

5.幾種方式的比較

在一般要求情況下,查詢方式是一種最直接的讀串口方式。但定時查詢存在一個致命弱點,即查詢是定時發生的,可能發生得過早或過晚。在數據變化較快的情況下,特別是主控計算機的串口通過擴展板擴展至多個時,需定時地對所有串口輪流查詢,此時容易發生數據的丟失。雖然定時間隔越小,數據的實時性越高,但系統的資源也被占去越多。

Windows中提出文件讀寫的異步方式,主要是針對文件I/O相對較慢的速度而進行的改進,它利用了Windows的多線程結構。雖然在Windows中沒有實現任何對文件I/O的異步操作,但它卻能對串口進行異步操作。采用異步方式,可以提高系統的整體性能,在對系統強壯性要求較高的場合,建議采用這種方式。

事件驅動方式是一種高效的串口讀方式。這種方式的實時性較高,特別是對于擴展了多個串口的情況,并不要求像查詢方式那樣定時地對所有串口輪流查詢,而是像中斷方式那樣,只有當設定的事件發生時,應用程序得到Windows操作系統發出的消息后,才進行相應處理,避免了數據丟失。在實時性要求較高的場合,筆者建議采用這種方式。

溫馨提示:喜歡本站的話,請收藏一下本站!

本類教程下載

系統下載排行

在线看毛片视频-国产免费av在线-欧美日韩一区二区三区-国产成人无码av在线播放无广告-亚洲人va欧美va人人爽-国产第一草草-西班牙黄色片-四虎在线网站8848-最新av片免费网站入口-东京热无码中文字幕av专区-日本大人吃奶视频xxxx-欧美精品一区二区三区四区五区-国产片天天弄-国产免费内射又粗又爽密桃视频-欧美爱爱网站-日韩v欧美
  • <li id="86scu"><menu id="86scu"></menu></li>
    <li id="86scu"></li>
    <button id="86scu"></button>
  • <s id="86scu"></s><button id="86scu"><menu id="86scu"></menu></button>
  • 久久久精品视频国产| 国产成人美女视频| 欧美中日韩在线| 日本特黄在线观看| 欧美成人手机在线视频| 中文字幕成人免费视频| 美女黄色片视频| 桥本有菜av在线| 日韩欧美中文视频| 黄色一级视频播放| 超碰91在线播放| 天天干天天操天天干天天操| 国产欧美一区二| 日本一二三四区视频| 国内国产精品天干天干| 欧美精品 - 色网| 艳母动漫在线观看| 男人天堂手机在线视频| 成人免费毛片在线观看| 波多野结衣50连登视频| 丰满少妇在线观看| 日韩高清在线一区二区| 伊人再见免费在线观看高清版 | 国产片侵犯亲女视频播放| 日产精品久久久久久久蜜臀| 人人妻人人做人人爽| 日韩亚洲在线视频| 中文字幕第一页在线视频| 日韩欧美视频免费在线观看| 天堂8在线天堂资源bt| 久久精品国产精品亚洲色婷婷| 97公开免费视频| 免费日韩在线观看| 国产精品少妇在线视频| 三级黄色片免费观看| 日日橹狠狠爱欧美超碰| 一级黄色特级片| 久久久久久久久久久99| 亚洲制服在线观看| 成人毛片视频网站| 中文字幕在线视频一区二区| 波多野结衣家庭教师视频| 亚欧精品在线视频| 男人天堂网视频| 日韩专区第三页| 最新中文字幕免费视频| 成人免费a级片| 亚洲 激情 在线| 国产91在线免费| 伊人再见免费在线观看高清版 | 六月婷婷在线视频| 国产又粗又长又爽又黄的视频| 国产中文字幕二区| 中文字幕av久久| 一区二区三区韩国| 国产a级一级片| 久久久久久久久久久99| 欧美另类videosbestsex日本| www.超碰97.com| 黄色永久免费网站| 黄色三级视频片| 国产亚洲天堂网| 少妇高潮喷水久久久久久久久久| 97超碰在线视| 无码熟妇人妻av在线电影| 午夜影院免费版| 青青在线视频观看| 在线免费视频一区| 阿v天堂2017| 99福利在线观看| 91网站在线观看免费| 中国黄色片免费看| 国产精品沙发午睡系列| 国产freexxxx性播放麻豆| 欧美做暖暖视频| 欧美一区二区视频在线播放| 免费看污污视频| 亚洲色欲久久久综合网东京热| 91传媒免费视频| 欧美大片在线播放| 精品国产成人av在线免| 国产又大又黄又粗又爽| 中文av一区二区三区| 欧美国产日韩在线视频 | 欧洲美女和动交zoz0z| 成人污网站在线观看| 青春草国产视频| 91黄色小网站| 免费av不卡在线| 成人免费在线视频播放| 黄色一级视频片| 污版视频在线观看| 神马午夜伦理影院| 久久久久久久久久久视频| 欧美午夜aaaaaa免费视频| 国产精品中文久久久久久| av在线免费观看国产| 一区二区在线播放视频| 无码人妻aⅴ一区二区三区日本| 自拍日韩亚洲一区在线| 国产精品区在线| 人妻av中文系列| 在线观看免费视频高清游戏推荐| 午夜久久久久久久久久久| 无码精品国产一区二区三区免费| 在线观看免费污视频| 欧美黄色免费网址| 污色网站在线观看| 1024av视频| 9色视频在线观看| 日韩av片网站| 国产 福利 在线| 欧美a级黄色大片| 奇米影音第四色| 777久久久精品一区二区三区| 99re6在线观看| 另类小说第一页| 日本韩国欧美在线观看| 欧美亚洲视频一区| 日本高清久久久| 欧美私人情侣网站| 欧美老熟妇喷水| 欧美又粗又长又爽做受| 最新黄色av网站| 91福利免费观看| 亚洲精品手机在线观看| 亚洲黄色小视频在线观看| 欧美日韩黄色一级片| 日韩极品视频在线观看 | 亚洲精品蜜桃久久久久久| 小早川怜子一区二区三区| 超碰在线播放91| 人妻丰满熟妇av无码区app| 妞干网在线视频观看| 蜜臀av色欲a片无码精品一区| 肉大捧一出免费观看网站在线播放| 在线观看国产一级片| 亚洲综合日韩欧美| 亚洲精品自拍网| 天天干天天色天天干| 日韩av片免费观看| 久久撸在线视频| 黄色一级片免费播放| 超薄肉色丝袜足j调教99| 天天干天天色天天爽| 永久av免费在线观看| 韩国黄色一级大片| 日本一区午夜艳熟免费| 日韩xxxx视频| 国产天堂在线播放| 日韩在线一区视频| 强开小嫩苞一区二区三区网站| 97超碰人人爱| 日韩欧美亚洲天堂| 亚洲va综合va国产va中文| www.久久com| 99色这里只有精品| 天堂社区在线视频| 麻豆视频传媒入口| 日韩久久一级片| 九九精品久久久| 成人精品视频在线播放| 波多野结衣作品集| 国产精品嫩草影院8vv8| 91成人综合网| 91视频免费版污| 国产成人精品免费看在线播放| 丰满的少妇愉情hd高清果冻传媒| 男人透女人免费视频| 日韩国产精品毛片| 激情综合网俺也去| 成年丰满熟妇午夜免费视频| 青青在线视频观看| 黄色录像特级片| 超碰在线公开97| 人妻夜夜添夜夜无码av| 天堂在线一区二区三区| 波多野结衣之无限发射| 久久久国产精华液999999 | 久艹在线免费观看| 岛国毛片在线播放| 国产精品丝袜久久久久久消防器材| 中文字幕线观看| 欧美综合在线观看视频| 又大又硬又爽免费视频| 色婷婷激情视频| 黑人粗进入欧美aaaaa| r级无码视频在线观看| 青少年xxxxx性开放hg| 男女视频一区二区三区| 成人av一级片| 成人精品视频在线播放| 成人在线免费高清视频| 午夜不卡福利视频| 在线观看免费视频高清游戏推荐| 国产最新免费视频| 久久久久免费看黄a片app| 成人短视频在线观看免费| 先锋影音男人资源| 日韩最新中文字幕|