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

我的地盘我做主
该用户从未签到
 |
< > </P>
2 i, I0 G H% w! C! P< >姜滨 </P>
6 H2 b! c1 x8 M( E< > </P>" d# j! V5 |8 v/ B; W
< > ·串口操纵的基本方法· </P>% W, R5 S& \7 v! k1 g2 T$ `' r
< > </P>5 o3 R5 d5 U. z( s/ R4 Z6 ^6 L
< > </P>
' g- ~+ W2 T% D/ {* ^( z< > 在Win32下,对串口的操作就如同对文件一样打开或关闭,对串行数据的读 </P>
# W1 B: |( I; ?- a/ f; V+ o' o< >写可在用户定义的读写缓冲区中进行。具体使用的函数为: </P>
$ {- H4 U/ C6 n8 F4 u! ~< > </P>7 M( Y. ~" h' ?; t! c y" Q& i) |
< > 首先用CreateFile( )打开通信串口,其中参数lpFileName指向串口逻辑名 </P>
% _( p8 ]! }. C4 {$ M0 U< >,如“COM1”或“COM2”等,参数dwDesiredAccess定义文件的读写权限,一般 </P>
5 R8 n7 z& v5 ~( y< >设为GENERIC—READ|GENERIC—WRITE;参数dwShareMode定义资源共享方式,此 </P> W# N l0 _! s
< >处必须设为0,为独占方式;lpSecurityAttributes定义安全属性,Win 95下为 </P>) d' I# D% i7 ~
< >NULL;dwCreationDistribution定义文件创建方式;dwFlagsAndAttributes定义 </P>( O! q/ ]- q2 e+ l1 ?# u6 {
< >文件属性和标记,应设为FILE—FLAG—OVERLAPPED,表示异步通信方式; </P>3 @: k+ F# a1 p- m/ q/ B
< >hTemplateFile 指向一个模板文件的句柄,在 Windows 95下为NULL。 </P> Z) e2 Z: z' ~- N
< > </P>
. v0 L: ?& T2 t" C+ w: r- L< > 然后用BuildCommDCB( )和SetCommState( )函数通过通信设备控制块DCB( </P>7 i& f. \' F" `
< >Device Control Block)设置串口通信参数(如波特率、停止位、数据位、校验 </P>2 r' ^0 s0 B; R; l5 I8 ^! x: r
< >位等),其中BuildCommDCB( )中的字符串参数lpDef 定义同DOS命令中MODE的参 </P>
; c0 R6 ^: n- F< >数格式,关于DCB更具体的设置需要根据用户对数据流定义、握手信号及通信控 </P>
) J- m4 a v$ j3 Y+ ]< >制要求具体定义,参见有关Windows技术资料。用GetCommState()可以得到当前 </P>
$ n. |% J. [6 e5 D' M< >的DCB参数值。如果需要还可通过SetCommTimeouts()和GetCommTomeouts()重新 </P> X K) h0 L, |3 l1 h! R ?3 q
< >设置读写的超时参数;读写缓冲区的设置使用SetupComm(),参数dwInQueue和 </P>- h/ _5 @! \3 k
< >dwOutQueue分别定义为输入和输出缓冲区的大小。 </P>+ z( `/ M' S* Q+ W
< > </P>- F) b9 |6 i) G3 r4 @
< > 在串口初始化完毕后,还要建立与通信有关的事件对象。一般使用 </P>
- x$ P: k! p7 A& t% L F: _1 j< >CreateEvent()函数,它返回一事件句柄,其中参数lpEventAttributes指向安全 </P>
; c: `! S2 j- V< >属性结构地址,在Win 95(无安全属性)中为NULL;布尔参数bManualReset 定 </P>
9 _- @1 f! }4 E% _8 J% I0 y, n< >义事件重置方式,true 表示手工重置,false表示自动重置(相关函数为 </P>" X- P7 `! n! ]4 M
<P>SetEvent()和ResetEvent());参数bInitialState定义事件初始状态,true表 </P>0 D, a- |9 }& x, U
<P>示发信号,否则为不发信号;lpName是为多进程设置的事件名,对于单进程定义 </P>/ L& v- }' ]7 j% |1 N" y
<P>为NULL。然后用SetCommMask()定义用户程序可监视的通信事件类别。 </P>& Z% S' Z) |- P2 K1 R
<P> </P>
& H& S4 I, a2 \3 Q2 Z<P> 以上设置完成后,用户程序就可以等待通信事件的产生,一般调用函数 </P>
' w7 i% K0 W1 f. A<P>WaitCommEvent()监视通信事件,其中参数lpEvtMask指向产生事件的掩码地址, </P>& U4 }2 h5 E0 [) f/ C2 i
<P>用于判断事件产生的性质,lpOverlapped指向重叠结构地址,可简单定义为 </P>' j2 x! \9 N& ?1 D. H
<P>NULL。对于串口事件的响应一般有四种方式:查询、同步I/O、异步I/O和事件驱 </P>1 R, B: z) Y# U \9 Q
<P>动I/O,需要根据用户不同控制要求而定。查询方式占用较长的计算机时间,同 </P>
9 c' b9 U& \& B; f2 h<P>步I/O方式直到读取完指定的字节数或超时时才返回,容易造成线程阻塞,异步 </P>
. E8 [) A: w J/ w& M: y<P>I/O用于后台处理,事件驱动是由系统通知用户程序发生的事件并进行串口操作 </P>! k" M' z3 G4 S2 e! C/ e$ T( b
<P>。 比较而言事件驱动I/O方式较灵活。 </P>2 r: [' x5 ^6 a2 b* H( n5 N" V
<P> </P># @6 ]% H: J: ? V" X$ k
<P> 当有通信事件产生时,就可用函数ReadFile()和WriteFile()直接对串口缓 </P>
- U7 n# \8 g j( G" P: u<P>冲区进行读写操作了。其中lpBuffer 指向读写缓冲区,nNumberOfBytes为要读 </P>
$ g; W1 E4 f- |1 \- A+ S! z7 s4 i<P>写的字节数,lpNumberOfBytes为实际读写的字节数,lpOverlapped指定同步或 </P>
* l+ V% }8 s F$ i- o% g' D<P>异步操作。通信结束后,调用函数CloseHandle()将串口关闭。 </P>+ u4 v/ \0 n7 u: _9 z% t
<P> </P>4 d4 M# q1 I% Z2 C
<P> ·应用实例说明· </P>
8 g+ {4 z) o5 D: i2 V$ N<P> </P>3 C5 w; o5 y" x& Q
<P> </P>
' c2 Y0 K( k. C<P> 使用以上的API函数,笔者给出了简化后的串口初始化的实例。图1为使用C </P>1 D m" Q, @7 F
<P>++ Builder 组件生成的串口通信基本参数设置的界面实例。 </P>
# j" ^% r1 y, n% C5 c<P> </P> e4 D* D! |0 ?: Q
<P> HANDLE hcom; //定义句柄 </P>' Z Z% H, O6 w
<P> </P>
! F/ u, B/ b6 |+ s6 @- \<P> DCB dcb; </P>
$ N \6 n9 s V0 N4 P<P> </P>) ^+ m9 \6 i' [* ~. o
<P> OVERLAPPED e; //定义重叠结构 </P>
9 ]/ d4 Z0 {. m) Y7 C" x1 ~<P> </P>
9 i4 c) a( z+ s$ H* ~9 Z7 Z<P> void —fastcall TForm1::OkBtnClick(TObject?Sender) </P>& _+ r- j0 w! R, x3 O$ w
<P> </P>, F/ V+ M4 C1 o9 U) R ~1 c4 u- Q
<P> { hcom=CreateFile("COM2",GENERIC—READ|GENERIC—WRITE,0,NULL,OPEN </P>
. _$ ?: ~; \; i- o, @7 E+ W<P>—EXISTING, </P>6 K7 s. @; w5 f0 q/ V8 z+ B+ z$ h
<P>FILE—ATTRIBUTE—NORMAL|FILE—FLAG—OVERLAPPED,NULL); //打开通讯口 </P>
8 a( k0 c* j6 G2 j<P> </P>
- D8 ~8 J: \' M; _! L<P> BuildCommDCB("9600,O,8,1",&dcb); </P>
7 N- i% x& a: O/ |<P> </P>
8 h0 e: |6 |, J1 u* A2 X" ?$ _ d4 e<P>//第一个字符串参数实际使用时由图1选择后组合,这里仅简单说明其格式 </P>
2 H% [9 ^% v4 [& q; q8 o% D: b<P> </P>
8 v: {0 l' o, J V: s& {7 A1 r<P> SetCommState(hcom,&dcb); </P>6 z" ]0 A/ [. r; L
<P> </P>
r( m- [! _; M/ Z<P> SetupComm(hcom,512,512);//设置读写缓冲区 </P>
7 e. n2 ?3 @$ j2 B, X<P> </P>
1 I i$ _2 X! r<P> e.hEvent=CreateEvent(NULL,false,false,NULL); //设置事件 </P>
3 J/ O9 V# D/ ?; ~& F<P> </P>- E8 [- p# D" d' s' s% J. c
<P> SetCommMask(hcom,EV—RXCHAR| EV—TXEMPTY); //设置事件掩码 </P>! `: c# J4 u/ b' e
<P> </P>. z7 t* b1 w3 ]& m9 v, @" Z$ X
<P> OkBtn-〉Enabled=false;} </P> |
zan
|