Comm口通讯再请教!(100分)

V

victor

Unregistered / Unconfirmed
GUEST, unregistred user!
今遇到一个问题:

两台计算机通过串口连接通讯,
在9600以上速率时,通讯正常,
但小于此时,如1200bps, 通讯就有问题?
是接收方不能完整地接收,或接收错误.

哪位能解答?

谢谢!
 
可能接受方已锁定速度。
 
32bit试用控件SPcomm ,mscomm
16bit 用Comm
 
你用的什么控件,还是自己写的事件?
注意buffer 的设定
 
双方的速度都一样吗?
 
很简单您可以使用流控制技术解决,CTS-RTS控制,绝对可以解决您的问题,
他会根据缓冲区的大小进行相应的控制收发动作。

对了,你9600通讯是自己编写程序,还是使用现成的通讯软件出问题?
 
用专线贺氏Modem通讯时也遇到这个问题
用自己的通讯程序和现成的通讯软件都不行
 
victor,是否满意答案?
如果满意请结束
 
如果中间无MODEM应检查收发双方是否对串口设置完全一致,包括数据间隔时间
与流量控制,通常采用多线程不会丢数据。
 
如果在发送方用的是时钟,则很可能是时钟间隔设的太短,以至于下一个时钟到来时缓冲区内容没有发送完
 
主机硬中断时间在1200 bps下与9600 bps下相比可能嫌短,
因此输送数据方在有限时间内不能实时完成数据的传送。
 
我现在遇到了一个奇怪的问题:
我用CreateFile以异步方式打开串口(参数中间有File_Flag_Overlapped),
然后我用WriteFile对串口进行写,其中的TOverlapped参数当然是设置好了
的,其hEvent为一个ManualReset的Event,OffSet与OffSetHigh为0.
但是当我调用WriteFile(hComm, strToSend, Length(strToSend),
dwLength, @writeOl)
API函数对串口进行写操作时,每次总是产生ERROR_IO_PENDING错误,在调用
GetOverLappedResult函数时,却返回True,TSR与CTS也是高电平.
我用的是DsrHandShaking(DSR握手),这是怎么回事?
而且我运行两次这个程序打开com1时居然都能成功!
应该串口是独享的呀,而且我调用CreateFile时也设置的是独享模式呀.
 
直接连接9600以下不行
 
CommHandle := CreateFile( PChar(s1),
GENERIC_READ or GENERIC_WRITE,
0, nil,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL ,
0 );
writefile(CommHandle,s1,length(s1)+1,writebyte,nil);

张磊,试试用以上的代码.我是可以的.不用TOVERLAPPED 这结构.
 
guo_qpeter:
首先,多谢了。
此外,为什么WriteFile中间的第三个参数为Length(sl)+1而不是Length(sl)?
另外我已经发现了串口能够共享的问题,那是因为我没有检查CreateFile的返回值,
如果为INVALID_HANDLE_VALUE则CreateFile调用失败。不好意思。我以为会产生
一个异常呢,用了一个try..excpet..end的结构。
另外我想问,如果对串口进行异步操作是否比同步的好?至少不会堵塞其他操作吧。
而且在调用SetCommState时,设置参数老是不成功。
我希望把BaudRate设置为19200,使用DSR握手,把CTS设置为ON,但是总不行。
再次麻烦了。
 
这次把源代码贴上来:
设置并创建一个串口句柄:
try
hComm := CreateFile(PChar(strCommName),
GENERIC_READ or GENERIC_WRITE,
0, //Exclusive Access
nil, //No Security Attribute
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0); //Template File
if hComm=INVALID_HANDLE_VALUE then
raise Exception.Create(strCommName+' Open Failed!');
except
ShowMessage(strCommName+' Open Failed!');
Exit;
end;

try
if not SetCommMask(hComm, EV_RXCHAR) then
raise Exception.Create(strCommName+' Setup Step 1 Failed!');
if not SetupComm(hComm, 4*nBuffLen, 4*nBuffLen) then
raise Exception.Create(strCommName+' Setup Step 1 Failed!');
if not PurgeComm(hComm, PURGE_RXABORT or PURGE_RXCLEAR or
PURGE_TXABORT or PURGE_TXCLEAR) then
raise Exception.Create(strCommName+' Setup Step 1 Failed!');
cto.ReadIntervalTimeout := $ffffffff;
cto.ReadTotalTimeoutMultiplier := 0;
cto.ReadTotalTimeoutConstant := 1000; //1 second
cto.WriteTotalTimeoutMultiplier := 2*CBR_9600 div CBR_19200;
cto.WriteTotalTimeoutConstant := 0;
if not SetCommTimeOuts(hComm, cto) then
raise Exception.Create(strCommName+' Setup Step 1 Failed!');
except
CloseHandle(hComm);
ShowMessage(strCommName+' Setup Step 1 Failed!');
Exit;
end;

try
dcb.DCBlength := SizeOf(TDCB);
if not GetCommState(hComm, dcb) then
raise Exception.Create(strCommName+' Setup Step 2 Failed!');
dcb.DCBlength := SizeOf(TDCB);
dcb.BaudRate := CBR_19200;
dcb.ByteSize := 8;
dcb.Parity := NOPARITY;
dcb.StopBits := ONESTOPBIT;
dcb.XonChar := Chr($11); //Ctrl_Q
dcb.XoffChar := Chr($13); //Ctrl_S
dcb.ErrorChar := Chr(0);
dcb.XonLim := 100;
dcb.XoffLim := 100;
dcbFlag := 1; //Binary must be True
dcbFlag := dcbFlag or 2; //Parity Check True
dcbFlag := dcbFlag or 4; //FOutxCtsFlowCtrl
dcbFlag := dcbFlag or 8; //FOutxDsrFlowCtrl
dcbFlag := dcbFlag or $20; //DtrHandShake
dcbFlag := dcbFlag or $1000; //RtsEnable
dcbFlag := dcbFlag or $800; //Ignore NULL Char
dcb.Flags := dcbFlag;
if not SetCommState(hComm, dcb) then
raise Exception.Create(strCommName+' Setup Step 2 Failed!');
bConnected := True;
except
CloseHandle(hComm);
ShowMessage(strCommName+' Setup Step 2 Failed!');
Exit;
end;

EscapeCommFunction(hComm, SETDTR);
EscapeCommFunction(hComm, SETRTS);
thdDaemon := TCommDaemonThd.Create;

TCommDaemonThd部分:
procedure TCommDaemonThd.Execute;
var
dwEventMask : DWORD;
nLength : integer;
begin
SetCommMask(frmMain.hComm, EV_RXCHAR);
while frmMain.bConnected do
begin
dwEventMask := 0;
WaitCommEvent(frmMain.hComm, dwEventMask, nil);
if ( (dwEventMask and EV_RXCHAR)=EV_RXCHAR ) then //Char Received
repeat
nLength := ReadComm;
Synchronize(ShowSuccess);
until nLength=0;
end;
SetEvent(frmMain.eveClose);
end;

constructor TCommDaemonThd.Create;
begin
FreeOnTerminate := True;
inherited Create(False);
end;

procedure TCommDaemonThd.ShowSuccess;
begin
frmMain.mStatus.Lines.Append(strFile+' Received!');
end;

function TCommDaemonThd.ReadComm;
var
dwErr, dwError, dwLength : DWORD;
commStat : TComStat;
begin
ClearCommError(frmMain.hComm, dwErr, @commStat);
dwLength := min( nBuffLen, commStat.cbInque);
if dwLength>0 then
if not ReadFile(frmMain.hComm, strFile, dwLength, dwLength, @frmMain.readOl) then
begin
if GetLastError=ERROR_IO_PENDING then
begin
while not GetOverLappedResult(frmMain.hComm, frmMain.readOl, dwLength, TRUE) do
begin
dwErr := GetLastError;
if dwErr=ERROR_IO_INCOMPLETE then
continue
else begin
//Show Error
ClearCommError(frmMain.hComm, dwError, @commStat);
//Show Error
end;
end; //end while
end // end if GetLastError...
else begin
//Show Error
ClearCommError(frmMain.hComm, dwError, @commStat);
//Show Error
end;
end; //end if dwLength>0 , end if not ReadFile...
Result := dwLength;
end;

发送部分:
if bConnected then //In fact Always True
begin
strToSend := eSendFile.Text;
bWriteFile := WriteFile(hComm, strToSend, Length(strToSend)+1, dwLength, @writeOl);
if not bWriteFile then
begin
dwErr := GetLastError;
if dwErr=ERROR_IO_PENDING then
begin
while not GetOverLappedResult(hComm, writeOl, dwLength, TRUE) do
begin
dwErr := GetLastError;
if dwErr=ERROR_IO_INCOMPLETE then
continue
else begin
//Show Error
ClearCommError(hComm, dwError, @commStat);
//show Error
end;
end; //end while
//Lines below for debuging
GetCommModemStatus(hComm, dwMStat);
if (dwMStat and MS_DSR_ON)=0 then
mStatus.Lines.Append('DSR Low!')
else if (dwMStat and MS_CTS_ON)=0 then
mStatus.Lines.Append('CTS Low!')
else
mStatus.Lines.Append('Strange Error!');
//Lines Above for Debuging
end // end if GetLastError=...
else begin
//Show Error
ClearCommError(hComm, dwError, @commStat);
mStatus.Lines.Append('Error: '+IntToStr(dwError));
end;
end; //end if not bWriteFile
end; //end if bConnected

此外断开连接是正确的,就不贴了.
请大家分析一下吧,多谢了.
 
我现在已经解决了问题:

说来好笑,似乎把WriteFile, ReadFile中的string
类型改为LPSTR就行了。
但是要如此用:
pchToRead : LPSTR;
pchToRead := LPSTR(LocalAlloc(...));
...//ReadFile
//格式:ReadFile(hComm, pchToRead^, ....);
LocalFree(THandle(pchToRead));
就行了。

在发送方也是一样的。
 
接受答案了.
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
989
SUNSTONE的Delphi笔记
S
顶部