请教有关串口的问题!(50分)

  • 主题发起人 Andy_chen
  • 开始时间
A

Andy_chen

Unregistered / Unconfirmed
GUEST, unregistred user!
简单的串口程序,使用线程对串口进行扫描。用一个按钮“receive”接收数据。
procedure TportForm.receiveButtonClick(Sender: TObject);
begin
if Thread1Active = false then
begin
ReceiveThread1.Create(false);// := TReceiveThread.Create(true);
Thread1Active := true;
end;
end;
Thread1Active :为全局变量
ReceiveThread1:TReceieveThread
线程中使用循环
while (not Terminated)and truedo
begin
sleep(80);
i := sio_read(port,@receivedata[0],n);
if i >= 0 then
begin
s := ansistring(receivedata);
portform.Memo1.Lines.Add(s);
end;
为何运行会出错

 
portform.Memo1.Lines.Add(s);这一句应该用同步方法包起来才行.
Synchronize(....)
在线程中如果需要操作主界面上的东东,必须用线程Synchronize(....)方法包起来才行,
否则容易出现访问冲突错误.
比如可以这样:
procedure updatememo;
begin
portform.Memo1.Lines.Add(s);
end;

然后
线程中使用循环
while (not Terminated)and truedo
begin
sleep(80);
i := sio_read(port,@receivedata[0],n);
if i >= 0 then
begin
s := ansistring(receivedata);
//portform.Memo1.Lines.Add(s);
//换成下面的语句
Synchronize(updatememo)
end;
这样就可以了.
 
怎么还是会出现Access violation at address 0041BC94 in module 'project2.exe'. Write
of address of 00000000E.的信息。
 
凡是哪些不是线程内部的过程全部用Synchronize包起来试试.
还有你的receivedata是怎么声明的?
 
procedure TReceiveThread.Execute;
var
i,length : integer;
receivedata: array of char;
s: string;
begin
{ Place thread code here }
length := n;
while (not Terminated)and truedo
begin
sleep(80);
i := sio_read(port,@receivedata[0],n);
if i >= 0 then
begin
s := ansistring(receivedata);
//portform.Memo1.Lines.Add(s);
//break;
Synchronize(updatememo);
end;
end;
这样的啊,可是还是会有问题。
 
receivedata: array of char;
改为
receivedata: array[1..1000] char;
 
好像还是不行啊!!
 
在sleep(80)那句上加个断点,然后看看具体出错在哪一步。
 
我有个问题,能不能跟我具体说说线程的结构,主要是于主线程的关系!多谢!
 
举例:
(*********************************************************************
ReadThd.pas
-- Read Thread for example program.
History: Date Author Comment
3/9/98 Casper Wrote it.
**********************************************************************)
unit ReadThd;
interface
uses Classes;
type
TReadThread = class(TThread)
private
m_buf : array [0..511] of Char;
{ Private declarations }
protected
procedure Execute;
override;
procedure ShowData;
end;

implementation
uses Windows,PComm,ExGlobal;
{ TReadThread }
procedure TReadThread.ShowData;
var
lend : LongInt;
begin
(*
When got any data,dump buffer to Edit window.
NOTE:
If any Null character in buffer,
characters after null can't be dumped
to Edit window.
*)
lend := Length(GhForm.Term.Text);
if(lend>25000)then
begin
{ Edit Control buffer size limit }
GhForm.Term.Text := string(m_buf);
Exit;
end;

GhForm.Term.SelStart := lend;
GhForm.Term.SelLength := 0;
GhForm.Term.SelText := string(m_buf);
end;

procedure TReadThread.Execute;
var
len : LongInt;
begin
(* before close port,set GhExit to true to terminate
the read thread *)
while not GhExitdo
begin
Sleep(10);
len := sio_read(GCommData.Port,@m_buf,511);
if (len>0) then
begin
m_buf[len] := Char(0);{null terminated string}
Synchronize(ShowData);
end
end;
end;

end.
 
换个思路吧, 读串口不要用多线程,直接在端口控件里的触发事件里写,很省事.
比如MSComm 控件吧,很方便.
 
同意楼上。to Andy_chen, 你虽然用了synchronize,但好像在updatememo函数里的s没有声明
为类的成员。
 
线程触发的时候是与主线程同时还是什么?
 
sio_read中 @receivedata[0] 改成 @receivedata
ReceiveThread1.Create(false);一执行,线程就开始运行了。
while (not Terminated)and truedo
这个死循环轮询串口是否接收数据。
你这样做其实是轮询,用中断好些。因为轮询耗费的资源多。
 
线程开始运行的时候是和主线程同时运行还是什么?
 
同时运行
 
那通过事件来触发线程又是怎么回事啊?
 
你的sio_read哪儿来的?
 
是用的pcomm啊
 
它自带了demo呀:.../PCommLt/Example/Delphi/IrqDemo
procedure TermIrq(Port:LongInt);stdcall;
begin
GTermIrqCnt := GTermIrqCnt + 1;
ShowCnt(GTermIrqCnt, 'sio_term_irq()');
{
When got this event,program will also
got 'Rx event'(sio_cnt_irq) at the same time.
}
end;

function InitIrq(Port:LongInt;termcode:Byte):boolean;
var
ret : LongInt;
begin
InitIrq := false;
GIdx := 0;
GTermIrqCnt := 0;
GCntIrqCnt := 0;
GModemIrqCnt := 0;
GBreakIrqCnt := 0;
GTxEmptyIrqCnt := 0;
ret := sio_term_irq(Port, TermIrq, termcode);
if ret <> SIO_OK then
begin
MxShowError('sio_term_irq', ret);
Exit;
end;

ret := sio_cnt_irq(Port, CntIrq, 1);
if ret <> SIO_OK then
begin
MxShowError('sio_cnt_irq', ret);
Exit;
end;

ret := sio_break_irq(Port, BreakIrq);
if ret <> SIO_OK then
begin
MxShowError('sio_break_irq', ret);
Exit;
end;

ret := sio_modem_irq(Port, ModemIrq);
if ret <> SIO_OK then
begin
MxShowError('sio_modem_irq', ret);
Exit;
end;

ret := sio_Tx_empty_irq(Port, TxEmptyIrq);
if ret <> SIO_OK then
begin
MxShowError('sio_Tx_empty_irq', ret );
Exit;
end;

InitIrq := true;
end;
 
顶部