在CSDN上很久没人理,还是回到大富翁来。(还是串口通信问题)(150分)

  • 主题发起人 主题发起人 moodboy
  • 开始时间 开始时间
语法没有错,但发送后什么也看不到。
多谢你一直关注!
 
qdyoung,能否抽点时间调试一下自发自收?
 
怎么自发自收,串口1连串口2?我没直连线
不可能串口1连串口1
你调试一下看发送的字符对不对,然后检查硬件
 
qdyoung,你把一个串口的2、3脚短接就可自收自发了。
硬件不会错,我用MScomm正在调试,能正确收发。只是速度好慢!:(
想不通我的程序到底哪里有错。
 
我就用下面的代码调试,结果一点反应也没有。我在Memo2里输入12345,看到发送的s为3132333435,
发送的字符应该没错啊,只是没接收?
procedure TsendForm.Button2Click(Sender: TObject);
var
s: string;
j:integer;
text:string;
begin
text:=memo2.text;
s := '';
for j := 1 to Length(Text) do
s := s + IntTohex(Byte( Text[j]),2);
Comm1.WriteCommData(PChar(s), Length(s));
end;

procedure TsendForm.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
sBuffer, s: string;
i:integer;
begin
sBuffer := '';
SetLength(sBuffer, BufferLength);
StrLCopy(PChar(sBuffer), Buffer, BufferLength);
s := '';
for i := 0 to BufferLength div 2 do
s := s +chr(strtoint('$'+Copy(sBuffer, i * 2 + 1, 2)));
memo1.Text :=s;
ShowMessage(s);
end;

 
发送对了,hex(1),hex(2)...
 
我这儿没有条件测试,我以前用spcomm很正常的,下面是以上pas代码的form代码
你看看我的属性设置:
object WriteCardForm: TWriteCardForm
Left = 263
Top = 277
BorderIcons = [biSystemMenu]
BorderStyle = bsSingle
Caption = 'WriteCardForm'
ClientHeight = 104
ClientWidth = 330
Color = clBtnFace
Font.Charset = ANSI_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = '宋体'
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
OnCreate = FormCreate
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 12
object Comm: TComm
CommName = 'COM1'
BaudRate = 9600
ParityCheck = True
Outx_CtsFlow = False
Outx_DsrFlow = False
DtrControl = DtrEnable
DsrSensitivity = False
TxContinueOnXoff = False
Outx_XonXoffFlow = False
Inx_XonXoffFlow = False
ReplaceWhenParityError = False
IgnoreNullChar = False
RtsControl = RtsHandshake
XonLimit = 500
XoffLimit = 500
ByteSize = _7
Parity = Odd
StopBits = _1
XonChar = #17
XoffChar = #19
ReplacedChar = #0
ReadIntervalTimeout = 100
ReadTotalTimeoutMultiplier = 0
ReadTotalTimeoutConstant = 0
WriteTotalTimeoutMultiplier = 0
WriteTotalTimeoutConstant = 0
OnReceiveData = CommReceiveData
Left = 24
Top = 32
end
end
 
各位高手,问题相当严重!
我用一个VB的调试工具,发现单片机发送完数据后,它就接收完了,在Memo上显示出来。
而我的程序则在单片机发送完后很久才有反应,而且------我的程序竟然没有接收完数据!
我以64个字节为单位校验,发现后面的经常出错,经查,原来是有数据丢失,但用VB的工具
又没有数据丢失。是不是读取缓冲区的问题(MScomm)?
那位愿帮我,我还有几百分全给他,看看我前面的贴就知道了,决不食言。
关于spcomm的问题简直让我吐血!它默认的端口是COM2。不过还是有点问题:
执行到 s := s +chr(strtoint('$'+Copy(sBuffer, i * 2 + 1, 2))); 后提示
“$ is not a valid integer value”
我是不是该走人了?我真的没办法了,希望大家帮帮我。
 
先不要急,我认为不应该使用SPCOMM,干脆用TCOMPORT算了,MSCOMM的控件在Delphi上用
有问题的
 
哎!我建议你最好不要用控件了,我好像看过书说MScomm在接收大数据量时可能发生错误,
最好使用底层的API函数吧,给你一段代码,编译一下就行了.
unit comunate;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Buttons, StdCtrls, ComCtrls;

const
WM_COMMNOTIFY = WM_USER + 1; // 通讯消息

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
OpenDialog1: TOpenDialog;
Label1: TLabel;
BitBtn1: TBitBtn;
RichEdit1: TRichEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private
{Private declarations}
procedure WMCOMMNOTIFY(var Message :TMessage);message WM_COMMNOTIFY;
public
{Public declarations}
end;

var
Form1: TForm1;

implementation
{$R *.DFM}
var
hNewCommFile,Post_Event: THandle;
Read_os : Toverlapped;
Receive :Boolean;
ReceiveData : Dword;

procedure AddToMemo(Str:PChar;Len:Dword); // 接收的数据送入显示区
begin
str[Len]:=#0;
Form1.RichEdit1.Text:=Form1.RichEdit1.Text+StrPas(str);
end;

procedure CommWatch(Ptr:Pointer);stdcall; // 通讯监视线程
var
dwEvtMask,dwTranser : Dword;
Ok : Boolean;
Os : Toverlapped;
begin
Receive :=True;
FillChar(Os,SizeOf(Os),0);
Os.hEvent :=CreateEvent(nil,True,False,nil); // 创建重叠读事件对象
if Os.hEvent=null then
begin
MessageBox(0,'Os.Event Create Error !','Notice',MB_OK);
Exit;
end;
if (not SetCommMask(hNewCommFile,EV_RXCHAR)) then
begin
MessageBox(0,'SetCommMask Error !','Notice',MB_OK);
Exit;
end;
while(Receive) do
begin
dwEvtMask:=0;
// 等待通讯事件发生
if not WaitCommEvent(hNewCommFile,dwEvtMask,@Os) then
begin
if ERROR_IO_PENDING=GetLastError then
GetOverLappedResult(hNewCommFile,Os,dwTranser,True)
end;
if ((dwEvtMask and EV_RXCHAR)=EV_RXCHAR) then
begin
// 等待允许传递WM_COMMNOTIFY通讯消息
WaitForSingleObject(Post_event,INFINITE);
// 处理WM_COMMNOTIFY消息时不再发送WM_COMMNOTIFY消息
ResetEvent(Post_Event);
// 传递WM_COMMNOTIFY通讯消息
Ok:=PostMessage(Form1.Handle,WM_COMMNOTIFY,hNewCommFile,0);
if (not Ok) then
begin
MessageBox(0,'PostMessage Error !','Notice',MB_OK);
Exit;
end;
end;
end;
CloseHandle(Os.hEvent); // 关闭重叠读事件对象
end;

procedure TForm1.WMCOMMNOTIFY(var Message :TMessage); // 消息处理函数
var
CommState : ComStat;
dwNumberOfBytesRead : Dword;
ErrorFlag : Dword;
InputBuffer : Array [0..1024] of Char;
begin
if not ClearCommError(hNewCommFile,ErrorFlag,@CommState) then
begin
MessageBox(0,'ClearCommError !','Notice',MB_OK);
PurgeComm(hNewCommFile,Purge_Rxabort or Purge_Rxclear);
Exit;
end;
if (CommState.cbInQue>0) then
begin
fillchar(InputBuffer,CommState.cbInQue,#0);
// 接收通讯数据
if (not ReadFile(hNewCommFile,InputBuffer,CommState.cbInQue,dwNumberOfBytesRead,@Read_os)) then
begin
ErrorFlag := GetLastError();
if (ErrorFlag <> 0) and (ErrorFlag <> ERROR_IO_PENDING) then
begin
MessageBox(0,'ReadFile Error!','Notice',MB_OK);
Receive :=False;
CloseHandle(Read_Os.hEvent);
CloseHandle(Post_Event);
CloseHandle(hNewCommFile);
Exit;
end
else begin
WaitForSingleObject(hNewCommFile,INFINITE); // 等待操作完成
GetOverlappedResult(hNewCommFile,Read_os,dwNumberOfBytesRead,False);
end;
end;
if dwNumberOfBytesRead>0 then
begin
Read_Os.Offset :=Read_Os.Offset+dwNumberOfBytesRead;
ReceiveData := Read_Os.Offset;
// 处理接收的数据
AddToMemo(InputBuffer,dwNumberOfBytesRead);
end;
end;
// 允许发送下一个WM_COMMNOTIFY消息
SetEvent(Post_Event);
end;

procedure TForm1.Button1Click(Sender: TObject); // 打开文件用于发送
begin
if OpenDialog1.Execute then
begin
Button3.Enabled :=False;
Button4.Enabled :=False;
RichEdit1.Lines.LoadFromFile(OpenDialog1.FileName);
Form1.Caption := IntToStr(RichEdit1.GetTextLen);
end;
Button1.Enabled :=False;
end;

procedure TForm1.Button2Click(Sender: TObject); // 发送数据
var
dcb : TDCB;
Error :Boolean;
dwNumberOfBytesWritten,dwNumberOfBytesToWrite,
ErrorFlag,dwWhereToStartWriting : DWORD;
pDataToWrite : PChar;
write_os: Toverlapped;
begin
Form1.Caption :='';
// 打开通讯端口COM2
hNewCommFile:=CreateFile( 'COM2',GENERIC_WRITE,0,nil, OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0 );
if hNewCommFile = INVALID_HANDLE_VALUE then
MessageBox(0,'Error opening com port!','Notice',MB_OK);
SetupComm(hNewCommFile,1024,1024); // 设置缓冲区大小及主要通讯参数
GetCommState( hNewCommFile,dcb);
dcb.BaudRate :=9600;
dcb.ByteSize :=8;
dcb.Parity :=NOPARITY;
dcb.StopBits := ONESTOPBIT;
Error := SetCommState( hNewCommFile, dcb );
if (not Error) then
MessageBox(0,'SetCommState Error!','Notice',MB_OK);
dwWhereToStartWriting := 0;
dwNumberOfBytesWritten := 0;
dwNumberOfBytesToWrite :=RichEdit1.GetTextLen;
if (dwNumberOfBytesToWrite=0) then
begin
ShowMessage('Text Buffer is Empty!');
Exit;
end
else begin
pDataToWrite:=StrAlloc(dwNumberOfBytesToWrite+1);
try
RichEdit1.GetTextBuf(pDataToWrite,dwNumberOfBytesToWrite);
Label1.Font.Color :=clRed;
FillChar(Write_Os,SizeOf(write_os),0);
// 为重叠写创建事件对象
Write_Os.hEvent := CreateEvent(nil,True,False,nil);
SetCommMask(hNewCommFile,EV_TXEMPTY);
Label1.Caption:='正在发送数据...!';
repeat
Label1.Repaint;
// 发送通讯数据
if not WriteFile( hNewCommFile,pDataToWrite[dwWhereToStartWriting],
dwNumberOfBytesToWrite,dwNumberOfBytesWritten,@write_os ) then
begin
ErrorFlag :=GetLastError;
if ErrorFlag<>0 then
begin
if ErrorFlag=ERROR_IO_PENDING then
begin
WaitForSingleObject(Write_Os.hEvent,INFINITE);
GetOverlappedResult(hNewCommFile,Write_os,dwNumberOfBytesWritten,False);
end
else begin
MessageBox(0,'WriteFile Error!','Notice',MB_OK);
Receive :=False;
CloseHandle(Read_Os.hEvent);
CloseHandle(Post_Event);
CloseHandle(hNewCommFile);
Exit;
end;
end;
end;
Dec(dwNumberOfBytesToWrite, dwNumberOfBytesWritten );
Inc( dwWhereToStartWriting, dwNumberOfBytesWritten );
until (dwNumberOfBytesToWrite <= 0); // Write the whole thing!
Form1.Caption:=IntToStr(dwWhereToStartWriting);
finally
StrDispose(pDataToWrite);
end;
CloseHandle(hNewCommFile);
end;
Label1.Font.Color :=clBlack;
Label1.Caption:='发送成功!';
Button1.Enabled :=True;
Button3.Enabled :=True;
Button4.Enabled :=True;
end;

procedure TForm1.Button3Click(Sender: TObject); // 接收处理
var
Ok : Boolean;
dcb : TDCB;
com_thread: Thandle;
ThreadID:DWORD;
begin
ReceiveData :=0;
Button1.Enabled :=False;
Button2.Enabled :=False;
RichEdit1.Clear;
// 打开COM2
hNewCommFile:=CreateFile( 'COM2',GENERIC_READ,0, nil, OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0 );
if hNewCommFile = INVALID_HANDLE_VALUE then
begin
MessageBox(0,'Error opening com port!','Notice',MB_OK);
Exit;
end;
Ok:=SetCommMask(hNewCommFile,EV_RXCHAR);
if (not Ok) then
begin
MessageBox(0,'SetCommMask Error!','Notice',MB_OK);
Exit;
end;
SetupComm(hNewCommFile,1024,1024);
GetCommState( hNewCommFile, dcb );
dcb.BaudRate :=9600;
dcb.ByteSize :=8;
dcb.Parity :=NOPARITY;
dcb.StopBits := ONESTOPBIT;
Ok := SetCommState( hNewCommFile, dcb );
if (not Ok) then MessageBox(0,'SetCommState Error!','Notice',MB_OK);
FillChar(Read_Os,SizeOf(Read_Os),0);
Read_Os.Offset := 0;
Read_Os.OffsetHigh := 0;
// Create Event for Overlapped Read
Read_Os.hEvent :=CreateEvent(nil,true,False,nil);
if Read_Os.hEvent=null then
begin
CloseHandle(hNewCommFile);
MessageBox(0,'CreateEvent Error!','Notice',MB_OK);
Exit;
end;
// Create Event for PostMessage
Post_Event:=CreateEvent(nil,True,True,nil);
if Post_Event=null then
begin
CloseHandle(hNewCommFile);
CloseHandle(Read_Os.hEvent);
MessageBox(0,'CreateEvent Error!','Notice',MB_OK);
Exit;
end;
// 建立通信监视线程
Com_Thread:=CreateThread(nil,0,@CommWatch,nil,0,ThreadID);
if (Com_Thread=0) then
MessageBox(Handle,'No CraeteThread!',nil,mb_OK);
EscapeCommFunction(hNewCommFile,SETDTR);
label1.Font.Color :=clRed;
Label1.Caption:='正在接收数据...!';
end;

procedure TForm1.Button4Click(Sender: TObject); // 停止通讯处理
begin
Label1.Font.Color :=clBlack;
Label1.Caption:='infomation';
Form1.Caption := IntToStr(ReceiveData);
Receive :=False;
CloseHandle(Read_Os.hEvent);
CloseHandle(Post_Event);
CloseHandle(hNewCommFile);
Button1.Enabled :=True;
Button2.Enabled :=True;
end;

end.
 
卸健飞天,你原来做项目的时候有没有这种情况?我用你的接收代码也是一样的慢。是不是
我有哪个属性没设置不对?请指点重要属性设置。
还有,难道VB调试工具没有用自带的MScomm?我学Delphi三个月了,进步很慢,现在转用API
我不知道来得及否,因为还要涉及到CRC校验的问题,我好不容易才搞定字符串的校验啊。
 
VB是微软的,API也是微软的,它,当然能玩的转了.转用API也并不太难,只是要了解一下函数的意义.
CRC校验只是一些字符的处理,移植起来完全没问题.
 
我还是先把贴结了吧。若还不能搞定,下星期再发贴,希望大家继续支持。
 
多人接受答案了。
 
卸健飞天:
我在richedit1中输入1234而已,点发送后再点接收处理,怎么很久都还在处理中?
它把接收的数据怎样处理?我看不懂。
请各位继续,有价值的我会开贴给分。
 
后退
顶部