数学建模社区-数学中国

标题: 用C++Builder4.0编写Win 95下的串行异步通信程序 [打印本页]

作者: 韩冰    时间: 2005-1-26 13:06
标题: 用C++Builder4.0编写Win 95下的串行异步通信程序
<>  </P>
) J: e' B9 X* R; a+ o) \4 D<>姜滨 </P>5 u' {) W- E, l3 L& z2 h9 b: P+ [3 \
<>  </P>: a1 q5 O$ u+ X: G# n! q
<>  ·串口操纵的基本方法· </P>
, U, T; F. V! x2 M% E<>  </P>6 k; ]7 ]7 ^0 |
<>  </P>
2 O: c2 ^5 b! d! C7 g4 I! c<>  在Win32下,对串口的操作就如同对文件一样打开或关闭,对串行数据的读 </P>
7 r0 t- r5 M% L3 Z, Q* E<>写可在用户定义的读写缓冲区中进行。具体使用的函数为: </P>1 ]" B* W" r% [
<>  </P>
- c+ r8 x) Z& @+ R; o. _& s! Z<>  首先用CreateFile( )打开通信串口,其中参数lpFileName指向串口逻辑名 </P># O( u# L/ Y6 l; p" S! N5 |# p
<>,如“COM1”或“COM2”等,参数dwDesiredAccess定义文件的读写权限,一般 </P>
$ A0 L. q5 l4 M+ @. _5 a$ }0 }<>设为GENERIC—READ|GENERIC—WRITE;参数dwShareMode定义资源共享方式,此 </P>
" T) B8 E3 l7 t- C. \; Z<>处必须设为0,为独占方式;lpSecurityAttributes定义安全属性,Win 95下为 </P>0 U7 h3 N" h, s) E  W
<>NULL;dwCreationDistribution定义文件创建方式;dwFlagsAndAttributes定义 </P>* ~6 z; y  |# B, F5 P0 s  D$ o
<>文件属性和标记,应设为FILE—FLAG—OVERLAPPED,表示异步通信方式; </P>
& a9 y/ o1 e( E8 m9 i* c4 J<>hTemplateFile 指向一个模板文件的句柄,在 Windows 95下为NULL。 </P>
6 c! f8 {) _4 U& J: b/ E0 B<>  </P>
/ G! F. R* ?$ q+ r. ~- T<>  然后用BuildCommDCB( )和SetCommState( )函数通过通信设备控制块DCB( </P>
1 X* I! M- f; H1 I<>Device Control Block)设置串口通信参数(如波特率、停止位、数据位、校验 </P>
% G4 W" t) y: J; t<>位等),其中BuildCommDCB( )中的字符串参数lpDef 定义同DOS命令中MODE的参 </P>1 a3 W2 ~- h; I2 a
<>数格式,关于DCB更具体的设置需要根据用户对数据流定义、握手信号及通信控 </P>
% c- i) R9 F# n( ~( w<>制要求具体定义,参见有关Windows技术资料。用GetCommState()可以得到当前 </P>2 V0 k' D6 C( q! }$ f) c7 u0 w  p
<>的DCB参数值。如果需要还可通过SetCommTimeouts()和GetCommTomeouts()重新 </P>
) k: J' \  f: G  `2 K9 R<>设置读写的超时参数;读写缓冲区的设置使用SetupComm(),参数dwInQueue和 </P>4 v9 t7 O& H  s# k6 z& {( p, L
<>dwOutQueue分别定义为输入和输出缓冲区的大小。 </P>
1 C+ R/ J/ F3 w9 \4 H( u% h<>  </P>
& b* l; [* y. `9 o% R! T& s<>  在串口初始化完毕后,还要建立与通信有关的事件对象。一般使用 </P>
' Q' a2 B8 o5 N' l<>CreateEvent()函数,它返回一事件句柄,其中参数lpEventAttributes指向安全 </P>
& k8 q( G6 L* w( ^5 K<>属性结构地址,在Win 95(无安全属性)中为NULL;布尔参数bManualReset 定 </P>
: U4 Q) A( p5 S$ o0 ^9 g<>义事件重置方式,true 表示手工重置,false表示自动重置(相关函数为 </P>0 b2 P) L0 @6 m( L" x
<P>SetEvent()和ResetEvent());参数bInitialState定义事件初始状态,true表 </P>
& k" ?5 r8 ^& u, p) a<P>示发信号,否则为不发信号;lpName是为多进程设置的事件名,对于单进程定义 </P>/ a/ ~& y. n9 b3 ~( z
<P>为NULL。然后用SetCommMask()定义用户程序可监视的通信事件类别。 </P>
7 l0 n4 p1 N4 k<P>  </P>
6 K9 ]5 p& p2 A9 t9 P* m. I<P>  以上设置完成后,用户程序就可以等待通信事件的产生,一般调用函数 </P>" N! [; t8 |' f/ {$ W' x
<P>WaitCommEvent()监视通信事件,其中参数lpEvtMask指向产生事件的掩码地址, </P>
/ V0 I# m0 m' C/ i, ?<P>用于判断事件产生的性质,lpOverlapped指向重叠结构地址,可简单定义为 </P>
" X6 }+ q, L, d+ ]  e& w" F<P>NULL。对于串口事件的响应一般有四种方式:查询、同步I/O、异步I/O和事件驱 </P>( ^) W8 Q* b) f' z
<P>动I/O,需要根据用户不同控制要求而定。查询方式占用较长的计算机时间,同 </P>+ U2 O. `0 ~6 a9 D2 `/ b% M
<P>步I/O方式直到读取完指定的字节数或超时时才返回,容易造成线程阻塞,异步 </P>
% T/ y1 Q8 R" L1 j4 N' S! ~<P>I/O用于后台处理,事件驱动是由系统通知用户程序发生的事件并进行串口操作 </P>' Z" ^5 l0 ], c+ O6 m
<P>。 比较而言事件驱动I/O方式较灵活。 </P>
5 s% V" y; v, a8 x* q2 {<P>  </P>
; I( B) k( W% s, K" Z# J<P>  当有通信事件产生时,就可用函数ReadFile()和WriteFile()直接对串口缓 </P>& e4 V- T! p4 `3 b0 ^% T
<P>冲区进行读写操作了。其中lpBuffer 指向读写缓冲区,nNumberOfBytes为要读 </P># T0 [( _# ^6 H/ F: V( Y0 e
<P>写的字节数,lpNumberOfBytes为实际读写的字节数,lpOverlapped指定同步或 </P>8 x7 w$ s2 w- q! Z$ N" @' |
<P>异步操作。通信结束后,调用函数CloseHandle()将串口关闭。 </P>
. n+ C2 w" B' H# N6 U" O) t- P<P>  </P>
: x2 H/ j, l) g! C# ~<P>  ·应用实例说明· </P>- T( |! [$ h; X7 J% N
<P>  </P>
! o. l5 f& D- \. O6 a; J<P>  </P>6 }5 f4 X4 I1 R+ l, }. w) ^
<P>  使用以上的API函数,笔者给出了简化后的串口初始化的实例。图1为使用C </P>
# u3 c2 {" ?: C, @6 m<P>++ Builder 组件生成的串口通信基本参数设置的界面实例。 </P>
8 V2 w: H: z& h<P>  </P>
2 r7 t1 E, \9 M<P>  HANDLE hcom; //定义句柄 </P>
) ?) }% Y; d4 H4 f<P>  </P>
+ G$ y/ \; x& t& n9 V<P>  DCB dcb; </P>
# P: O, |  n7 `! N: L<P>  </P>: B' \+ H0 D  X( L
<P>  OVERLAPPED e; //定义重叠结构 </P>
1 I+ d' s3 R- O' P<P>  </P>
+ D7 h6 A2 W) @0 V9 F<P>  void —fastcall TForm1::OkBtnClick(TObject?Sender) </P># Y3 _0 h) V. q6 a. s/ e
<P>  </P>
& p' u4 Z& \2 ]2 ?: M; ~<P>  { hcom=CreateFile("COM2",GENERIC—READ|GENERIC—WRITE,0,NULL,OPEN </P>4 u$ x- f' f$ o6 I, x
<P>—EXISTING, </P>& U! i6 s! S5 _# T0 a& n* s
<P>FILE—ATTRIBUTE—NORMAL|FILE—FLAG—OVERLAPPED,NULL); //打开通讯口 </P># ^- g% A3 y, z" U6 q% d% g5 S# u
<P>  </P>' X# ~& E# |( P- s, I# g
<P>   BuildCommDCB("9600,O,8,1",&dcb); </P>
! e1 ?& Y7 F6 d6 x6 w# P. G<P>  </P>
( d7 n* w3 l4 p# G) E- Q5 \9 X<P>//第一个字符串参数实际使用时由图1选择后组合,这里仅简单说明其格式 </P>2 Y# U$ g3 r# m; |, o% ~5 Q: F! h
<P>  </P>. b8 J1 p4 _6 F- t- I  z
<P>   SetCommState(hcom,&dcb); </P>
5 k, l4 e2 v. l/ _. I3 f: U<P>  </P>
" i+ T" q) _3 k8 f$ E$ j8 U. R<P>   SetupComm(hcom,512,512);//设置读写缓冲区 </P>
9 V  k# e% g  b<P>  </P>/ n! K% P4 _/ F- U- e8 ?
<P>   e.hEvent=CreateEvent(NULL,false,false,NULL); //设置事件 </P>7 L  S) w, M8 S4 W
<P>  </P>
8 \3 y7 ]; d* w' K8 F<P>   SetCommMask(hcom,EV—RXCHAR| EV—TXEMPTY); //设置事件掩码 </P>' @" L7 q) @- p3 a/ M6 k" d
<P>  </P>
" b% a5 G* H4 F<P>   OkBtn-〉Enabled=false;} </P>
作者: cjplove    时间: 2005-1-31 23:43
<>强啊,顶</P>
作者: cjplove    时间: 2005-1-31 23:43
<>不错呢</P>
作者: lhc_mike    时间: 2005-3-9 09:33
又是转的吧?
作者: xtmlj    时间: 2005-3-12 19:24

作者: ai8815    时间: 2010-8-6 11:07
这个程序看着怎么有点怪呢
作者: ai8815    时间: 2010-8-6 11:08
我用VB编过,好像是比c build简单呢   个人觉得




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5