在
C++ Builder
中利用串行通信控件編程
轉(zhuǎn)發(fā)別人的文章,閱讀時可以使用IE的,查看--字體大小--最大;這樣可以看到大字體的文章。
?
摘要:串口是常用的計算機(jī)與外部串行設(shè)備之間的數(shù)據(jù)傳輸通道,由于串行通信方便易行,所以應(yīng)用廣泛。本文介紹了在
C++ Builder
中如何利用串行通信控件進(jìn)行串行通信編程。
?
一、引言
目前,在用計算機(jī)進(jìn)行數(shù)據(jù)傳輸時,常用的是串行通信方式。用
C
++
Builder
來編寫串行通信程序時,可以調(diào)用
Windows API
函數(shù),也可以利用
VB
中的
MSComm
控件。
利用
API
函數(shù)編寫實際應(yīng)用程序時,往往要考慮多線程的問題,這樣編出來的程序不但十分龐大,而且結(jié)構(gòu)比較復(fù)雜,繼承性差,維護(hù)困難。但是使用串行通信控件就相對簡單一些,而且功能強(qiáng)大,性能安全可靠。本文就簡單的介紹一下在
C++ Builder
中利用
MSComm
控件進(jìn)行編程。
二、
MSComm
控件的常用屬性和事件
MSComm
控件通過串行端口傳輸和接收數(shù)據(jù),為應(yīng)用程序提供串行通訊功能。具體的來說,它提供了兩種處理通信問題的方法:一是事件驅(qū)動
(Event
-
driven)
方法,一是查詢法。
事件驅(qū)動方式
在使用事件驅(qū)動法設(shè)計程序時,每當(dāng)有新字符到達(dá),或端口狀態(tài)改變,或發(fā)生錯誤時,
MSComm
控件將解發(fā)
OnComm
事件,而應(yīng)用程序在捕獲該事件后,通過檢查
MSComm
控件的
CommEvent
屬性可以獲知所發(fā)生的事件或錯誤,從而采取相應(yīng)的操作。這種方法的優(yōu)點(diǎn)是程序響應(yīng)及時,可靠性高。
查詢方式
查詢方式實質(zhì)上還是事件驅(qū)動,但在有些情況下,這種方式顯得更為便捷。在程序的每個關(guān)鍵功能之后,可以通過檢查
CommEvent
屬性的值來查詢事件和錯誤。如果應(yīng)用程序較小,并且是自保持的,這種方法可能是更可取的。
1.MSComm
控件的常用屬性
CommPort
屬性:設(shè)置或返回通訊端口號,可以設(shè)置為
1
到
16
之間的任何值,本系統(tǒng)采用缺省值
2
;
Settings
屬性:以字符串形式設(shè)置或返回波特率、奇偶校驗、數(shù)據(jù)位和停止位,本系統(tǒng)采用缺省值
"9600
,
n
,
8
,
1";
PortOpen
屬性:設(shè)置或返回通訊口的狀態(tài)以及打開和關(guān)閉端口,可通過把該屬性設(shè)置為
true
或者
false
來打開或者關(guān)閉端口;
InBufferSize
和
OutBufferSize
屬性:分別設(shè)置接收和發(fā)送緩沖區(qū)分配的內(nèi)存數(shù)量,單位為字節(jié),缺省值分別為
1024byte
和
512byte
;
InputLen
屬性:確定希望從接收緩沖區(qū)移出的字符數(shù)量,當(dāng)
InputLen
=
0
時,一次把接收緩沖區(qū)的字符全部移出;
Input
屬性:從接收緩沖區(qū)中讀出數(shù)據(jù),然后將該數(shù)據(jù)從緩沖區(qū)移走。
OutPut
屬性:向發(fā)送緩沖區(qū)傳遞待發(fā)送的數(shù)據(jù)。
InBufferCount
和
OutBufferCount
屬性:分別確定當(dāng)前駐留在接收緩沖區(qū)等待被取出和發(fā)送緩沖區(qū)準(zhǔn)備發(fā)送的字符數(shù)量,這兩個屬性設(shè)置為
0
,接收和發(fā)送緩沖區(qū)的內(nèi)容將被清除;
InputMode
屬性:設(shè)置接收傳入數(shù)據(jù)的格式,設(shè)置為
0
采用文本形式,設(shè)置為
1
采用二進(jìn)制格式,本系統(tǒng)設(shè)置為二進(jìn)制格式進(jìn)行發(fā)送和接收;
SThreshold
屬性:保存一個產(chǎn)生發(fā)送
OnComm
事件的界限值,本系統(tǒng)設(shè)置該屬性為
0
,發(fā)送數(shù)據(jù)時不產(chǎn)生
OnComm
事件;
RThreshold
屬性:設(shè)定當(dāng)接收幾個字符時觸發(fā)
OnComm
事件,本系統(tǒng)設(shè)置該屬性為
1
,每接收一個字符就產(chǎn)生一個
OnComm
事件;
2
.
MSComm
控件的事件
MSCOMM
控件只使用一個事件
OnComm
,用屬性
CommEvent
的十七個值來區(qū)分不同的觸發(fā)時機(jī)。主要有以下幾個:
(1)CommEvent=1
時:傳輸緩沖區(qū)中的字符個數(shù)已少于
Sthreshold(
可設(shè)置的屬性值
)
個。
(2)CommEvent=2
時:接收緩沖區(qū)中收到
Rthreshold(
可設(shè)置的屬性值
)
個字符,利用此事件可編寫接收數(shù)據(jù)的過程。
(3)CommEvent=3
時:
CTS
線發(fā)生變化。
(4)CommEvent=4
時:
DSR
線發(fā)生變化。
(5)CommEvent=5
時:
CD
線發(fā)生變化。
(6)CommEvent=6
時:檢測到振鈴信號。
另外十種情況是通信錯誤時產(chǎn)生,即錯誤代碼。
?
三、程序的實現(xiàn)
1.
注冊
MSComm
控件
眾所周知,
C++Builder
本身并不提供串行通訊控件
MSComm
,但我們卻可以通過注冊后直接使用它。啟動
C++Builder5.0
后,然后選擇
C++Builder
主菜單中的
Component
菜單項,單擊
Import Active Control
命令,彈出
Import Active
窗口,選擇
Microsoft Comm Control6.0
,再選擇
Install
按鈕執(zhí)行安裝命令
,
系統(tǒng)將自動進(jìn)行編譯
,
編譯完成后即完成
MSComm
控件在
C++Builder
中的注冊
,
系統(tǒng)默認(rèn)安裝在控件板的
Active
頁
,
接下來我們就可以像使用
C++Builder
本身提供的控件那樣使用新注冊的
MSComm
控件了。(前提條件是你的機(jī)子上安裝了
Visual Basic
,或者有它的庫)
2.
具體實現(xiàn)
新建一個工程
Project1
,把注冊好的
MSComm
控件加入到窗體中,然后再加入
5
個
ComboBox
用來設(shè)置串口的屬性,
4
個
Button
分別用來
"
打開串口
" "
關(guān)閉串口
""
發(fā)送數(shù)據(jù)
""
保存數(shù)據(jù)
"
,
2
個
Memo
控件分別用來顯示接收到的數(shù)據(jù)和發(fā)送的數(shù)據(jù)。再加入一個
Shape
控件用來標(biāo)明串口是否打開。
ComboBox1
用來設(shè)置串口號,通過它的
Items
屬性設(shè)置
1
,
2
,
3
,
4
四個列表項分別表示
COM1,COM2,COM3,COM4
口。
ComboBox2
用來設(shè)置波特率,
ComboBox3
用來設(shè)置奇偶校驗位,
ComboBox4
用來設(shè)置數(shù)據(jù)位,
ComboBox5
用來設(shè)置停止位。他們的缺省值分別是
9600
,
n
,
8
,
1
。
Button1
用來打開串口,
Button2
用來關(guān)閉串口,
Button3
用來發(fā)送數(shù)據(jù),
Button4
用來保存數(shù)據(jù)。
Memo1
用來顯示發(fā)送的數(shù)據(jù),
Memo2
顯示接收的數(shù)據(jù)。
Shape1
的
Shape
屬性設(shè)置為
stCircle
。
下面給出部分源碼:
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{?
??????if(MSComm1->PortOpen==true)?
??????{?
????????????Button1->Enabled=false;?
????????????Button2->Enabled=true;?
????????????Button3->Enabled=true;?
????????????Button4->Enabled=true;?
????????????Shape1->Brush->Color=clGreen;
??????}
??????else
??????{?
????????????Button2->Enabled=true;?
????????????Button2->Enabled=false;?
????????????Button3->Enabled=false;?
????????????Button4->Enabled=false;?
????????????Shape1->Brush->Color=clRed;
??????}
}
void __fastcall TForm1::Button1Click(TObject *Sender) / /
打開串口
{?
??????if(MSComm1->PortOpen!=true)?
??????{?
????????????MSComm1->CommPort=StrToInt(ComboBox1->Text);//
選擇串口號?
????????????MSComm1->Settings=?
??????????????????ComboBox2->Text+","+?
??????????????????ComboBox3->Text+","+?
??????????????????ComboBox4->Text+","+?
??????????????????ComboBox5->Text; file://
設(shè)置串口的屬性波特率、奇偶校驗、數(shù)據(jù)位和、
//
停止位。?
????????????MSComm1->InputMode=0;//
設(shè)置傳入數(shù)據(jù)的格式,
0
表示文本形式?
????????????MSComm1->PortOpen=true;//
打開串口?
????????????Button1->Enabled=false;?
????????????Button2->Enabled=true;?
????????????Button3->Enabled=true;?
????????????Button4->Enabled=true;?
????????????Shape1->Brush->Color=clGreen;?
??????}
}
void __fastcall TForm1::Button2Click(TObject *Sender) / /
關(guān)閉串口
{?
??????if(MSComm1->PortOpen!=false)?
??????{?
????????????MSComm1->PortOpen=false;?
????????????Button1->Enabled=true;?
????????????Button2->Enabled=false;?
????????????Button3->Enabled=false;?
????????????Button4->Enabled=false;?
????????????Shape1->Brush->Color=clRed;?
??????}?
??????else?
??????{?
????????????Button1->Enabled=false;?
????????????Button2->Enabled=true;?
????????????Shape1->Brush->Color=clRed;?
??????}
}
MSComm
控件的
Input
和
Output
屬性在
Object Inspector
中是看不到的,而且在
C++Builder
環(huán)境下這兩個屬性已不在是
VB
、
VC
中的原類型,而是
OleVariant
類型,也就是
Ole
萬能變量,這就需要我們在發(fā)送接收數(shù)據(jù)時要把數(shù)據(jù)轉(zhuǎn)換成
Ole
類型。
void __fastcall TForm1::Button3Click(TObject *Sender) file://
發(fā)送
Memo2
中的數(shù)據(jù)
{?
??????MSComm1->Output=StringToOleStr(Memo2->Text); file://
把
AnsiString
型轉(zhuǎn)化成
//Ole
形式。
}
通過
OnComm
事件接收數(shù)據(jù),必須把
MSComm
的
RThreshold
屬性設(shè)置為大于
0
,只有這樣在接收到字符時才會產(chǎn)生一個
OnComm
事件。
void __fastcall TForm1::MSComm1Comm(TObject *Sender)
{?
??????AnsiString str; file://
聲明一個
AnsiString
類型的變量?
??????OleVariant s; file://
聲明一個用于接收數(shù)據(jù)的
OleVariant
變量。?
??????if(MSComm1->CommEvent==comEvReceive)?
??????//
接收緩沖區(qū)中是否收到
Rthreshold
個字符。?
??????{?
????????????if(MSComm1->InBufferCount)//
是否有字符駐留在接收緩沖區(qū)等待被取出?
????????????{?
??????????????????s=MSComm1->Input;//
接收數(shù)據(jù)?
??????????????????str=s.AsType(varString); file://
把接收到的
OleVariant
變量轉(zhuǎn)換成
AnsiString
類型?
??????????????????Memo1->Text=Memo1->Text+str;//
把接收到的數(shù)據(jù)顯示在
Memo1
中。?
????????????}?
??????}
}
要保存數(shù)據(jù)應(yīng)該再加入一個
SaveDialog
模塊
void __fastcall TForm1::Button4Click(TObject *Sender)
file://
把
Memo1
中的數(shù)據(jù)保存在指定的文件中
{?
??????AnsiString filename1;?
??????SaveDialog1->Filter="Text files (*.txt)|*.txt|All files (*.*)|*.*";//
文件類型過濾器?
??????SaveDialog1->FilterIndex=2;?
??????if(SaveDialog1->Execute())?
??????{?
????????????filename1=SaveDialog1->FileName;?
????????????Memo1->Lines->SaveToFile(filename1);//
把收到的數(shù)據(jù)保存在文件
filename1
中?
??????}
}
四、結(jié)束語
上面給出了
C++ Builder
中利用
MSComm
控件進(jìn)行串行通信編程的實現(xiàn)和部分源碼,有了上面的參照讀者可以根據(jù)實際需要編寫出具有發(fā)送文件和接收文件功能的程序。
?
posted on 2006-07-05 16:22
石正 閱讀(1299)
評論(1) 編輯 收藏