基于VC++开发串口通信的方法
?????? 串行通信中的關(guān)鍵是串行通信設(shè)備的初始化、數(shù)據(jù)的發(fā)送和接收及其實現(xiàn)方式。
在Dos環(huán)境下,用戶可以直接對通信設(shè)備編程,可以通過查詢中斷的方式使用通信設(shè)備。但是Windows不提倡應(yīng)用程序直接控制硬件,而是通過Windows所提供的設(shè)備驅(qū)動程序來進行數(shù)據(jù)傳遞。在Windows環(huán)境中,通信支持中斷功能,當通信設(shè)備接收到一個輸入字符的時候就產(chǎn)生一個硬件中斷,該中斷暫停應(yīng)用程序的執(zhí)行,并把接收到的字符存入到一個叫接收數(shù)據(jù)隊列的內(nèi)存緩沖區(qū)中。而待發(fā)數(shù)據(jù)也先存入到一個叫發(fā)送數(shù)據(jù)隊列的內(nèi)存緩沖區(qū)中,再由Windows系統(tǒng)負責(zé)在后臺進行發(fā)送。因此,在Windows下接收和發(fā)送數(shù)據(jù)的關(guān)鍵就是如何從接收隊列取數(shù)據(jù)和如何向發(fā)送數(shù)據(jù)隊列發(fā)數(shù)據(jù)。Windows提供了相應(yīng)的API函數(shù)來實現(xiàn)這些功能。
串行口在Win 32中是作為文件來進行處理的,而不是直接對端口進行操作。在Win32環(huán)境下,可以把串口看作由文件系統(tǒng)訪問的設(shè)備。使用標準的CreateFile()函數(shù)打開端口,再使用ReadFile()和WriteFile()函數(shù)讀寫數(shù)據(jù),就如同端口只是一個文件對象一樣。對于串行通信,Win 32提供了相應(yīng)的文件I/O函數(shù)與通信函數(shù),使用這些函數(shù),可以編制出符合不同需要的通信程序。
通常實現(xiàn)串行通信的步驟如下:
1 ) 按協(xié)議的設(shè)置初始化并打開串行口,這樣做就是通知Windows本應(yīng)用程序需要這個串口,并封鎖其他應(yīng)用程序使它們不能使用此串口。
2) 配置這個串行口。
3) 在串口上往返地傳輸數(shù)據(jù),并在傳輸過程中進行校驗。
4) 不需要此串口時,關(guān)閉串口,即釋放串口以供其它應(yīng)用程序使用。
在這四個步驟中,主要的程序代碼集中在第3步。
本文就Win32環(huán)境下基于VC++開發(fā)串口通信三種方式的編程問題展開討論。
1?采用MFC串口通信編程
Win32系統(tǒng)把文件的概念進行了擴展,無論是文件、通信設(shè)備、命名管道、郵件槽、磁盤還是控制臺都被看作是文件。因此,可以用MFC中的CFile類來實現(xiàn)對串口的操作,并且Win32中的文件I/O函數(shù)支持重疊式輸入輸出,這使得線程從費時的I/O操作中解放出來。Win32 API包含了一系列訪問通信資源的通信函數(shù)。
通常采用MFC的串口通信編程主要步驟如下:
1)在MainFrm?cpp中定義全局變量
HANDLE hCom;//準備打開的串口的句柄
2)打開串口
Windows通信會話以調(diào)用CreateFile()函數(shù)打開串行口開始。通信程序從CreateFile處指定串口設(shè)備及相關(guān)的操作屬性,并返回一個句柄,該句柄將被用于后續(xù)的通信操作。
3)串口初始化(設(shè)置串口參數(shù)及進行串口超時設(shè)置)
在打開通信設(shè)備句柄后,通常要對串口進行初始化工作(即配置參數(shù)如波特率、數(shù)據(jù)位數(shù)、停止位數(shù)、奇偶校驗以及握手和流控協(xié)議等),配置串口通過改變數(shù)據(jù)結(jié)構(gòu)——設(shè)備控制塊DCB(Device Control Block)來實現(xiàn)。結(jié)構(gòu)DCB有近30個數(shù)據(jù)成員,對于采用3線方式的串行通信來說,只要設(shè)置好波特率、數(shù)據(jù)位、停止位、校驗位等幾個關(guān)鍵參數(shù)就可以。
調(diào)用GetCommState函數(shù)可以獲得串口的配置,該函數(shù)把當前配置填充到一個DCB結(jié)構(gòu)中。要修改串口配置,應(yīng)該先修改串口的DCB結(jié)構(gòu),然后調(diào)用SetCommState函數(shù)用指定的DCB結(jié)構(gòu)來設(shè)置串口。
除了在結(jié)構(gòu)DCB中的設(shè)置外,程序一般還需要設(shè)置I/O緩沖區(qū)的大小和超時。超時設(shè)置是為了避免當通信過程中由于數(shù)據(jù)傳輸突然中斷時而造成對串口的讀寫操作進入無限期的等待狀態(tài)。超時設(shè)置過程分為兩步,首先設(shè)置超時結(jié)構(gòu)COMMTIMEOUTS中的五個成員,然后調(diào)用SetCommTimeouts()函數(shù)設(shè)置超時值。
這里介紹一種簡捷的方法可以做到不了解DCB的詳細內(nèi)容也可以設(shè)置好串行通信參數(shù):即利用BuildCommDCB函數(shù)來設(shè)置DCB,然后用函數(shù)SetCommState()配置串行通信口。
DCB dcb;//定義數(shù)據(jù)控制塊結(jié)構(gòu)
GetCommState(hCom,&dcb);//讀串口原來的參數(shù)設(shè)置
BuildCommDCB(“COM2:9600,N,8,1”,& dcb);//創(chuàng)建數(shù)據(jù)控制塊DCB結(jié)構(gòu)
SetCommState(hCom,&dcb);//將結(jié)構(gòu)DCB的主要參數(shù)設(shè)置到串口COM2
其中的BuildCommDCB(“COM2:9600,N,8,1”,&dcb)語句可以代替前面4條串口通信參數(shù)賦值語句的效果。
4)讀寫串口API函數(shù)
串行口打開后,可以對它進行讀寫操作。
5)關(guān)閉串口API函數(shù)
串行口是非共享資源,所以打開串口后,一定要關(guān)閉串口。關(guān)閉串口函數(shù)的原型:BOOL CloseHandle(HANDLE hObject);其中hObject參數(shù)為CreateFile()返回的端口句柄。返回值非0,則調(diào)用成功。
2?采用ActiveX控件 (MScomm控件)編程
雖然在Windows下Win32API提供了使用CreateFile/WriteFile等文件I/O函數(shù)進行串行口操作的方法,但是在編程實現(xiàn)上比較復(fù)雜。Windows平臺先進的ActiveX技術(shù)使得對串行口編程時不再需要處理煩瑣的細節(jié)。利用已有的ActiveX控件,只需要編寫少量的代碼,就可以輕松高效地完成任務(wù)。
Microsoft Communications Control(以下簡稱MSComm)是Microsoft公司提供的簡化Windows下串行通信編程的ActiveX控件,它為應(yīng)用程序提供了通過串行接口收發(fā)數(shù)據(jù)的簡便方法。具體地說,它提供了兩種處理通信問題的方法:一是事件驅(qū)動(Event-driven)方法:主要是在comEvReceive(接收到數(shù)據(jù))事件發(fā)生時響應(yīng)并獲取緩沖區(qū)的數(shù)據(jù)。一是查詢法:在這種情況下,每當應(yīng)用程序執(zhí)行完某一串行口操作后,將不斷檢查MSComm控件的CommEvent屬性以檢查執(zhí)行結(jié)果或者檢查某一事件是否發(fā)生(Microsoft提供的用于串口操作的控件Mscomm共有27個屬性)。
以下介紹在VC集成開發(fā)環(huán)境下對該控件編程的步驟。
(1)在當前的Workspace中插入MSComm控件
在VC環(huán)境下,創(chuàng)建基于對話框的MFC應(yīng)用程序,在設(shè)置項目選項時必須選上ActiveX Controls,其他的按照缺省設(shè)置。然后進行以下步驟:Project菜單→Add to Project→Components and Controls→Registered ActiveX Controls→選擇Components: Microsoft Communications Control,version 6.0插入到當前的Workspace中。
結(jié)果添加了類CMSComm(另有相應(yīng)文件:mscomm.h和mscomm?cpp)。
(2)在MainFrm.h中加入MSComm控件
protected:
CMSComm m_ComPort;
在Mainfrm.cpp::OnCreate()中加入:
DWORD style=WS_VISIBLE|WS_CHILD;
if(!m_ComPort.Create(NULL,style,CRect(0,0,0,0),this,ID_COMMCTRL)){
TRACE0(“Failed to create OLE Communications Control\n”);
return-1;//創(chuàng)建失敗}
(3)初始化串口
以下是通過設(shè)置控件屬性對串口進行初始化的實例:
m_ComPort.SetCommPort(1);//指定串口號
m_ComPort.SetInBufferSize(1024);//設(shè)置輸入緩沖區(qū)的
大小,Bytes
m_ComPort.SetOutBufferSize(512);//設(shè)置輸出緩沖區(qū)的
Bytes,
if(!m_ComPort.GetPortOpen());//打開串口
m_ComPort.SetPortOpen(TRUE);//打開通信口
m_ComPort.SetInputMode(1);//設(shè)置輸入方式為二進制
方式
m_ComPort.SetSettings(“9600,n,8,1”);//設(shè)置波特率等
參數(shù)
m_ComPort.SetRThreshold(1);//為1表示有一個字符引
發(fā)一個事件
m_ComPort.SetInputLen(0);
(4)捕捉串口事件
MSComm控件可以采用輪詢或事件驅(qū)動的兩種方法從端口獲取數(shù)據(jù)。比較常用的是事件驅(qū)動方法:有事件(如接收到數(shù)據(jù))時通知程序。在程序中需要捕獲并處理這些通訊事件。
(5)串口讀寫
完成讀寫的兩個函數(shù)的原型是VARIANT GetInput();及void SetOutput(const VARIANT& newValue);都要使用VARIANT類型。首先由函數(shù)GetInBufferCount()檢查串口接收到的字符數(shù),然后由GetInput()函數(shù)讀取這些已接收的字節(jié)。用SetOutput函數(shù)將數(shù)據(jù)從串口發(fā)送出去。
3?利用VC++運行時庫的標準通信函數(shù)實現(xiàn)串口編程
利用C進行異步通信編程,其實是對UART內(nèi)部寄存器的讀出或?qū)懭氩僮鳌C可利用VC++類庫中提供的標準通信函數(shù)-inp()/-outp()函數(shù)對其進行編程,它們的端口地址列于下表。
通過計算機串口進行串行通信之前,必須根據(jù)設(shè)備的有關(guān)通信參數(shù),約定雙方的通信方式,包括波特率的設(shè)置、奇偶位校驗及停止位的設(shè)立,確定數(shù)據(jù)傳輸幀格式和UART操作方式,逐個對線路控制寄存器、波特率因子寄存器等寄存器寫入操作,可以利用VC運行庫提供的通信函數(shù)_inp,_outp來實現(xiàn)串口通信。
具體的實現(xiàn)步驟為:
確定計算機的通信口地址。假定計算機的通信口地址是2F8,則PORT=0x2F8;利用_outp(PORT,0x60)將波特率設(shè)置為2400,數(shù)據(jù)傳輸格式則由地址PORT+3確定,如選用七位-停止位偶校驗,則采用outp(PORT+3,0x3a)及outp(PORT+3,0x03)兩個語句。
計算機通過串行通信口與外設(shè)進行數(shù)據(jù)傳輸和控制時,首先要對端口的狀態(tài)進行檢測,然后通過UART芯片把傳送來的數(shù)字信號轉(zhuǎn)換為模擬信號,數(shù)據(jù)經(jīng)過移位寄存器將并行的以字節(jié)為單位的數(shù)據(jù)以位為單位串行發(fā)送到串行通信端口,當數(shù)據(jù)到達串行通信端口時,按照RS-232通信協(xié)議規(guī)定傳送數(shù)據(jù)至外設(shè)。這就是主機進行串行通信從而實現(xiàn)控制外設(shè)的整個過程。反之,當主機獲取外設(shè)當前狀態(tài)和相關(guān)數(shù)據(jù),或者外設(shè)向主機回送數(shù)據(jù)時,端口檢測到有數(shù)據(jù)信號,則通過RS-232總線協(xié)議傳送信號至UART芯片,UART芯片把傳送來的模擬信號轉(zhuǎn)換為數(shù)字信號,數(shù)據(jù)經(jīng)過移位寄存器將串行數(shù)據(jù)合為并行數(shù)據(jù),送至CPU進行處理。只要CPU檢測到UART發(fā)送器保持寄存器為空,即向UART輸出一個字符。發(fā)送方首先輸出RTS和DTR有效,檢測MODEM寄存器,只有收到DEC輸入的CTS和DTR有效,CPU才向UART輸出一發(fā)送字符。
只要CPU檢測到UART接收器數(shù)據(jù)準備就緒,就可以從接收器的數(shù)據(jù)寄存器重讀取一個字符。接收方首先輸出數(shù)據(jù)終端就緒(DTR=1),然后檢測MODEM狀態(tài)寄存器,只有DSR=1,CPU才接收字符。
結(jié)論:VC++是一個非常優(yōu)秀的用戶平臺,提供了多種方法對串口進行通信控制,使用戶不必了解具體的硬件原理,簡化了編程,使程序透明化,并且適應(yīng)性好,可移植性高。以上三種實現(xiàn)串口通信的方法是筆者經(jīng)過長期具體工程實踐總結(jié)出來的。經(jīng)過比較,筆者認為:采用MFC串口通信編程是最靈活、最常用并且功能強大的方法,適用于與各種不同的外設(shè)進行串行通信,但需要程序員對硬件工作原理有較深入的了解;ActiveX控件編程容易實現(xiàn),不需要處理煩瑣的細節(jié),但是靈活性較差;利用VC運行時庫的標準通信函數(shù)實現(xiàn)串口編程原理簡單,不足之處是實用性和靈活性較差。因此,在具體實踐中要結(jié)合功能需要,綜合考慮復(fù)雜程度、靈活性等因素,選擇合適的方法,實現(xiàn)串口通信。
總結(jié)
以上是生活随笔為你收集整理的基于VC++开发串口通信的方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 得力条码扫描器怎么用_广东智能物流控制系
- 下一篇: 获取元素大小和位置的方式