- 在线时间
- 0 小时
- 最后登录
- 2007-9-23
- 注册时间
- 2004-9-10
- 听众数
- 3
- 收听数
- 0
- 能力
- 0 分
- 体力
- 9975 点
- 威望
- 7 点
- 阅读权限
- 150
- 积分
- 4048
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1893
- 主题
- 823
- 精华
- 2
- 分享
- 0
- 好友
- 0

我的地盘我做主
该用户从未签到
 |
< > </P>/ g1 d; W/ u) y" n/ ~) ]
< >姜滨 </P>
5 @& E$ n- ], _; Q< > </P>- W. U# j M$ ?; x8 b: |
< > ·串口操纵的基本方法· </P>0 Y, p. B+ _. {
< > </P>
+ W; f5 {# j. w< > </P>
1 o. U0 m5 q9 W, G" r% L: P( t< > 在Win32下,对串口的操作就如同对文件一样打开或关闭,对串行数据的读 </P>
6 E* ?. _; c- Q< >写可在用户定义的读写缓冲区中进行。具体使用的函数为: </P>! V6 Q( N. O$ F7 m$ [8 s! q5 D
< > </P>
: z) O/ [- F2 q! O< > 首先用CreateFile( )打开通信串口,其中参数lpFileName指向串口逻辑名 </P>
0 x( j# v! N( b0 ~2 X* k4 c< >,如“COM1”或“COM2”等,参数dwDesiredAccess定义文件的读写权限,一般 </P>9 v7 S4 d% J8 w, x
< >设为GENERIC—READ|GENERIC—WRITE;参数dwShareMode定义资源共享方式,此 </P>
" [6 k) {* Z; L; R9 P< >处必须设为0,为独占方式;lpSecurityAttributes定义安全属性,Win 95下为 </P>
9 u5 I3 P' O. C9 W5 b< >NULL;dwCreationDistribution定义文件创建方式;dwFlagsAndAttributes定义 </P>( o4 ~& @, x$ R
< >文件属性和标记,应设为FILE—FLAG—OVERLAPPED,表示异步通信方式; </P>7 }0 R: D; N6 h7 {
< >hTemplateFile 指向一个模板文件的句柄,在 Windows 95下为NULL。 </P>
S, `% C5 W- h- L! Y1 l1 b< > </P>
2 b% u6 J8 Y6 m$ v< > 然后用BuildCommDCB( )和SetCommState( )函数通过通信设备控制块DCB( </P>
7 ^. Z; n+ q6 N& J3 Q< >Device Control Block)设置串口通信参数(如波特率、停止位、数据位、校验 </P>
$ u" Y/ x( U4 `% A9 W< >位等),其中BuildCommDCB( )中的字符串参数lpDef 定义同DOS命令中MODE的参 </P>+ L2 S$ g# K" r% Y4 q* z
< >数格式,关于DCB更具体的设置需要根据用户对数据流定义、握手信号及通信控 </P>6 q& R W( X3 f$ [2 W+ M9 a
< >制要求具体定义,参见有关Windows技术资料。用GetCommState()可以得到当前 </P>& p9 M8 h! ?4 S' D4 M% Q. ~
< >的DCB参数值。如果需要还可通过SetCommTimeouts()和GetCommTomeouts()重新 </P>
1 Z+ G& Y8 h S" |< >设置读写的超时参数;读写缓冲区的设置使用SetupComm(),参数dwInQueue和 </P>/ C2 s, o9 r8 x1 W# P7 h
< >dwOutQueue分别定义为输入和输出缓冲区的大小。 </P>
; U0 `4 U5 {4 j' H4 n% o* N< > </P>
+ x7 P0 m5 P! K' A; Y< > 在串口初始化完毕后,还要建立与通信有关的事件对象。一般使用 </P>
0 p) G9 z+ `7 F9 e+ X< >CreateEvent()函数,它返回一事件句柄,其中参数lpEventAttributes指向安全 </P>
! c6 ?! }8 b" J) u< >属性结构地址,在Win 95(无安全属性)中为NULL;布尔参数bManualReset 定 </P>3 y1 l, \- i, b% {
< >义事件重置方式,true 表示手工重置,false表示自动重置(相关函数为 </P>
3 d. a. h! E6 z$ l- |<P>SetEvent()和ResetEvent());参数bInitialState定义事件初始状态,true表 </P>3 m! V' K5 P2 r h% i5 L
<P>示发信号,否则为不发信号;lpName是为多进程设置的事件名,对于单进程定义 </P>% r+ \0 K* R0 m l1 B
<P>为NULL。然后用SetCommMask()定义用户程序可监视的通信事件类别。 </P>
/ B" w5 W* u( h. ]<P> </P>1 d; C2 C5 k1 @
<P> 以上设置完成后,用户程序就可以等待通信事件的产生,一般调用函数 </P>
8 o' p, }, i, A) _+ f% O* O3 }<P>WaitCommEvent()监视通信事件,其中参数lpEvtMask指向产生事件的掩码地址, </P>; g( ~0 k3 ^8 J$ F3 `! R' `4 \
<P>用于判断事件产生的性质,lpOverlapped指向重叠结构地址,可简单定义为 </P>
0 d$ s$ y6 c) u: s, p<P>NULL。对于串口事件的响应一般有四种方式:查询、同步I/O、异步I/O和事件驱 </P>
$ T0 b% o, d+ ^" |) I2 U# k- y<P>动I/O,需要根据用户不同控制要求而定。查询方式占用较长的计算机时间,同 </P>
* m: l6 z3 d8 o<P>步I/O方式直到读取完指定的字节数或超时时才返回,容易造成线程阻塞,异步 </P>6 Q" @6 H: N/ A6 h# o' M
<P>I/O用于后台处理,事件驱动是由系统通知用户程序发生的事件并进行串口操作 </P>; l- G1 h' K1 M
<P>。 比较而言事件驱动I/O方式较灵活。 </P>
v3 W6 d2 k6 ^5 o" d- `<P> </P>4 i$ D( ? W- G. U' I
<P> 当有通信事件产生时,就可用函数ReadFile()和WriteFile()直接对串口缓 </P>
6 o1 U* q/ B% h% O5 V0 X<P>冲区进行读写操作了。其中lpBuffer 指向读写缓冲区,nNumberOfBytes为要读 </P>
( C- z0 f+ l# A6 r. `<P>写的字节数,lpNumberOfBytes为实际读写的字节数,lpOverlapped指定同步或 </P>
* Q8 `/ L; q$ m<P>异步操作。通信结束后,调用函数CloseHandle()将串口关闭。 </P>
- [3 K; \& E# u) ~; k3 z" x6 u$ j<P> </P>
6 ]! Z4 w% S, L4 L$ [4 S0 D) ]<P> ·应用实例说明· </P>
+ w! a+ s" A+ e# A) [1 i<P> </P>
$ B6 @& M) |- F Y1 ^<P> </P>9 [8 B& L! i( [1 y3 y# d
<P> 使用以上的API函数,笔者给出了简化后的串口初始化的实例。图1为使用C </P>
6 n3 B4 X1 G( ?8 ?6 L<P>++ Builder 组件生成的串口通信基本参数设置的界面实例。 </P>6 N1 @( S# N) N$ W0 i5 X9 n$ Y
<P> </P>
4 s7 t! g/ [% `2 p u* O$ V<P> HANDLE hcom; //定义句柄 </P>
7 O( @1 m0 A, V7 e: s) o<P> </P>. E' l- i; F+ c8 j
<P> DCB dcb; </P>
: R" g& q, T! j) _/ G* v<P> </P>
4 N9 [ M( I7 I5 y+ x5 v( \<P> OVERLAPPED e; //定义重叠结构 </P>
% Q% u# k4 k5 a; o5 S2 h. P2 }<P> </P>3 K2 G; r5 \& ^4 g4 W/ D
<P> void —fastcall TForm1::OkBtnClick(TObject?Sender) </P>, o# p9 U5 V# Q. m/ ~( a) @0 b
<P> </P>0 D8 N/ k( V6 ]& [& @
<P> { hcom=CreateFile("COM2",GENERIC—READ|GENERIC—WRITE,0,NULL,OPEN </P>! c3 o. E- p2 x1 ?8 k" m- j
<P>—EXISTING, </P>
* \2 N! _* G2 |; d0 [<P>FILE—ATTRIBUTE—NORMAL|FILE—FLAG—OVERLAPPED,NULL); //打开通讯口 </P>: E o; r# S/ {) i7 y. ?* d
<P> </P>, n% u( T6 ~( m, n& P X3 G* Z
<P> BuildCommDCB("9600,O,8,1",&dcb); </P>
: {" ?6 l& x- g3 g6 o" `6 ?<P> </P>& i" x. J2 ^4 x+ @9 G: {
<P>//第一个字符串参数实际使用时由图1选择后组合,这里仅简单说明其格式 </P>
U& _- _; N9 G% x( w$ n<P> </P>
8 B5 @% ~# h0 x3 F! u" K<P> SetCommState(hcom,&dcb); </P>4 F$ F/ V4 V' _# J7 j7 h1 Q
<P> </P>( P1 S8 U1 P/ G2 E$ i# `
<P> SetupComm(hcom,512,512);//设置读写缓冲区 </P>9 y' B M$ N* ^! C/ @9 @" h
<P> </P>
& m; m1 p( ^+ S2 L7 Q% g! a& `<P> e.hEvent=CreateEvent(NULL,false,false,NULL); //设置事件 </P>
5 s* P$ L0 g0 k" `<P> </P>. N/ [" l1 v% j5 e8 K" H& G
<P> SetCommMask(hcom,EV—RXCHAR| EV—TXEMPTY); //设置事件掩码 </P>
0 Q. h7 e" F4 O<P> </P>+ F' P; Q+ g# y; R @
<P> OkBtn-〉Enabled=false;} </P> |
zan
|