高分寻求原码,关于串口通讯!(100分)

  • 主题发起人 主题发起人 pingpingniu
  • 开始时间 开始时间
P

pingpingniu

Unregistered / Unconfirmed
GUEST, unregistred user!
首次接触串口通讯!见笑!
需求:两台PC,一台模拟硬件设备,接受协议发送数据,另一台就是发送协议接收数据的机器,用CPORT来实现;或者用一台机器上的两个串口来模拟,请提供帮助
 
1、阅读协议
2、按说明书设置串口
3、用其他的串口调试工具测试协议,弄清每一个字节的含义
4、动手开始编写
5、确认接受到数据,并作相应处理
 
清说详细一点好吗?
另外,积分选错了,我是用400分来求帮助的!
所以,只要解决了我的问题,高分送上!
 
这还不详细啊,至差我帮你做了[:D][:)][8D]

按照我说的方法一条一条来撒

如果产品有维护软件,用串口监视程序看一下,更简单了
 
大侠,请提供至少是伪码也好,因为我是想通过这个来学习学习,我真的很菜!:P
 
如果你没有cport 的例子,以下是控件中带的example.
可以参考。
unit ComMainForm;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, CPort, CPortCtl;

type
TForm1 = class(TForm)
ComPort: TComPort;
Memo: TMemo;
Button_Open: TButton;
Button_Settings: TButton;
Edit_Data: TEdit;
Button_Send: TButton;
NewLine_CB: TCheckBox;
Panel1: TPanel;
Bt_Store: TButton;
Bt_Load: TButton;
ComLed1: TComLed;
ComLed2: TComLed;
ComLed3: TComLed;
ComLed4: TComLed;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
ComLed5: TComLed;
ComLed6: TComLed;
Label1: TLabel;
Label6: TLabel;
procedure Button_OpenClick(Sender: TObject);
procedure Button_SettingsClick(Sender: TObject);
procedure Button_SendClick(Sender: TObject);
procedure ComPortOpen(Sender: TObject);
procedure ComPortClose(Sender: TObject);
procedure ComPortRxChar(Sender: TObject; Count: Integer);
procedure Bt_LoadClick(Sender: TObject);
procedure Bt_StoreClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button_OpenClick(Sender: TObject);
begin
if ComPort.Connected then
ComPort.Close
else
ComPort.Open;
end;

procedure TForm1.Button_SettingsClick(Sender: TObject);
begin
ComPort.ShowSetupDialog;
end;

procedure TForm1.Button_SendClick(Sender: TObject);
var
Str: String;
begin
Str := Edit_Data.Text;
if NewLine_CB.Checked then
Str := Str + #13#10;
ComPort.WriteStr(Str);
end;

procedure TForm1.ComPortOpen(Sender: TObject);
begin
Button_Open.Caption := 'Close';
end;

procedure TForm1.ComPortClose(Sender: TObject);
begin
if Button_Open <> nil then
Button_Open.Caption := 'Open';
end;

procedure TForm1.ComPortRxChar(Sender: TObject; Count: Integer);
var
Str: String;
begin
ComPort.ReadStr(Str, Count);
Memo.Text := Memo.Text + Str;
end;

procedure TForm1.Bt_LoadClick(Sender: TObject);
begin
ComPort.LoadSettings(stRegistry, 'HKEY_LOCAL_MACHINE/Software/Dejan');
// ComPort.LoadSettings(stIniFile, 'e:/Test.ini');
end;

procedure TForm1.Bt_StoreClick(Sender: TObject);
begin
// ComPort.StoreSettings(stIniFile, 'e:/Test.ini');
ComPort.StoreSettings(stRegistry, 'HKEY_LOCAL_MACHINE/Software/Dejan');
end;

end.
 
说详细一点,数据文件在模拟硬件的机器上,就是说发送协议(包含一个地址),一旦受到请求数据的协议,模拟硬件的机器就会到相应的地址找到数据,再发送回去。这样是否应该在两台机器上各有一个程序,且发送数据时,两个程序都必须启动,就有点像Socket一样?
 
如果是这样的话,那么,模拟硬件的机器上的这个程序怎么写?
 
两台机器上都应各有一个程序,模拟机上的程序的接口与通讯规则应尽量与硬件的通讯相同,你只要把两者之间的通讯数按照规则发送过去就就行,串口接到相关数据后再执行相关的代码.
 
yingwei,那么模拟机上的串口号和发送请求PC上的串口号是定成一样的吗?如果一样,那如果在同一台机器上模拟两个又怎么办?
 
串口号在程序当中是可设置的,就是说:com1,com2的通讯是一样的。如果要在同一台机上模拟的前提是你的机子上有两上串口,然后再把普通串口通讯进行改接:即把通讯线的一头的2,3脚进行互换就可以了。
 
这是com1,com2的通讯的例子
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.

 
给个email我,发一段给你看看
 
app2001:
现在我的问题出现在,当我用Cport同时发几条信息时,它收到的信息就不再是一条一条收了,而是变成了一个消息串传过来!而且我发现Cport在收数据时只能8位一收!请帮我解决这个问题,谢谢!
 
我没有cport呀,所以没发瞧,我想要给你看的是另外一个例子,有讲解的,你要不要了
 
ok,pingpingniu@163.net,thank u!
 
我倒是有个收发的例子,cport做的,明天找给你吧。
 
收藏此问题,学习中.........!
 
CPort的确是8位收一次,我的程序收发的数据比较复杂,你改一下就能适应你的要求了,现发给你。
 
发给你了,注意查收
 
后退
顶部