著作權資訊:
本文來自internet,轉載這裡供網路編程愛好者學習和研究使用,請尊重作者的勞動成果。未經授權而在商業上使用原作者的文章屬侵權行為,後果由使用者自負,本人不承擔任何法律責任
串口通訊方法:
(1)利用Windows API通訊函數;(2)利用Visual C++的標準通訊函數_inp、_inpw、_inpd、_outp、_outpw、_outpd等直接對串口進行操作;(3)通過Microsoft Visual C++的通訊控制項(MSComm);(4)利用第3方編寫的通訊類,比如MuMega Technologies公司提供的CSerail類。
採用微軟MSComm控制項編程:
ON_EVENT(CModemConnetDlg, ID_COMMCTRL, 1, OnCommMscomm, VTS_NONE)
MSComm控制項什麼時候觸發訊息函數?
通過 m_Comm.SetRThreshold(1); //為1表示有一個字元引發一個事件
只要串口接收到資料就觸發OnCommMscomm訊息函數。
MSComm 控制項的 Modem 通訊
MSComm 控制項通過序列埠(serial port)傳送和接收資料,為應用程式提供了串列通訊功能。而且在可視化編程盛行的今天,可以很方便的在Visual Basic(VB)、Visual C++(VC)、Delphi等語言及開發平台中應用。
MSComm 是 Microsoft 公司為簡化Windows下序列埠編程而提供的ActiveX控制項,它提供了一系列標準通訊命令的使用介面,為應用程式提供了通過串列口收發資料的簡潔方法。處理資料的方式有事件驅動(Event-driver)、查詢法(Inquire)兩種。
1.事件驅動法
在使用事件驅動法設計程式時,每當有新字元到達、連接埠狀態變化或發生錯誤時,MSComm控制項將解發OnComm事件,而應用程式在捕獲該事件後,通過檢查MSComm控制項的CommEvent屬性可以獲知所發生的事件或錯誤,從而採取相應的操作。這種方法的優點是程式響應及時,可靠性高。
2.查詢法
這種方法適合於較小的應用程式。在這種情況下,每當應用程式執行完某一串列口操作後,將不斷檢查MSComm控制項的CommEvent屬性以檢查執行結果或者檢查某一事件是否發生。例如,當程式向串列裝置發送了某個命令後,可能只是在等待收到一個特定的響應字串,而不是對收到的每一個字元都立刻響應並處理。
在VC中添加?MSComm控制項非常簡單。在開啟的工程中,選擇菜單Project->Add To Project->Component and Controls,在彈出的對話方塊“Component and Controls Gallery”中選中“Microsoft Communication Controls Version 6.0”,單擊“Insert”按鈕即可完成添加MSComm控制項操作。
本工程應用採用事件驅動法,具體實現如下:
一.串口資訊配置
按上述方法完成在基於對話方塊的應用程式中添加MSComm控制項操作並增加相應成員變數m_comm。在對話方塊模板上按右鍵MSComm控制項,選擇Property功能表項目,即可設定MSComm控制項各項屬性。在此數據機通訊的程式中,設定“Control”屬性頁面中Handshaking項為“2-comRTS”,否則國內部分廠家modem不能正常通訊。其它接受預設設定。
另外亦可通過修改對話方塊類的OnInitDialog()函數來設定控制項的屬性。具體參考MSDN中的關於Comm Control的詳細說明。
if(m_comm.GetPortOpen())
{
m_comm.SetPortOpen(FALSE); //設定串口配置資訊前先要關閉串口
}
m_comm.SetCommPort(1); //Com1串列口
m_comm.SetSettings("9600,n,8,1");//設定傳輸速率為9600bps,無同位位元,資料位元8位,停止位1位
m_comm.SetInputMode(1); //設定資料通訊格式為位元組格式
m_comm.SetRThreshold(1); //設定為每次接到一個位元組資料就觸發OnComm事件
if(!m_comm.GetPortOpen())
{
m_comm.SetPortOpen(TRUE);
}
m_comm.GetInput(); //清除串口輸入緩衝區中殘留資料
m_SendData="ATZ/r/n"; //數據機初始化
m_comm.SetOutput(COleVariant(m_SendData));
二.接收資料
添加接收資料函數,在對話方塊中雙擊Comm Control,接受預設函數,則對話方塊類的成員函數為OnCommMscomm(),添加代碼如下:
Sleep(500); //視各廠家modem而定。不加則資料接受不全
VARIANT m_input;
char *str,*str1;
int k,nEvent,i,len,m;
CString str2;
m_ReceiveData="";
nEvent=m_comm.GetCommEvent();
switch(nEvent)
{
case 2: //收到大於RTHresshold個字元
k=m_comm.GetInBufferCount(); //接收緩衝區的字元數目
if(k>0)
{
m_input=m_comm.GetInput();
str=(char*)(unsigned char*)m_input.parray->pvData;
}
?i=0;
str1=str;
while(i 以上是在做工程之餘寫下的一點東西。VC我是初學者,有錯誤的地方,還請各位批評指正。例子在VC 6.0+Win2000下調試通過。Win98下測試資料接收不全。
(2)mscomm控制項串口通訊
摘要:串口是常用的電腦與外部串列裝置之間的資料轉送通道,由於串列通訊方便易行,所以應用廣泛。本文介紹了在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控制項進行串列通訊編程的實現和部分源碼,有了上面的參照讀者可以根據實際需要編寫出具有傳送檔案和接收檔案功能的程式。