廣告廣告
  加入我的最愛 設為首頁 風格修改
首頁 首尾
 手機版   訂閱   地圖  簡體 
您是第 13174 個閱讀者
 
發表文章 發表投票 回覆文章
  可列印版   加為IE收藏   收藏主題   上一主題 | 下一主題   
ziele 手機
個人文章 個人相簿 個人日記 個人地圖
初露鋒芒
級別: 初露鋒芒 該用戶目前不上站
推文 x1 鮮花 x32
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片
推文 x0
[C/C++] -問題- 如何控制通訊埠 ??
想要用c / c++ 來寫通訊 ..

訪客只能看到部份內容,免費 加入會員 或由臉書 Google 可以看到全部內容



獻花 x0 回到頂端 [樓 主] From:台灣中華電信 | Posted:2005-09-09 15:52 |
codeboy 手機
個人文章 個人相簿 個人日記 個人地圖
社區建設獎
小有名氣
級別: 小有名氣 該用戶目前不上站
推文 x6 鮮花 x331
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

MSDN應該有相關的資訊可以參考~要不要去查一下 表情



連結有問題請來信,我會盡快修正~^^
通報時請附上是"哪一篇失效"...這樣我才能去修正~麻煩各位好心人士了~

[連結失效通報][ 網頁.伺服.程式 討論區]
----------------------在世界中心呼喊愛情----------------------
深深思念一個人的時候,我們不知不覺的地活在世界的中心...
獻花 x0 回到頂端 [1 樓] From:台灣政府網際 | Posted:2005-09-12 11:43 |
夷希微
個人頭像
個人文章 個人相簿 個人日記 個人地圖
社區建設獎
知名人士
級別: 知名人士 該用戶目前不上站
推文 x13 鮮花 x1682
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

請問您指的通訊埠是 RS-232 嗎?
是的話~請參考以下的資料吧 ^_^

Subject: 在Win32[BCB]下用Serial Port通訊的範例

發信人: vega6385.bbs@cszone.twbbs.org (simayi), 信區: programming
標 題: 在Win32[BCB]下用Serial Port通訊的範例
發信站: 程式設計樂園(CSZone) (Thu Jul 27 21:16:13 2000)
轉信站: cis_nctu!news.cis.nctu!freebsd.ntu!news.ntu!CSZone
來 源: octa2.ee.ntu.edu.tw

在Win32[BCB]下用Serial Port通訊的範例
///////////////////////////////////////////////
下列的程式示範了如何在Win32下
用console mode做Serial Port通訊
關於與之通訊的硬體,請參考松崗
出版的"單晶片8051實務<增修版>"
一書,作者:吳一農,ISBN:957-22-3242-8
硬體線路及8051ASM CODE.請參照
書中第16章的部份.本程式能完全取代
16-19頁中的Qbasic程式,達到雙向傳輸的功用.
本程式在BCB5中能順利編譯執行!!


#include <windows.h>
#include <stdio.h>
#include <conio.h>
int main(int argc, char* argv[])
{
HANDLE com2_handle ; //RS-232的Com2的handle
DCB dcb ; //設定傳輸參數所需之結構
char buffer[10]; //讀取資料所需的緩衝區

DWORD read_bytes = 1 ; //每次讀取的byte數

com2_handle = CreateFile( "COM2" ,GENERIC_READ|GENERIC_WRITE ,
0, NULL ,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
//開啟com2,設為一般讀取寫入,一般屬性,不使用非同步IO

BuildCommDCB( "baud=4800 parity=N data=8 stop=2", &dcb );
//設定傳輸參數結構的內含值:鮑率:4800,無同位檢查,資料位元8,停止位元2

SetCommState( com2_handle , &dcb );
//設定傳輸參數

COMMTIMEOUTS time_out ; //設定讀寫逾時參數的結構
time_out.ReadIntervalTimeout = MAXDWORD ;
//設為MAXDWORD:如果沒有資料供讀取,ReadFile函式將立即返回
time_out.ReadTotalTimeoutMultiplier = 0 ;
time_out.ReadTotalTimeoutConstant = 0 ;
//不使用讀取總和時間來判斷是否讀取逾時
time_out.WriteTotalTimeoutMultiplier = 5 ;
time_out.WriteTotalTimeoutConstant = 50 ;
//使用寫入總和時間來判斷是否寫入逾時,逾時WriteFile函式將立即返回

SetCommTimeouts( com2_handle , &time_out ) ;
//設定com2讀寫逾時返回

printf("請撥動switch然後接收 或 按數字鍵0~9傳輸 或 可以按X結束\n");

while( 1 )
{

ReadFile( com2_handle , buffer , read_bytes ,&read_bytes ,NULL); //由com2讀取1byte

//因為ReadFile函式逾時的時候,不僅沒讀到資料(所以buffer[0]沒變動)就返回,
//還會把read_bytes內含值改為0,因此read_bytes!= 0時表示有讀到資料

if(read_bytes!= 0)
{
//下面這一段顯示四個switch的狀態,用1與0表示ON/OFF
//方法是有點拙,我也知道用<<和>>很快,可是實作時出了點狀況,所以用這個拙方法
int sw1,sw2,sw3,sw4 ;
sw1 = (0-buffer[0]-113) / 8 ;
sw2 = ((0-buffer[0]-113)- (sw1 * 8)) / 4 ;
sw3 = ((0-buffer[0]-113)-(sw1*8)-(sw2*4)) / 2 ;
sw4 = ((0-buffer[0]-113)-(sw1*8)-(sw2*4)-(sw3*2)) / 1 ;
printf("由COM2得到Switch狀態 %d%d%d%d \n", sw1,sw2,sw3,sw4);
printf("可以按X結束\n");

}
else
{
read_bytes = 1 ;
//因為ReadFile函式逾時的時候,不僅沒讀到資料(所以buffer[0]沒變動)就返回,
//還會把read_bytes內含值改為0,所以我們要設回初值,不然下一輪會讀不到資料
//(因為內函值為0,表示要讀取0byte,所以讀不到資料)
}

if( kbhit() != 0 ) //如果鍵盤有被按到,kbhit函式傳回值不等於0
{
int key ; //存放被按的鍵的鍵值
key = getch() ; //把被鍵值讀出來
if( key == 'x' )
{
break ; //按下小寫x結束本程式
}
else
{
switch( key ) //如果輸入數字鍵0~9,將之傳給8051實習板顯示出來
{
case Ɔ' : WriteFile( com2_handle , &key , read_bytes ,
&read_bytes ,NULL );
printf("傳送%c到UART的另一端\n",key);
printf("可以按X結束\n");
break ;
case Ƈ' : WriteFile( com2_handle , &key , read_bytes ,
&read_bytes ,NULL );
printf("傳送%c到UART的另一端\n",key);
printf("可以按X結束\n");
break ;
case ƈ' : WriteFile( com2_handle , &key , read_bytes ,
&read_bytes ,NULL );
printf("傳送%c到UART的另一端\n",key);
printf("可以按X結束\n");
break ;
case Ɖ' : WriteFile( com2_handle , &key , read_bytes ,
&read_bytes ,NULL );
printf("傳送%c到UART的另一端\n",key);
printf("可以按X結束\n");
break ;
case Ɗ' : WriteFile( com2_handle , &key , read_bytes ,
&read_bytes ,NULL );
printf("傳送%c到UART的另一端\n",key);
printf("可以按X結束\n");
break ;
case Ƌ' : WriteFile( com2_handle , &key , read_bytes ,
&read_bytes ,NULL );
printf("傳送%c到UART的另一端\n",key);
printf("可以按X結束\n");
break ;
case ƌ' : WriteFile( com2_handle , &key , read_bytes ,
&read_bytes ,NULL );
printf("傳送%c到UART的另一端\n",key);
printf("可以按X結束\n");
break ;
case ƍ' : WriteFile( com2_handle , &key , read_bytes ,
&read_bytes ,NULL );
printf("傳送%c到UART的另一端\n",key);
printf("可以按X結束\n");
break ;
case Ǝ' : WriteFile( com2_handle , &key , read_bytes ,
&read_bytes ,NULL );
printf("傳送%c到UART的另一端\n",key);
printf("可以按X結束\n");
break ;
case Ə' : WriteFile( com2_handle , &key , read_bytes ,
&read_bytes ,NULL );
printf("傳送%c到UART的另一端\n",key);
printf("可以按X結束\n");
break ;
default: break ;
}

}
}

}

CloseHandle( com2_handle ); //關閉com2
return 0;

}
///////////////////////////////////
改寫成BCB的版本如下
///////////////////////////////////
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "uart_GUI_cpp.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
#include <stdio.h>
TForm1 *Form1;
HANDLE com2_handle ; //RS-232的Com2的handle
DCB dcb ; //設定傳輸參數所需之結構
char buffer[10]; //讀取資料所需的緩衝區
DWORD read_bytes = 1 ; //每次讀取的byte數
COMMTIMEOUTS time_out ; //設定讀寫逾時參數的結構
int key ; //存放被按的鍵的鍵值
char temp_string[256];
char temp_string2[256];

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormResize(TObject *Sender)
{
Width = 435 ;
Height = 300 ;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button11Click(TObject *Sender)
{
Form1->Close();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{

com2_handle = CreateFile( "COM2" ,GENERIC_READ|GENERIC_WRITE ,
0, NULL ,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
//開啟com2,設為一般讀取寫入,一般屬性,不使用非同步IO

BuildCommDCB( "baud=4800 parity=N data=8 stop=2", &dcb );
//設定傳輸參數結構的內含值:鮑率:4800,無同位檢查,資料位元8,停止位元2

SetCommState( com2_handle , &dcb );
//設定傳輸參數

time_out.ReadIntervalTimeout = MAXDWORD ;
//設為MAXDWORD:如果沒有資料供讀取,ReadFile函式將立即返回
time_out.ReadTotalTimeoutMultiplier = 0 ;
time_out.ReadTotalTimeoutConstant = 0 ;
//不使用讀取總和時間來判斷是否讀取逾時
time_out.WriteTotalTimeoutMultiplier = 5 ;
time_out.WriteTotalTimeoutConstant = 50 ;
//使用寫入總和時間來判斷是否寫入逾時,逾時WriteFile函式將立即返回

SetCommTimeouts( com2_handle , &time_out ) ;
//設定com2讀寫逾時返回
Memo1->Clear();
Memo2->Clear();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
key = Ƈ'
sprintf(temp_string,"%c",key);
Memo1->Clear();
Memo1->SetSelTextBuf(temp_string);
WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL );
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)
{
key = ƈ'
sprintf(temp_string,"%c",key);
Memo1->Clear();
Memo1->SetSelTextBuf(temp_string);
WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL );
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button10Click(TObject *Sender)
{
key = Ɔ'
sprintf(temp_string,"%c",key);
Memo1->Clear();
Memo1->SetSelTextBuf(temp_string);
WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL );
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender)
{
key = Ɖ'
sprintf(temp_string,"%c",key);
Memo1->Clear();
Memo1->SetSelTextBuf(temp_string);
WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL );
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button4Click(TObject *Sender)
{
key = Ɗ'
sprintf(temp_string,"%c",key);
Memo1->Clear();
Memo1->SetSelTextBuf(temp_string);
WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL );
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button5Click(TObject *Sender)
{
key = Ƌ'
sprintf(temp_string,"%c",key);
Memo1->Clear();
Memo1->SetSelTextBuf(temp_string);
WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL );
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button6Click(TObject *Sender)
{
key = ƌ'
sprintf(temp_string,"%c",key);
Memo1->Clear();
Memo1->SetSelTextBuf(temp_string);
WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL );
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button7Click(TObject *Sender)
{
key = ƍ'
sprintf(temp_string,"%c",key);
Memo1->Clear();
Memo1->SetSelTextBuf(temp_string);
WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL );
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button8Click(TObject *Sender)
{
key = Ǝ'
sprintf(temp_string,"%c",key);
Memo1->Clear();
Memo1->SetSelTextBuf(temp_string);
WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL );
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button9Click(TObject *Sender)
{
key = Ə'
sprintf(temp_string,"%c",key);
Memo1->Clear();
Memo1->SetSelTextBuf(temp_string);
WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL );
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
CloseHandle( com2_handle );
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Timer1->Enabled = false;

ReadFile( com2_handle , buffer , read_bytes ,&read_bytes ,NULL); //由com2讀取1byte

if(read_bytes!= 0)
{
//下面這一段顯示四個switch的狀態,用1與0表示ON/OFF
//方法是有點拙,我也知道用<<和>>很快,可是實作時出了點狀況,所以用這個拙方法
int sw1,sw2,sw3,sw4 ;
sw1 = ((0-buffer[0]-113) & 8)/8 ;
sw2 = ((0-buffer[0]-113) & 4)/4 ;
sw3 = ((0-buffer[0]-113) & 2)/2 ;
sw4 = ((0-buffer[0]-113) & 1)/1 ;
sprintf(temp_string2,"由COM2得到Switch狀態 %d%d%d%d \n", sw1,sw2,sw3,sw4);

Memo2->Clear();
Memo2->SetSelTextBuf(temp_string2);
while(read_bytes!= 0)//把緩衝區資料全讀完才跳出
{
ReadFile( com2_handle , buffer , read_bytes ,&read_bytes ,NULL); //由com2讀取1byte
sw1 = ((0-buffer[0]-113) & 8)/8 ;
sw2 = ((0-buffer[0]-113) & 4)/4 ;
sw3 = ((0-buffer[0]-113) & 2)/2 ;
sw4 = ((0-buffer[0]-113) & 1)/1 ;
sprintf(temp_string2,"由COM2得到Switch狀態 %d%d%d%d \n", sw1,sw2,sw3,sw4);

Memo2->Clear();
Memo2->SetSelTextBuf(temp_string2);
}
read_bytes = 1 ;
//因為ReadFile函式逾時的時候,不僅沒讀到資料(所以buffer[]沒變動)就返回,
//還會把read_bytes內含值改為0,所以我們要設回初值,不然下一輪會讀不到資料
//(因為內函值為0,表示要讀取0byte,所以讀不到資料)
}
else
{
read_bytes = 1 ;
//因為ReadFile函式逾時的時候,不僅沒讀到資料(所以buffer[]沒變動)就返回,
//還會把read_bytes內含值改為0,所以我們要設回初值,不然下一輪會讀不到資料
//(因為內函值為0,表示要讀取0byte,所以讀不到資料)
}

Timer1->Enabled = true;
}
//---------------------------------------------------------------------------


*********************************************
* Simayi司馬仲達 simayi@kimo.com.tw ? *
* CICQ : 663287 ICQ : 49827636 *
* 歡迎大家一起討論程式設計的問題 *
* C/C++ OWL ASM QB都可以討論喔!! *
*********************************************

--
※ Origin: 程式設計樂園 ◆ From: h117.s170.ts32.hinet.net

另一版本的參考資料如下:
如何使用 Win32 API 存取 RS232
作者 : 鄭旭崇

§前言
  以往我們在 DOS 作業系統的真實模式下,想要存取 Serial port 可說是件輕而易舉的事,
我們可以透過 BIOS 提供的中斷服務常式(ISR)對 Serial port 進行存取,或者直接
經由 I/O Port規化 UART 晶片,達到串列通訊的目的.而今在 Windows 作業系統的保
護模式下,欲直接存取 I/O Port 卻不是那麼簡單,而且如果要從低階 I/O 來控制
Serial port 的話,又會涉及到硬體中斷(interrupt)的問題,我們都知道在 Windows
下處理硬體中斷也是相當麻煩的.幸好 Windows API 提供了一套通訊函式(Communication Functions)
可以專門用來解決串列通訊的問題.關於 Communication Functions 總共有二十幾個,
但實際上如果只想做單純的傳送及接收的話,只須用到五個 Communication Functions.
也就是說,讀者只要學會使用這幾個 Communication Functions 那麼關於串列通訊的問題
便可迎刃而解了.
§Win32 API Communication Functions 說明
以下茲對相關的 Win32 API Communication Functions 作簡短的介紹.
1.BuildCommDCB
函數原型: BOOL BuildCommDCB( LPCTSTR lpDef, LPDCB lpDCB ).
BuildCommDCB 函數是用來填寫 DCB 的資料,何謂 DCB 呢? DCB 的全名為 Device Control Block
是一資料結構,裡面定義著所有有關串列通訊(Serial Communication)的設定值,DCB 資料結構定義如下:
typedef struct _DCB {  
  DWORD DCBlength;       // DCB 的大小 (in byte)
  DWORD BaudRate;         // 傳輸率 (baud rate) bit/秒
  DWORD fBinary: 1;       // 二進制模式,沒有 EOF 檢查.
  DWORD fParity: 1;       // 同位元檢查 (parity checking)
  DWORD fOutxCtsFlow:1;     // CTS output flow control
  DWORD fOutxDsrFlow:1;     // DSR output flow control
  DWORD fDtrControl:2;     // DTR flow control type
  DWORD fDsrSensitivity:1;   // DSR sensitivity
  DWORD fTXContinueOnXoff:1; // XOFF continues Tx
  DWORD fOutX: 1;         // XON/XOFF out flow control
  DWORD fInX: 1;         // XON/XOFF in flow control
  DWORD fErrorChar: 1;     // enable error replacement
  DWORD fNull: 1;         // enable null stripping
  DWORD fRtsControl:2;     // RTS flow control
  DWORD fAbortOnError:1;   // abort reads/writes on error
  DWORD fDummy2:17;       // reserved
  WORD wReserved;         // not currently used
  WORD XonLim;           // transmit XON threshold
  WORD XoffLim;         // transmit XOFF threshold
  BYTE ByteSize;         // 每一筆資料的 bit 數, 4-8
  BYTE Parity;           // 同位元 (0-4) = 無,奇同位,偶同位,mark,space
  BYTE StopBits;         // 停止位元 (0,1,2) = 1, 1.5, 2
  char XonChar;         // Tx and Rx XON character
  char XoffChar;         // Tx and Rx XOFF character
  char ErrorChar;         // error replacement character
  char EofChar;         // end of input character
  char EvtChar;         // received event character
  WORD wReserved1;       // reserved; do not use
} DCB;
  這個 DCB Structure 幾乎函蓋了所有有關串列通訊的參數,提供以後使用 SetCommState API 函數
對硬體進行初始化設定.透過 BuildCommDCB 函數,我們可以最簡單的方法來向 DCB Structure
填值,其中 LPCTSTR lpDef 指向一個叫做 device-control string 的位址,而 LPDCB lpDCB
正指向 DCB Structure.我們較感興趣的是 device-control string,它使用設定串列埠的語
法就跟以往 DOS 時代的 Mode 指令一樣,唯一不同的是它的傳輸率 (baud rate)已經不再限
制於 19200 bit/秒以下,並且最高可達 256000 bit/秒.例如:欲設定 COM2 的 Baud = 57600,
沒有同位元,資料 = 8 bit,一個停止位元,可以寫成 BuildCommDCB("19200,n,8,1",&dcb).
若涵數執行成功,將傳回一個非零的值.若執行失敗則傳回零.
2.CreatFile
函數原型:
HANDLE CreateFile(
  LPCTSTR lpFileName,                       // pointer to name of the file
  DWORD dwDesiredAccess,                // access (read-write) mode
  DWORD dwShareMode,                       // share mode
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,      // pointer to security attributes
  DWORD dwCreationDistribution,           // how to create
  DWORD dwFlagsAndAttributes,                 // file attributes
  HANDLE hTemplateFile                 // handle to file with attributes to copy
  );
這個 Windows API 函數在此是用來開啟系統的 Serial Port 並取得一個 HANDLE 代碼.以後想要存取
Serial Port 時,只須面對這個 HANDLE 代碼即可.當然 CreateFile 函數也可以開啟其他類型的檔案,
例如 files,pipes,mailslots 等等,有興趣的朋友可以參考 Borland C++ 或 C++Builder 附加的 Help
file 內皆有詳盡的說明.
  此函數共有七個變數欄位,第一個變數欄位 lpFileName 指向檔案名稱或裝置名稱,要當做串列通
訊時, lpFileName 為 "COM1" 或 "COM2".變數 dwDesiredAccess 設定存取型式.常數 GENERIC_READ
代表可讀不可寫,常數 GENERIC_WRITE 代表可寫不可讀,GENERIC_READ + GENERIC_WRITE 代表可寫亦
可讀.變數 dwShareMode 設定共享模式.常數 FILE_SHARE_READ 代表可以同時被多個程式讀取,而常數
FILE_SHARE_READ 代表可以同時被多個程式寫入,NULL 代表不開放共享.當然在 Serial Port 下
dwShareMode是不能開放共享的.
變數 lpSecurityAttributes 設定保密程度.
變數 dwCreationDistribution 決定檔案開啟模式.常數 OPEN_EXISTING 代表開啟一個已存在的舊檔.
常數CREATE_ALWAYS 代表開啟新檔.
變數 dwFlagsAndAttributes 決定檔案屬性.在使用 COM Port 時,檔案屬性必須設為 FILE_ATTRIBUTE_NORMAL.
變數 hTemplateFile 指定檔案屬性原型.
3.SetCommState
函數原型:
BOOL SetCommState(
  HANDLE hFile,      // handle of communications device
  LPDCB lpDCB           // address of device-control block structure
  );      
SetCommState 函數會根據 DCB 資料結構的內容,來設定串列通訊裝置,並對硬體重新初始化(initialize).
變數 hFile 存放著執行 CreatFile 函數後所傳回的 HANDLE 代碼.
變數 lpDCB 指向 DCB 資料結構的位址.
例如 : SetCommState(handle,&dcb)
若涵數執行成功,將傳回一個非零的值.若執行失敗則傳回零.
4.SetupComm
函數原型:
BOOL SetupComm(
  HANDLE hFile,      // handle of communications device
  DWORD dwInQueue,      // size of input buffer
  DWORD dwOutQueue      // size of output buffer
  );      
SetupComm 函數主要是用來設定輸入資料儲列(Queue)與輸出資料儲列大小.
變數 hFile 一樣也是存放著執行 CreatFile 函數後所傳回的 HANDLE 代碼.
變數 dwInQueue 設定輸入資料儲列的大小單位為 Byte.
變數 dwOutQueue 設定輸出資料儲列的大小單位為 Byte.
若涵數執行成功,將傳回一個非零的值.若執行失敗則傳回零.
5.SetCommTimeouts
函數原型:
BOOL SetCommTimeouts(
  HANDLE hFile,      // handle of communications device
  LPCOMMTIMEOUTS lpCommTimeouts      // address of communications time-out structure
  );      
本函數執行的結果,會影響 ReadFile 的讀取時間與 WriteFile 的寫入時間.
變數 hFile 存放著執行 CreatFile 函數後所傳回的 HANDLE 代碼.
變數 lpCommTimeouts 指向一個 communications time-out 的資料結構,
typedef struct _COMMTIMEOUTS {
  DWORD ReadIntervalTimeout;
  DWORD ReadTotalTimeoutMultiplier;
  DWORD ReadTotalTimeoutConstant;
  DWORD WriteTotalTimeoutMultiplier;
  DWORD WriteTotalTimeoutConstant;
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
變數 ReadIntervalTimeout 設定讀取第一個字元與第二個字元之間的 time out 時間.單位為毫秒
(msec)當使用 ReadFile 函數從串列埠讀取一個字元時,若在 ReadIntervalTimeout 時間內讀取第
二個字元,則 ReadFile函數會繼續讀取下一個字元.若未在 ReadIntervalTimeout 時間內讀取第二
個字元,則ReadFile 函數將完成工作也就是跳出 ReadFile 執行下一行敘述.ReadIntervalTimeout
設為 0 表示關閉此功能.
變數 ReadTotalTimeoutMultiplier 視讀取的字元數來決定總 time out 時間.
總 time out 時間 = ReadTotalTimeoutMultiplier * 欲讀取字元數 + ReadTotalTimeoutConstant.
將 ReadTotalTimeoutMultiplier 設為 0 表示關閉此功能.
變數 ReadTotalTimeoutConstant 為 time out 時間常數.加在 ReadTotalTimeoutMultiplier 之後.
變數 WriteTotalTimeoutMultiplier 與 WriteTotalTimeoutConstant 設定寫入串列埠的總 time out
時間.寫入串列埠的總 time out 時間 =
WriteTotalTimeoutMultiplier * 欲寫入之字元數 + WriteTotalTimeoutConstant.
將 WriteTotalTimeoutMultiplier 和 WriteTotalTimeoutConstant 設為 0 表示關閉此功能.
  讀取串列埠之 time out 設定的恰當與否,將會影響程式的執行效率,如果設定的總 time out 時
間過長,而遠端裝置又沒有回應(No Response)時通常會導致讓 User 誤判成電腦當機,所以不可以亂設
.一般通常都設成:
TimeOut.ReadIntervalTimeout = 0;
TimeOut.ReadTotalTimeoutMultiplier = 0;
TimeOut.ReadTotalTimeoutConstant = 500; //(總讀取 time out 時間 = 0.5 秒)
TimeOut.WriteTotalTimeoutMultiplier = 0;
TimeOut.WriteTotalTimeoutConstant = 500; //(總寫入 time out 時間 = 0.5 秒)
再執行 SetCommTimeouts(handle,&TimeOut) ,即完成了communications time-out 的設定.
若涵數執行成功,將傳回一個非零的值.若執行失敗則傳回零.
  最後再將上述的五個 Communication Function 簡單地複習一遍.
初始化 COM PORT 的步驟
1.BuildCommDCB : 建立 DCB (Device Control Block).
2.CreatFile   : 開啟 COM Port 並取得 Handle 代碼.
3.SetCommState : 根據 DCB 資料結構的內容,來設定串列通訊裝置,並對硬體重新初始化(initialize).
4.SetupComm   : 用來設定輸入資料儲列(Queue)與輸入資料儲列.
5.SetCommTimeouts :設定 ReadFile 的最大讀取時,間與 WriteFile 的最大寫入時間.
此時的 Com Port 已可隨意存取,欲存取 Com Port 請用 ReadFile() 與 WriteFile() API函數.
從 Com Port 讀取一個字元:
ReadFile(handle, &lpBuf, 1, &dwRead, NULL);
寫一個字元至 Com Port :
WriteFile(handle,&WriteBuffer,1,&NoWrite,0);
§範例
  本次以一個 8051 單板當作遠端裝置(Remote),透過一條 RS232 傳輸線與電腦相互溝通做為範例.
在 PC 端使用 Borland C++ Builder ,而在 Remote 8051 端則使用組合語言.由於本文章是以如何使
用 Win32 API 存取 Serial port 為主,所以在 8051 的程式上並沒有太複雜的流程與技巧,故不作詳
細的說明.
壹、功能:
  讓游標停留在 "傳送的字元" 下的文字方塊內,當 User 按下鍵盤上任一字元時,PC 端送出一個字
元給8051 Remote,8051 Remote 收到此字元後,立即回覆相同的字元給 PC 端,並將此字元顯示在 "接收
的字元" 下的文字方塊中.若當 User 按下 Read From Remote 時,8051單板收到 "!" 字元,立即傳回一
個二進制檔(binary file)給 PC,此二進制檔的內容是一個16色的 Bitmap File (BMP 檔).PC 端在接收
完整個 Bitmap File 後,自動以 C16.BMP 存檔.8051 單板的線路圖請參照圖二.  
貳、程式&說明
一、PC (Host) 方面
1.放置如圖一所示之控制項.

           < 1I?@
2.設定物件屬性,見表一.

           < ai?@
3.程式碼.
HANDLE handle;
FILE *infile;
FILE *outfile;
char TxdBuffer;
char RxdBuffer;
DWORD dwNoByte;
DCB dcb;
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Edit1-Text="";
Edit2-Text="";
COMMTIMEOUTS TimeOut;
  TimeOut.ReadIntervalTimeout = 0;
  TimeOut.ReadTotalTimeoutMultiplier = 0;
  TimeOut.ReadTotalTimeoutConstant = 500; //(總讀取 time out 時間 = 0.5 秒)
  TimeOut.WriteTotalTimeoutMultiplier = 0;
  TimeOut.WriteTotalTimeoutConstant = 500; //(總寫入 time out 時間 = 0.5 秒)
if (BuildCommDCB("9600,n,8,1",&dcb)){
lbBuildCommDCB-Caption="BuildCommDCB 成功";}
else{
lbBuildCommDCB-Caption="BuildCommDCB 失敗";}
handle=CreateFile("Com1",
            GENERIC_READ|GENERIC_WRITE,
            0,
            0,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            0);
if (SetCommState(handle,&dcb))
lbSetCommState-Caption="SetCommState 成功";
else
lbSetCommState-Caption="SetCommState 失敗";
if (SetupComm(handle,1024,1024))
lbSetupComm-Caption="SetupComm 成功";
else
lbSetupComm-Caption="SetupComm 失敗";
if (SetCommTimeouts(handle,&TimeOut))
lbSetCommTimeouts-Caption="SetCommTimeouts 成功";
else
lbSetCommTimeouts-Caption="SetCommTimeouts 失敗";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnReadClick(TObject *Sender)
{
TxdBuffer='!'
char Name[]={"C16.bmp"};
int a=0;
outfile=fopen(Name,"wb");
WriteFile(handle,&TxdBuffer,1,&dwNoByte,0);
ReadFile(handle,&RxdBuffer,1,&dwNoByte,NULL);
if (dwNoByte == 0 ) {lbStatus-Caption="沒有回應 !";return;}
a++;
fwrite(&RxdBuffer,1,1,outfile);
while(dwNoByte != 0)
{
ReadFile(handle,&RxdBuffer,1,&dwNoByte,NULL);
fwrite(&RxdBuffer,1,1,outfile);
a++;
}
fclose(outfile);
lbStatus-Caption="共接收了 "+IntToStr(a)+" Bytes";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)
{
char lpBuf;
char WriteBuffer;
char *ptr;
DWORD dwWrite;
DWORD dwRead;
ptr=&Key;
WriteBuffer=*ptr;
WriteFile(handle,&WriteBuffer,1,&dwWrite,0);
ReadFile(handle, &lpBuf, 1, &dwRead, NULL);
if (dwRead == 0)
{ lbStatus-Caption="沒有回應 !"; }
else
{Edit2-Text=Edit2-Text+lpBuf;}
}    
//---------------------------------------------------------------------------
二、8051 (Remote) 方面
1.硬體如圖二所示

           <圖二 >
2.程式碼.
;********************************************************
;* 使用 RS232 傳送 Binrary File For 8051. 作者:鄭旭崇 *      
;********************************************************
     LLCHAR ?                 ;宣告 Local Label Character = '?'
     ORG 0H
     JMP BEGIN
;---------------------------------------------------------------------------
BEGIN:      MOV      SP,#60H                  ;
     MOV      SCON,#50H            ;Serial Port 傳輸格式: 9600,N,8,1
     MOV      TMOD,#20H            ;
     MOV      TH1,#0FDH            ;
     SETB      TR1
     SETB      TI
     MOV      DPTR,#Hello            ;8051單板一開機,先送出歡迎詞給 PC 端.
     CALL      SendStr                  ;
Again:
     JNB      RI,$                  ;等待 PC 送字元過來.
     CLR      RI                  ;
     MOV      A,SBUF                  ;
     
     CJNE      A,'!',?10            ;不是 '!' 就將原字元傳回 PC 端.
     CALL      SendBinaryFile            ;是 '!' 就傳回二進制檔(Binary File).
     JMP      Again      
?10      CALL      SendByte
     JMP      Again
;===============================================================================
SendStr:            ;送出一字串.
?10      CLR      A
     MOVC      A,@A+DPTR            ;從 ROM 裡面取一個 Byte.
     CJNE      A,0,?20                  ;
     RET
?20      CALL      SendByte
     INC      DPTR
     JMP      ?10
     RET
;===============================================================================
SendBinaryFile:            ;送出二進制檔(Binary File).      
     MOV      DPTR,#BinData
     MOV      R4,#4                  ;準備傳送出 200 * 4 = 800 個 Bytes.
?10      MOV      R5,#200
?20        CLR      A
     MOVC      A,@A+DPTR            ;從 ROM 裡面取一個 Byte.
     CALL      SendByte
     INC      DPTR
     DJNZ      R5,?20
     DJNZ      R4,?10
     RET
;===============================================================================
SendByte:            ;送出一字元.
     JNB      TI,$
     CLR      TI
     MOV      SBUF,A
     RET
;===============================================================================
Hello:      DB 'Hello Welcome !',0
BinData:
     DB   42H,4DH,1EH,03H,00H,00H,00H,00H,00H,00H,76H,00H,00H,00H,28H,00H
     DB   00H,00H,22H,00H,00H,00H,22H,00H,00H,00H,01H,00H,04H,00H,00H,00H
     DB   00H,00H,A8H,02H,00H,00H,C4H,0EH,00H,00H,C4H,0EH,00H,00H,00H,00H
    DB   00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,80H,00H,00H,80H
     DB   00H,00H,00H,80H,80H,00H,80H,00H,00H,00H,80H,00H,80H,00H,80H,80H
     DB   00H,00H,C0H,C0H,C0H,00H,80H,80H,80H,00H,00H,00H,FFH,00H,00H,FFH
     DB   00H,00H,00H,FFH,FFH,00H,FFH,00H,00H,00H,FFH,00H,FFH,00H,FFH,FFH
     DB   00H,00H,FFH,FFH,FFH,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H
     DB   00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H
    DB   00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,AAH,AAH
     DB   AAH,AAH,AAH,AAH,99H,99H,99H,99H,FFH,FFH,FFH,99H,99H,00H,00H,00H
     DB   00H,00H,AAH,AAH,AAH,AAH,AAH,AAH,99H,99H,99H,99H,FFH,FFH,FFH,99H
     DB   99H,00H,00H,00H,00H,00H,00H,99H,AAH,AAH,AAH,AAH,AAH,99H,99H,99H
     DB   99H,FFH,FFH,FFH,99H,99H,00H,00H,00H,00H,00H,99H,AAH,AAH,AAH,AAH
     DB   AAH,99H,99H,99H,99H,FFH,FFH,FFH,99H,99H,00H,00H,00H,00H,00H,00H
     DB   99H,AAH,99H,99H,AAH,AAH,99H,99H,FFH,FFH,FFH,FFH,99H,00H,00H,00H
     DB   00H,00H,00H,00H,99H,AAH,99H,99H,AAH,AAH,99H,99H,FFH,FFH,FFH,FFH
     DB   99H,00H,00H,00H,00H,00H,00H,00H,00H,AAH,99H,99H,99H,AAH,AAH,FFH
     DB   FFH,FFH,FFH,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,AAH,99H,99H
     DB   99H,AAH,AAH,FFH,FFH,FFH,FFH,00H,00H,00H,00H,00H,00H,00H,00H,00H
     DB   00H,AAH,99H,99H,99H,AAH,AAH,AAH,AAH,AAH,AAH,AAH,00H,00H,00H,00H
     DB   00H,00H,00H,00H,00H,AAH,99H,99H,99H,AAH,AAH,AAH,AAH,AAH,AAH,AAH
     DB   00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,AAH,99H,AAH,AAH,00H,00H
     DB   00H,FFH,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,AAH,99H
     DB   AAH,AAH,00H,00H,00H,FFH,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H
     DB   00H,99H,AAH,AAH,AAH,AAH,AAH,FFH,FFH,AAH,FFH,AAH,AAH,00H,00H,00H
     DB   00H,00H,00H,00H,00H,99H,AAH,AAH,AAH,AAH,AAH,FFH,FFH,AAH,FFH,AAH
     DB   AAH,00H,00H,00H,00H,00H,00H,00H,99H,99H,AAH,AAH,AAH,AAH,FFH,FFH
     DB   00H,AAH,00H,FFH,AAH,00H,00H,00H,00H,00H,00H,00H,99H,99H,AAH,AAH
     DB   AAH,AAH,FFH,FFH,00H,AAH,00H,FFH,AAH,00H,00H,00H,00H,00H,00H,00H
     DB   00H,00H,AAH,AAH,AAH,AAH,FFH,FFH,00H,AAH,00H,FFH,AAH,00H,00H,00H
     DB   00H,00H,00H,00H,00H,00H,AAH,AAH,AAH,AAH,FFH,FFH,00H,AAH,00H,FFH
     DB   AAH,00H,00H,00H,00H,00H,00H,00H,00H,99H,AAH,AAH,AAH,AAH,FFH,FFH
     DB   00H,AAH,00H,FFH,00H,00H,00H,00H,00H,00H,00H,00H,00H,99H,AAH,AAH
     DB   AAH,AAH,FFH,FFH,00H,AAH,00H,FFH,00H,00H,00H,00H,00H,00H,00H,00H
     DB   99H,99H,99H,AAH,AAH,AAH,FFH,FFH,FFH,AAH,FFH,FFH,00H,00H,00H,00H
     DB   00H,00H,00H,00H,99H,99H,99H,AAH,AAH,AAH,FFH,FFH,FFH,AAH,FFH,FFH
     DB   00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,AAH,AAH,AAH,AAH,FFH
     DB   FFH,AAH,FFH,AAH,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,AAH
     DB   AAH,AAH,AAH,FFH,FFH,AAH,FFH,AAH,00H,00H,00H,00H,00H,00H,00H,00H
     DB   00H,00H,99H,99H,AAH,AAH,AAH,AAH,AAH,AAH,AAH,00H,00H,00H,00H,00H
     DB   00H,00H,00H,00H,00H,00H,99H,99H,AAH,AAH,AAH,AAH,AAH,AAH,AAH,00H
     DB   00H,00H,00H,00H,00H,00H,00H,00H,00H,99H,99H,99H,99H,AAH,AAH,AAH
     DB   AAH,AAH,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,99H,99H,99H
     DB   99H,AAH,AAH,AAH,AAH,AAH,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H
     DB   00H,00H,00H,00H,00H,99H,99H,99H,00H,00H,00H,00H,00H,00H,00H,00H
     DB   00H,00H,00H,00H,00H,00H,00H,00H,00H,99H,99H,99H,00H,00H,00H,00H
     DB   00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,99H,00H
     DB   00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H
     DB   00H,00H,99H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,8BH,D1H
           END
;-----------------------------------------------------------------------------------------
3.組譯程式,在 DOS 提示字元下輸入:
C:\X8051 REMOTE51
            8051 Macro Assembler   -   Version 4.03a
          Copyright (C) 1985 by 2500 A.D. Software, Inc.
                ***** Active Commands *****
                  Ctrl S = Stop Output
                  Ctrl Q = Start Output
                  Esc C = Stop Assembly
                  Esc T = Terminal Output
                  Esc P = Printer Output
                  Esc D = Disk Output
                  Esc M = Multiple Output
                  Esc N = No Output
          2500 A.D. 8051 Macro Assembler - Version 4.03a
          ------------------------------------------------
              Input Filename : REMOTE51.asm
              Output Filename : REMOTE51.obj
      Lines Assembled : 116         Assembly Errors : 0
4.連結程式,在 DOS 提示字元下輸入:
C:\LINK51 -c REMOTE51 -O -X
2500 A.D. Linker Copyright (C) 1985 - Version 4.03a
******************************************************************************
*                   L O A D     M A P                   *
******************************************************************************
*   Section Name         Starting Address   Ending Address   Size   *
******************************************************************************
* remote51.obj                                           *
*   CODE                   0000           0383       0384   *
******************************************************************************
            Linker Output Filename : remote51.tsk
            Disk Listing Filename :
            Symbol Table Filename :
      Link Errors : 0           Output Format : Executable
參、執行例
  請看圖三至圖五.
       

           <1I?T >鍵入 "Lovely",Remote 8051 回覆 "Lovely"

< 1I¥| 按下 Read From Remote 鈕,Remote 8051傳回一個二進制檔(binary file)給 PC,此二
      進制檔的內容是一個16色的 Bitmap File (BMP 檔).

<1I?- > C16.BMP 的內容
§結語
  看完了本篇文章後,是否對 Win32 API 如何存取 Serial Port 更加了解呢 ?
雖然我用 Borland C++ Builder 來講解程式,但小弟覺得用何種 Tool 或程式語言的本
身並不重要,重要的是能夠攝取文章中的靈魂,進而加以吸收,變成自己的東西,在各種程式語言
或情況下都能運用自如.
  讀者朋友對於本文章有任何問題或建議,歡迎您 E-mail 給我,小弟的 E-mail是 :
pttgood@cm1.hinet.net 當然,讀者朋友們想要程式的 Source Code 的話,也可以來信索取.
幾個月前我的好友 Tony 的老婆 LCM 生了一個白白胖胖的兒子,他們叫他 "阿肥 ".看到胖嘟嘟
的阿肥和他們倆如此幸福的臉龐,頓時讓我覺得人活著就應該感恩惜福,自然就會幸福快樂。
祝福每一位讀者健康快樂。

以上資料轉載自:http://finetek.myweb.hinet.net/t...2/bcbrs232.htm
大大加油唷 ^_^ 表情 表情

此文章被評分,最近評分記錄
財富:200 (by codeboy) | 理由: 回答的辛苦了~^^


視之不見,名曰夷;
聽之不聞,名曰希;
搏之不得,名曰微。
此三者不可致詰,故混而為一。

[截自老子道德經第十四章]
獻花 x1 回到頂端 [2 樓] From:台灣中華電信 | Posted:2005-09-12 17:13 |

首頁  發表文章 發表投票 回覆文章
Powered by PHPWind v1.3.6
Copyright © 2003-04 PHPWind
Processed in 0.022889 second(s),query:16 Gzip disabled
本站由 瀛睿律師事務所 擔任常年法律顧問 | 免責聲明 | 本網站已依台灣網站內容分級規定處理 | 連絡我們 | 訪客留言