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