关于多线程对串口的操作,常量comnum=1就可以,大于1就出错(200)

  • 主题发起人 feng7504
  • 开始时间
F

feng7504

Unregistered / Unconfirmed
GUEST, unregistred user!
常量comnum=1就可以,大于1就出错,迷糊了,大家帮忙看看,不胜感激,谁有好的多线程对串口的控制也可以给我feng7504@126.com我还实验了动态创建spcomm的办法,但是串口无法接收到信息,动态创建的怎么写接收信息unit Unit1;interface uses ShareMem, Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons;Const Wm_CommNotify=WM_User+12; type TForm1 = class(TForm) BitBtn1: TBitBtn; Memo1: TMemo; Label1: TLabel; Edit1: TEdit; procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); procedure BitBtn1Click(Sender: TObject); private Procedure CommInitialize; Procedure MsgComm(Var Msg:Tmessage); Message WM_CommNotify; Function WriteStr(const Str:String;C:byte):Boolean; { Private declarations } public { Public declarations }// function ThreadFun(p: Pointer): Integer; end; TComm=Class(TThread) constructor Create(my:integer); Protected Procedure Execute;override; end; const comnum=2;var Form1: TForm1; Hcom,Post_Event:array[0..comnum] of Thandle; LpolW,LpolR:array[0..comnum] of Poverlapped; myHandle : Thandle; RXComm: array[0..comnum] of TComm; xc:integer;implementation{$R *.DFM} Procedure TForm1.CommInitialize;VarLpdcb:TDCB;i:integer; str:pansichar;begin for i:=0 to comnum do begin str := Pansichar('com'+IntToStr(i+3)); //pchar('com'+IntToStr(i+3)) hcom:=createFile(str, //串口名,可为com1-com4 generic_read or Generic_write,//访问模式 0, //共享模式,必须为0 nil, //安全属性指针 open_existing, ///找开方式必须为open_existing File_Flag_Overlapped,//文件属性,本文设为交迭标志 0); //临时文件句柄,必须为0 if hcom<>invalid_Handle_Value then begin SetupComm(hcom,4096,4096); //设置缓冲区长度 getCommState(hcom,lpdcb); //设置串口 lpdcb.baudrate:=9600; lpdcb.stopbits:=0; lpdcb.bytesize:=8; lpdcb.parity:=0; setCommState(hcom,lpdcb); SetCommMask(Hcom,ev_Rxchar); //设置串口事件屏蔽 end else showMessage('无法打开串口!'); end;end;Function TForm1.WriteStr(const Str:String;C:byte):Boolean; //发送数据varDwCharsWritten,DwRes:Dword;S_DATA:String;BRes:boolean;Begin BRes:=False; S_Data:=Str; if hcom[c]<>INVALID_HANDLE_VALUE then begin DwCharsWritten:=0; BRes:=WriteFile(Hcom[c],PChar(S_Data)^,Length(S_Data), DwCharsWritten,LpolW[c]); //返回True,数据立即发送完成 if not BRes then begin if GetLastError()=Error_IO_Pending then begin //正在发送数据 DwRes:=WaitForSingleObject(LpolW[c]^.hEvent,Infinite); if DwRes=Wait_Object_0 then // 如果不相等,出错 BRes:=GetOverLappedResult(hcom[c],LpolW[c]^,DwCharsWritten,False) //返回False,出错 else BRes:=true; //数据发送完成 end; end; end; Result:=Bres;end;Procedure TForm1.MsgComm(Var Msg:Tmessage); //接收数据var clear:boolean; coms:TComStat; cbNum,Cbread,lpErrors:Dword; s:string;begin clear:=clearCommerror(hcom[Msg.WParam],lperrors,@Coms); if clear then begin cbnum:=Coms.cbInQue; //获取接收缓冲区待接收字节数 setlength(s,cbnum+1); //分配内存 ReadFile(hcom[Msg.WParam],PChar(S)^,cbnum,Cbread,LpolR[Msg.WParam]); //读串口 setlength(s,cbread); //分配 SetEvent(Post_Event[Msg.WParam]); //同步事件置位 Memo1.Lines.Add(S); end;end;procedure TForm1.FormDestroy(Sender: TObject); //释放内存var i:integer;begin for i:=0 to comnum do begin CloseHandle(LpolW^.hEvent); CloseHandle(LpolR^.hEvent); dispose(lpolW); dispose(lpolR); LpolW:=Nil; LpolR:=Nil; RXComm.Terminate; SetEvent(Post_Event); CloseHandle(Post_Event); FileClose(hcom); end;end;procedure TForm1.FormCreate(Sender: TObject); //初始化内存及串口var i:integer;begin Comminitialize; for i:=0 to comnum do begin New(lpolW); New(lpolR); LpolW^.Internal:=0; LpolW^.InternalHigh:=0; LpolW^.Offset:=0; LpolW^.OffsetHigh:=0; LpolW^.hEvent:=Createevent(nil,true,False,nil); Lpolr^.Internal:=0; Lpolr^.InternalHigh:=0; Lpolr^.Offset:=0; Lpolr^.OffsetHigh:=0; Lpolr^.hEvent:=Createevent(nil,true,False,nil); PurgeComm(Hcom,Purge_TxAbort or Purge_RxAbort or Purge_Txclear or Purge_Rxclear); Post_Event:=Createevent(nil,true,true,nil); RXComm:=Tcomm.Create(i); end;end;procedure TForm1.BitBtn1Click(Sender: TObject);VarS_DATA:String; i:integer;begin S_Data:=Chr($eb)+Chr($90)+Chr($eb)+Chr($90); i := strtoint(edit1.Text); If not WriteStr(S_Data,i) then ShowMessage('无法发送数据') else ShowMessage('发送成功');end;constructor TComm.Create(my:integer);begin xc := my; inherited create(false);end;Procedure TComm.Execute;vardwEvtmask,dwOvres,bb:Dword;RXFinish:Bool;begin while true do begin DwEvtMask:=0; RXFinish:=WaitCommEvent(hcom[xc],dwevtmask,LpolR[xc]); //等待串口事件EV_RXCHAR if not RXFinish then //如果返回True,已立即完成,否则继续判断 if GetLastError()=ERROR_IO_PENDING then //正在接收数据 begin bb:=WaitForSingleObject(LpolR[xc]^.hEvent,500);//等待500ms Case bb of Wait_Object_0: RXFinish:=GetOverLappedResult(hcom[xc],LpolR[xc]^,dwOvRes,False); //返回False,出错 Wait_TimeOut: RXFinish:=False;//定时溢出 else RXFinish:=False; //出错 end; end else RXFinish:=False; if RXFinish then begin if WaitForsingleobject(Post_Event[xc],infinite)=Wait_Object_0 then //等待同步事件置位 begin resetEvent(Post_Event[xc]); //同步事件复位 PostMessage(Form1.handle,WM_CommNotify,xc,0); //发送消息//在这里可以触发串口接收事件 end; end; end;end;end.
 
Z

zhengrong117

Unregistered / Unconfirmed
GUEST, unregistred user!
for i:=0 to comnum do begin str := Pansichar('com'+IntToStr(i+3)); //pchar('com'+IntToStr(i+3)) hcom:=createFile(str, //串口名,可为com1-com4[red]//当 comnum 为2的时候你这是 com5了,估计你的com5不存在[/red] generic_read or Generic_write,//访问模式 0, //共享模式,必须为0 nil, //安全属性指针 open_existing, ///找开方式必须为open_existing File_Flag_Overlapped,//文件属性,本文设为交迭标志 0); //临时文件句柄,必须为0
 
F

feng7504

Unregistered / Unconfirmed
GUEST, unregistred user!
不好意思 补充一下,我安装的是多串口卡,有7个串口,从com3到com9,不用线程,单独设置成任何串口都可以
 
Z

zhengrong117

Unregistered / Unconfirmed
GUEST, unregistred user!
--具体出错的是哪句呢?
 
F

feng7504

Unregistered / Unconfirmed
GUEST, unregistred user!
执行完FormCreate的end就弹出错误框runtime error 217 at 0041447c
 
L

lastforest

Unregistered / Unconfirmed
GUEST, unregistred user!
你在程序中设个断点,一步一步执行一下
 
L

lastforest

Unregistered / Unconfirmed
GUEST, unregistred user!
你用 turbo Power async professional 的那个串口控件 好用
 
F

feng7504

Unregistered / Unconfirmed
GUEST, unregistred user!
虽然没有解决问题,但是仍然感谢各位的热心回答,谢谢,谢谢……………………!
 
顶部