数学建模社区-数学中国

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

作者: 韩冰    时间: 2005-1-26 13:06
标题: 用C++Builder4.0编写Win 95下的串行异步通信程序
<>  </P>) r: k+ R+ {/ |# ^, j' k& V
<>姜滨 </P>, d! c  |; w9 P- j
<>  </P>0 }5 c6 f$ d+ N; L: j/ X0 Z
<>  ·串口操纵的基本方法· </P>: C- A9 f2 p) p% \: t, g+ T% C8 N
<>  </P>
" @# L) w& p4 V. n8 V* f' l<>  </P>3 d! U$ l9 O, g5 ?% _& h$ j7 u
<>  在Win32下,对串口的操作就如同对文件一样打开或关闭,对串行数据的读 </P>
# n* [. x8 k/ i$ y* f6 R/ t<>写可在用户定义的读写缓冲区中进行。具体使用的函数为: </P>; v) u% t5 `; N, d. q1 u6 y
<>  </P>- d. B' e! T5 u# g  d  f
<>  首先用CreateFile( )打开通信串口,其中参数lpFileName指向串口逻辑名 </P>
3 F0 p: J9 a5 _) N<>,如“COM1”或“COM2”等,参数dwDesiredAccess定义文件的读写权限,一般 </P>
/ H+ D5 V5 k' |1 X! m+ P<>设为GENERIC—READ|GENERIC—WRITE;参数dwShareMode定义资源共享方式,此 </P>
9 t0 E2 k, K8 y: v: _3 Y<>处必须设为0,为独占方式;lpSecurityAttributes定义安全属性,Win 95下为 </P>2 i' S7 J' Z+ n4 ^9 m
<>NULL;dwCreationDistribution定义文件创建方式;dwFlagsAndAttributes定义 </P>
) d, E3 ~3 w/ Y, o  o' S4 w0 _- e" w<>文件属性和标记,应设为FILE—FLAG—OVERLAPPED,表示异步通信方式; </P>
( }! S# Z6 G* c, _<>hTemplateFile 指向一个模板文件的句柄,在 Windows 95下为NULL。 </P>& e* I: Z, l8 G& X2 V0 D' _
<>  </P>0 A2 [' i; z  r/ ~0 L" |
<>  然后用BuildCommDCB( )和SetCommState( )函数通过通信设备控制块DCB( </P>1 ^1 Z) U! ?6 u5 l4 d, l
<>Device Control Block)设置串口通信参数(如波特率、停止位、数据位、校验 </P>
, N0 L2 r2 f9 C% @* W, \8 b<>位等),其中BuildCommDCB( )中的字符串参数lpDef 定义同DOS命令中MODE的参 </P>
, B3 o  c; z) x% W9 j# E: g7 Z: m: `<>数格式,关于DCB更具体的设置需要根据用户对数据流定义、握手信号及通信控 </P>
# Z! }4 [+ M& e<>制要求具体定义,参见有关Windows技术资料。用GetCommState()可以得到当前 </P>
" S  z* m- z% Z  W/ t<>的DCB参数值。如果需要还可通过SetCommTimeouts()和GetCommTomeouts()重新 </P>
! W; `$ e) B  H$ y, t<>设置读写的超时参数;读写缓冲区的设置使用SetupComm(),参数dwInQueue和 </P>% D; F/ o& ^+ a: v* d" W: [5 d
<>dwOutQueue分别定义为输入和输出缓冲区的大小。 </P>) l4 O& B) w( M" a! k6 Y
<>  </P>% |+ o, q* b/ W) q) U3 @
<>  在串口初始化完毕后,还要建立与通信有关的事件对象。一般使用 </P>
# L( p( {) d% Z3 u<>CreateEvent()函数,它返回一事件句柄,其中参数lpEventAttributes指向安全 </P>! A8 n# m* o; V' R( V
<>属性结构地址,在Win 95(无安全属性)中为NULL;布尔参数bManualReset 定 </P>; j1 i6 U+ g$ S& K7 [' ~' X7 U
<>义事件重置方式,true 表示手工重置,false表示自动重置(相关函数为 </P>8 j% A. ~6 M* @* E- y
<P>SetEvent()和ResetEvent());参数bInitialState定义事件初始状态,true表 </P>
7 A/ p/ v( N, ]3 s1 r<P>示发信号,否则为不发信号;lpName是为多进程设置的事件名,对于单进程定义 </P>
0 A( ]) F8 m* h; h/ I<P>为NULL。然后用SetCommMask()定义用户程序可监视的通信事件类别。 </P>. O, `8 z1 _  w8 S/ r
<P>  </P>) e) v9 o3 p: Q; T, G
<P>  以上设置完成后,用户程序就可以等待通信事件的产生,一般调用函数 </P>
5 b% A5 A7 l, S7 M. B: z; p4 Y; `<P>WaitCommEvent()监视通信事件,其中参数lpEvtMask指向产生事件的掩码地址, </P>
* b! m( H) I: r- B7 ^( `( D9 S<P>用于判断事件产生的性质,lpOverlapped指向重叠结构地址,可简单定义为 </P>
2 G. K9 I8 d% k& S& Q<P>NULL。对于串口事件的响应一般有四种方式:查询、同步I/O、异步I/O和事件驱 </P>
0 N2 o9 N$ u  ~<P>动I/O,需要根据用户不同控制要求而定。查询方式占用较长的计算机时间,同 </P>
/ i" q6 ?2 R; ^0 z! M<P>步I/O方式直到读取完指定的字节数或超时时才返回,容易造成线程阻塞,异步 </P>" l, \1 m% Z$ S( K6 o
<P>I/O用于后台处理,事件驱动是由系统通知用户程序发生的事件并进行串口操作 </P>
/ t; ]- {& L2 s! p8 H<P>。 比较而言事件驱动I/O方式较灵活。 </P>$ E" ^5 Y. `) e4 a  S+ K$ B
<P>  </P>* W+ K5 @/ E6 z5 t) {; g% L
<P>  当有通信事件产生时,就可用函数ReadFile()和WriteFile()直接对串口缓 </P>0 Q) S+ o; s( [; H7 s2 f# b
<P>冲区进行读写操作了。其中lpBuffer 指向读写缓冲区,nNumberOfBytes为要读 </P>
' q2 b! S. e1 i4 Y<P>写的字节数,lpNumberOfBytes为实际读写的字节数,lpOverlapped指定同步或 </P>
4 r6 ]: A8 s8 t7 E<P>异步操作。通信结束后,调用函数CloseHandle()将串口关闭。 </P>
- G; E, I& }3 o<P>  </P>
% d; A* h% o* N# V/ f2 i0 I( ~& q<P>  ·应用实例说明· </P>: Q: C' W$ v$ a" t3 O6 @5 B
<P>  </P>
# Y! P" k8 T1 v) k& r7 q9 q<P>  </P>9 |5 H+ r7 i2 j2 i9 z- s
<P>  使用以上的API函数,笔者给出了简化后的串口初始化的实例。图1为使用C </P>
' s3 {% w" ?$ X* N! r1 Z0 K<P>++ Builder 组件生成的串口通信基本参数设置的界面实例。 </P>
4 b" d6 O; x; r<P>  </P>. |/ ]6 s& Y/ R1 U, W' ^- J9 `" X+ M
<P>  HANDLE hcom; //定义句柄 </P>9 F9 Y; i. m! W8 I( L& E
<P>  </P>
+ m% H. A, d4 L8 ]! H* a! j6 z<P>  DCB dcb; </P>
" v$ K1 g2 k! q2 P, V% z, k# V0 G<P>  </P>
* W! O1 E" U! E* e<P>  OVERLAPPED e; //定义重叠结构 </P>
0 X+ z. O7 u0 W# ~( z2 U5 R' I<P>  </P>( E& U- `) }: y
<P>  void —fastcall TForm1::OkBtnClick(TObject?Sender) </P>
5 l2 {8 |! n1 h( H! g7 m% O<P>  </P>
, S9 _% m, a  E# m<P>  { hcom=CreateFile("COM2",GENERIC—READ|GENERIC—WRITE,0,NULL,OPEN </P>
; d7 l6 f/ v& g" C<P>—EXISTING, </P>
- t1 K& g) Y1 Z- r2 V<P>FILE—ATTRIBUTE—NORMAL|FILE—FLAG—OVERLAPPED,NULL); //打开通讯口 </P>
( C4 c1 L8 k' _8 b! W4 l! E<P>  </P>) Y" y( e6 {6 Q  d' z/ J; A
<P>   BuildCommDCB("9600,O,8,1",&dcb); </P>% T- U: u7 q) M$ A' ~5 t
<P>  </P>+ q: `! j. `9 N
<P>//第一个字符串参数实际使用时由图1选择后组合,这里仅简单说明其格式 </P>/ D! J3 q1 d6 r( ~
<P>  </P>( X, F) t0 U: n0 k5 X6 o
<P>   SetCommState(hcom,&dcb); </P>
1 x. q% m# U8 j; s<P>  </P>
& j5 g7 E3 S9 i' O<P>   SetupComm(hcom,512,512);//设置读写缓冲区 </P>2 H3 v8 v% G; C9 W: _% p
<P>  </P>$ n; k" \4 n! q( M' j
<P>   e.hEvent=CreateEvent(NULL,false,false,NULL); //设置事件 </P>& r& D6 e- H  w3 G
<P>  </P>
- ~- {$ j  Q' Z4 q+ ]<P>   SetCommMask(hcom,EV—RXCHAR| EV—TXEMPTY); //设置事件掩码 </P>( @& C1 p" j" ?5 O* F! `( H
<P>  </P>
1 p5 ^' x$ m3 m& |& g2 ^<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