国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
用Windows API 實(shí)現(xiàn)串行通信

http://blog.163.com/zhaojun_xf/blog/static/30050580200872465739835/

2008

劉樹(shù)坤 劉金

  摘 要:介紹利用Windows API 在VC++ 5.0下實(shí)現(xiàn)微機(jī)串行通信程序的設(shè)計(jì)方法,并給出主要的通信程序代碼。
  關(guān)鍵詞:Windows API;串行通信;VC++
 

1 引言

  Windows 下的串行通信可有多種實(shí)現(xiàn)方法,如利用VB的MSCOMM.OCX控件,或利用Windows API等。在某些情況下,VB的MSCOMM.OCX控件不適合我們的要求,這時(shí)我們可以用Windows API 提供的通信函數(shù)來(lái)實(shí)現(xiàn),以編寫(xiě)出可移植性強(qiáng)的串行通信程序。自Windows95以來(lái),Windows 提供了大量的API,這些API幾乎可以幫助我們快速、方便地實(shí)現(xiàn)Windows應(yīng)用程序的各種功能。VC++是Windows應(yīng)用程序開(kāi)發(fā)的主流語(yǔ)言之一,它具有良好的圖形設(shè)計(jì)界面并支持面向?qū)ο蟮某绦蛟O(shè)計(jì)方法。本文結(jié)合一個(gè)實(shí)例介紹VC++5.0下利用Windows API 的串行通信程序設(shè)計(jì)。

2 通信程序設(shè)計(jì)

  本文的實(shí)例是一臺(tái)微機(jī)和多臺(tái)單片機(jī)設(shè)備進(jìn)行串行通信,通信協(xié)議為RS—485,微機(jī)和單片機(jī)組成一個(gè)總線式網(wǎng)絡(luò)結(jié)構(gòu)。由于采用這種總線式結(jié)構(gòu),為防止總線競(jìng)爭(zhēng)(數(shù)據(jù)碰撞),只能由微機(jī)依次輪循總線上的各單片機(jī)設(shè)備來(lái)進(jìn)行通信。
  對(duì)串行通信設(shè)備,Win32 API 可支持同步和異步兩種I/O操作。同步操作方式程序設(shè)計(jì)相對(duì)比較簡(jiǎn)單,但I(xiàn)/O操作函數(shù)在I/O操作結(jié)束前不能返回,這將掛起調(diào)用線程,直到I/O操作結(jié)束。異步操作方式相對(duì)要復(fù)雜一些,但它可讓耗時(shí)的I/O操作在后臺(tái)進(jìn)行,這樣不會(huì)掛起調(diào)用線程,這在大數(shù)據(jù)量通信的情況下對(duì)改善調(diào)用線程的響應(yīng)速度是相當(dāng)有效的。異步操作方式特別適合同時(shí)對(duì)多個(gè)串口設(shè)備進(jìn)行I/O操作和同時(shí)對(duì)一個(gè)串口設(shè)備進(jìn)行讀/寫(xiě)操作。兩種操作方式的程序設(shè)計(jì)基本思想是相似的,考慮到本文實(shí)例的這種總線網(wǎng)絡(luò)結(jié)構(gòu)且通信數(shù)據(jù)量不大,將針對(duì)同步操作方式給出具體的通信程序設(shè)計(jì),同時(shí)簡(jiǎn)單說(shuō)明如何實(shí)現(xiàn)異步I/O操作。
2.1 串口設(shè)備的初始化
  通過(guò)CreateFile獲得串口設(shè)備句柄并對(duì)其進(jìn)行通信參數(shù)設(shè)置,包括設(shè)置輸出/接收緩沖區(qū)大小、超時(shí)控制和事件監(jiān)視等。
HANDLE hComDev=0;

//串行設(shè)備句柄;

BOOL bOpen=FALSE;

//串口打開(kāi)標(biāo)志;

HANDLE hEvent=0;

//線程同步事件句柄;

BOOL SetupSynCom()
{
 DCB dcb;
 COMMTIMEOUTS timeouts;
 if(bOpen) return FALSE;

//設(shè)備已打開(kāi);

 if((hComDev=CreateFile("COM1",GENERICREAD|GENERICWRITE,0,NULL,OPENEXISTING,FILEATTRIBUTENORMAL,NULL))==INVALIDHANDLEVALUE)

//打開(kāi)COM1;

 return FALSE;
 //此處我們不使用超時(shí)控制,
 //將timeouts結(jié)構(gòu)中各項(xiàng)的值賦成0;
 SetCommTimeouts(hComDev,&timeouts);

//設(shè)置超時(shí)控制;

 SetupComm(hComDev,1024,512);

//設(shè)置接收緩沖區(qū)和輸出緩沖區(qū)的大小;

 GetCommState(hComDev,&dcb);

//獲取缺省的dcb結(jié)構(gòu)的值

 dcb.BaudRate=CBR9600;

//波特率為9600 bps;

 dcb.fParity=NOPARITY;

//無(wú)奇偶校驗(yàn);

 dcb.ByteSize=8;

//數(shù)據(jù)位為8;

 dcb.StopBits=ONESTOPBIT;

//一個(gè)停止位;

 SetCommMask(hComDev,EVERR|EVRXCHAR);

//監(jiān)視串口的錯(cuò)誤和接收到字符兩種事件;

 SetCommState(hComDev,&dcb);

//設(shè)置串口設(shè)備控制參數(shù);

 bOpen=TRUE;

//設(shè)備已打開(kāi);

 hEvent=CreateEvent(NULL,FALSE,FALSE,"WatchEvent");

//創(chuàng)建人工重設(shè)、未發(fā)信號(hào)的事件;

 AfxBeginThread(CommWatchProc,pParam);

//創(chuàng)建一個(gè)事件監(jiān)視線程來(lái)監(jiān)視串口事件;

}
  在設(shè)置串口的DCB結(jié)構(gòu)的參數(shù)時(shí),我們沒(méi)有必要設(shè)置每一個(gè)的值,首先讀出DCB缺省的參數(shù)設(shè)置,然后只修改我們需要的參數(shù),其它都取缺省值。由于我們對(duì)串口進(jìn)行的同步I/O操作,除非指定進(jìn)行監(jiān)測(cè)的事件發(fā)生,否則WaitCommEvent函數(shù)不會(huì)返回,所以在串口設(shè)備初始化的最后,建立一個(gè)單獨(dú)的監(jiān)視線程來(lái)監(jiān)視串口的事件,以免掛起當(dāng)前調(diào)用線程,其中pParam可以是一個(gè)對(duì)事件進(jìn)行處理的窗口類(lèi)指針。
  如果要進(jìn)行異步I/O操作,打開(kāi)設(shè)備句柄時(shí),CreateFile的第六個(gè)參數(shù)應(yīng)增加FILEFLAGOVERLAPPED 標(biāo)志。
2.2 數(shù)據(jù)發(fā)送
  我們用WriteFile來(lái)進(jìn)行數(shù)據(jù)發(fā)送,對(duì)于同步I/O操作,它的最后一個(gè)參數(shù)可為NULL,而對(duì)異步I/O操作,它的最后一個(gè)參數(shù)必須是一個(gè)指向OVERLAPPED結(jié)構(gòu)的指針,通過(guò)這個(gè)OVERLAPPED結(jié)構(gòu)來(lái)獲得當(dāng)前操作狀態(tài)。
BOOL WriteComm(LPCVOID lpSndBuffer,DWORD dwBytesToWrite)
{ //lpSndBuffer為發(fā)送數(shù)據(jù)緩沖區(qū)指針,dwBytesToWrite為
 將發(fā)送的字節(jié)長(zhǎng)度;
 BOOL bWriteState;

//發(fā)送結(jié)果;

 DWORD dwBytesWritten;

//實(shí)際發(fā)送的字節(jié)數(shù);

 if(!bOpen) return FALSE;

//設(shè)備未打開(kāi);

 bWriteState=WriteFile(hComDev,lpSndBuffer,dwBytesToWrite,&dwBytesWritten,NULL);
 if(!bWriteState || dwBytesToWrite!=dwBytesWritten)
  return FALSE;

//發(fā)送失?。?/font>

 else
  return TRUE;

//發(fā)送成功;

}
2.3 數(shù)據(jù)接收
  用ReadFile來(lái)從串口接收緩沖區(qū)讀取數(shù)據(jù),數(shù)據(jù)讀取前,用ClearCommError函數(shù)獲得接收緩沖區(qū)中的字節(jié)數(shù)。至于同步和異步讀取的差別,同發(fā)送數(shù)據(jù)是一樣的。
DWORD ReadComm(LPVOID lpInBuffer,DWORD dwBytesToRead)
{ //lpInBuffer為接收數(shù)據(jù)的緩沖區(qū)指針, dwBytesToRead為準(zhǔn)備讀取的數(shù)據(jù)長(zhǎng)度(字節(jié)數(shù));
 COMSTAT ComStat;

//串口設(shè)備狀態(tài)結(jié)構(gòu);

 DWORD dwBytesRead,dwErrorFlags;
 if(!bOpen) return 0;

//設(shè)備未打開(kāi);

 ClearCommError(hComDev,&dwErrorFlags,&ComStat);

//讀取串口設(shè)備的當(dāng)前狀態(tài);

 dwBytesRead=min(dwBytesToRead,ComStat.cbInQue);

//應(yīng)該讀取的數(shù)據(jù)長(zhǎng)度;

 if(dwBytesRead>0)
  if(!ReadFile(hComDev,lpInBuffer,dwBytesRead,&dwBytesRead,NULL))

//讀取數(shù)據(jù);

    dwBytesRead=0;
 return dwBytesRead;
}
2.4 事件監(jiān)視線程
  事件監(jiān)視線程對(duì)串口事件進(jìn)行監(jiān)視,當(dāng)監(jiān)視的事件發(fā)生時(shí),監(jiān)視線程可將這個(gè)事件發(fā)送(SendMessage)或張貼(PostMessage)到對(duì)事件進(jìn)行處理的窗口類(lèi)(由pParam指定)中去。
UINT CommWatchProc(LPVOID pParam)
{ DWORD dwEventMask=0;

//發(fā)生的事件;

 while(bOpen)
 { WaitCommEvent(hComDev, &dwEventMask, NULL);

//等待監(jiān)視的事件發(fā)生;

  if ((dwEventMask & EVRXCHAR) == EVRXCHAR)
   //接收到字符事件,可以將此消息張貼到由pParam有指定的窗口類(lèi)中進(jìn)行處理;
  if(dwEventMask & EVERR)==EVERROR)

//發(fā)生錯(cuò)誤事件,處理;

 }
 SetEvent(hEvent);

//發(fā)信號(hào),指示監(jiān)視線程結(jié)束;

 return 0;
}
2.5 關(guān)閉串口設(shè)備
  在整個(gè)應(yīng)用程序結(jié)束時(shí)或不再使用串口設(shè)備時(shí),應(yīng)將串口設(shè)備關(guān)閉,包括取消事件監(jiān)視,將設(shè)備打開(kāi)標(biāo)志bOpen置為FALSE以使事件監(jiān)視線程結(jié)束,清除發(fā)送/接收緩沖區(qū)和關(guān)閉設(shè)備句柄。
void CloseSynComm()
{ if(!bOpen) return;
 bOpen=FALSE;

//結(jié)束事件監(jiān)視線程;

 SetCommMask(hComDev,0);

//取消事件監(jiān)視,此時(shí)監(jiān)視線程中的WaitCommEvent將返回;

 WaitForSingleObject(hEvent,INFINITE);

//等待監(jiān)視線程結(jié)束;

 CloseHandle(hEvent);

//關(guān)閉事件句柄;

 //停止發(fā)送和接收數(shù)據(jù),并清除發(fā)送和接收緩沖區(qū);
 PurgeComm(hComDev,PURGETXABORT|PURGERXABORT|PURGETXCLEAR|PURGERXCLEAR);
 CloseHandle(hComDev);

//關(guān)閉設(shè)備句柄;

}

3 結(jié)束語(yǔ)

  以上給出了用Windows API 設(shè)計(jì)串行通信的基本思想,對(duì)這個(gè)同步I/O操作的串行通信程序稍加改造就可進(jìn)行異步I/O操作。在實(shí)際應(yīng)用中,我們可以將這些串行通信函數(shù)和成員變量加到一個(gè)現(xiàn)成的CWnd類(lèi)或其派生類(lèi)中來(lái)實(shí)現(xiàn)串行通信,也可設(shè)計(jì)一個(gè)新的串行通信類(lèi)來(lái)包含這些成員函數(shù)和成員變量??傊?,利用WIN 3.2 API可以設(shè)計(jì)出靈活、能滿足各種要求的串行通信程序。

作者簡(jiǎn)介:劉樹(shù)坤 從事計(jì)算機(jī)網(wǎng)絡(luò)通信和工業(yè)控制、檢測(cè)的研究開(kāi)發(fā)工作。
作者單位:劉樹(shù)坤(西南計(jì)算中心 四川.綿陽(yáng)621900)
     劉金(西南計(jì)算中心 四川.綿陽(yáng)621900)

參考文獻(xiàn)

[1]?。溃㏒tefano Maruzzi.The Microsoft Windows 95開(kāi)發(fā)人員指南[M].周靖,等譯.北京:機(jī)械工業(yè)出版社,1997.
[2] 史惠康.VISUAL C++5.0實(shí)用編程技術(shù)[M]. 中國(guó)水利水電出版社,1998.

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服