广告广告
  加入我的最爱 设为首页 风格修改
首页 首尾
 手机版   订阅   地图  繁体 
您是第 13372 个阅读者
 
发表文章 发表投票 回覆文章
  可列印版   加为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.077223 second(s),query:16 Gzip disabled
本站由 瀛睿律师事务所 担任常年法律顾问 | 免责声明 | 本网站已依台湾网站内容分级规定处理 | 连络我们 | 访客留言