spcomm中,如果串口不停发数据,该如何处理为好?(100分)

  • 主题发起人 主题发起人 linying
  • 开始时间 开始时间
哪里有SPCOMM控件下载?
 
问题还没搞定,我用的挺顺利,没有问题。你用定时开关串口试试。
 
你的问题我遇到过,我用单片机不停的发送数据,用计算机接收,试过各种控件,最后只有两个控件
可以使用来处理连续数据,
1。mscomm,用查询方式,判断mscomm.inputbufferlength>19(我的是19字节为一个循环)时开始处理,
2.pcomm.dll,忘了是哪一个控件附带的了,也是查询方式。
在115200的速度下,我边接收变画曲线一点没问题。
但是一用spcomm就不行了,onreceivedata触发一次就接收1024个字节,也就是直到缓冲区满了才触发,
这样很容易丢失数据,实在不好处理。
 
不好意思,刚刚找到,PCOMPRO,带hlp完整帮助,及C,DELPHI,VB的例子,只用其中的PCOMM.DLL就行了。
http://www.moxa.com.tw/product/PComm/registry/pcommpro.zip
 
to bluebirds:
mscomm我没有用过,不知能否迅速掌握?使用重点要注意什么?
 
bluebirds,
SPCOMM的onReceiveData何时触发事实上并不象你说的那样,实际上是 :
只要有数据输入缓存就触发
 
自己写串口通讯程序不就可以了吗
以下是我做的一个项目中使用的一个方法,
我的项目中的串口是多个的,由于原程序太大,我拷几个供参考
//接收数据链表
type
preceivelink=^treceivelink;
treceivelink=record
data:byte;
next:preceivelink;
end;

//读串口数据线程
{ TreadThread }
Type
TreadThread = class(TThread)
private
Fport: integer;
Fcomhandle: Integer;
Fdata:integer;
procedure add_onereceivedata;
protected
procedure Execute; override;
procedure data_handle(port:integer;receivelink:preceivelink;receivecount:integer);
procedure read_commdata;
public
constructor Create(port:integer;comhandle:thandle);
destructor Destroy;override;
end;

var
overlapped:poverlapped;
receivelink:preceivelink;
receivecount:integer;
//通讯口初始化
function init_comport(port:string;var comhandle:thandle;sbaud,sstop,sbyte,sparity:integer):boolean;
var
lpdcb:Tdcb;
begin
fillchar(overlapped,sizeof(toverlapped),0);
Comhandle:=CreateFile(PChar(Port),generic_read or generic_write,0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if comhandle = INVALID_HANDLE_VALUE then
result:=false
else
begin
if not setupcomm(comhandle,512,512) then //字节数可以根据需要修改
begin
result:=false;
exit;
end;
getcommstate(comhandle,lpdcb);
lpdcb.baudrate:=sbaud;
lpdcb.StopBits:=sstop;
lpdcb.ByteSize:=sbyte;
lpdcb.Parity=sparity;
if not Setcommstate(comhandle,lpdcb) then
begin
result:=false;
exit;
end;
if not setcommMask(comhandle,ev_rxchar) then
begin
result:=false;
exit;
end;
result:=true;
end;
end;


//读串口线程
constructor TreadThread.Create(port:integer;comhandle:thandle);
begin
Fport:=port;
Fcomhandle:=comhandle;
FreeOnTerminate := True;
inherited Create(true);
end;

destructor TreadThread.destroy;
begin
inherited destroy;
end;

//执行读串口线程
procedure TreadThread.Execute;
begin
read_commdata;
end;

//增加一个接收数据
procedure treadthread.add_onereceivedata;
var
headreceivelink,tempreceivepoint:preceivelink;
begin
new(tempreceivepoint);
tempreceivepoint^.data:=Fdata;
tempreceivepoint^.next:=nil;
if tempportlink^.receivelink<>nil then
begin
headreceivelink:=tempportlink^.receivelink;
while headreceivelink^.next<>nil do
headreceivelink:=headreceivelink^.next;
headreceivelink^.next:=tempreceivepoint;
tempportlink^.receivecount:=tempportlink^.receivecount+1;
end
else
begin //第一个数据必须为“$A5”才是正确数据,可以改为需要的值
if Fdata<>$A5 then
begin
dispose(tempreceivepoint);
tempportlink^.receivecount:=1;
end
else
begin
tempportlink^.receivelink:=tempreceivepoint;
tempportlink^.receivecount:=1;
end;
end;
if receivecount=11 then //接收的为定长数据11个字符
begin
data_handle //数据处理,自己写
tempportlink^.receivecount:=0;
end;
end;

//接收通讯口数据
procedure treadthread.read_commdata;
var
eventmask:dword;
Clear:Boolean;
Coms:Tcomstat;
cbNum,ReadNumber:cardinal;
lpErrors:cardinal;
Read_Buffer:array[1..512] of byte;
i:integer;
begin
eventmask:=0;
while true do
if (waitcommevent(Fcomhandle,eventmask,overlapped)) then
if (eventmask=ev_rxchar) then
begin
Clear:=Clearcommerror(Fcomhandle,lpErrors,@Coms);
if Clear Then
Begin
cbNum:=Coms.cbInQue;
if ReadFile(Fcomhandle,Read_Buffer,cbNum,ReadNumber,overlapped) then
for i:=1 to cbnum do
begin
Fdata:=read_buffer;
Synchronize(add_onereceivedata);
end;
end;
end;
end;


 
这样行不行?
采取舍弃的方法,就是说发送过来,如果没用就舍弃 可以一直在读,但处不处理可以自行决定
或者独占式 或折多线程

 
我刚从现场出差回来。把SLEEP语句去掉了,程序运行还好。目前等待时间检验。
谢谢JACKYZHANG,你的程序我会仔细研究的。
 
多人接受答案了。
 
后退
顶部