300分求助delphi串口通信问题 ( 积分: 300 )

  • 主题发起人 主题发起人 loverofangel1
  • 开始时间 开始时间
L

loverofangel1

Unregistered / Unconfirmed
GUEST, unregistred user!
各位大侠,本人要在4天之内完成一个校园一卡通项目的前置机模块,主要功能是和中心服务器进行通信,校对时钟,获取设备列表和黑名单等,采用Socket通信,同时还要和终端进行通信,获取消费记录,采用485通信。由于我对串口通信知之甚少,实在无奈,在大富翁上查的资料看的也是晕头转向,时间太短,所以非常非常着急,希望哪位大侠能救我于危难之中。本来打算倾尽所有送500,但最多只能300,所以对于帮助我的大侠,我会再找机会送出剩下的分数,如果您的帮助能让我完成工作,我会将另外一个帐号的500分全部奉上,绝不食言!
我请教以下问题:
1。MSCOMM,SPCOMM,CPORT这三个究竟哪个好,我应该用哪个?
2。哪位大侠能否发给我现成的代码可以让我学习。就是尤其是delphi关于485通信的代码。Socket的我看过一些,但是485的我不清楚。比如前置机程序用Socket与中心服务程序通信,下载黑名单,同时,他可以轮询下位的10个终端,采用485通信,获取消费记录,然后将获取的消费记录发送到中心服务程序。如果能有这些完整的代码就最好了,如果可以的话,给我发到loverofangel@163.com,在下万分感谢,一定送分!!!!!!!!!!
 
各位大侠,本人要在4天之内完成一个校园一卡通项目的前置机模块,主要功能是和中心服务器进行通信,校对时钟,获取设备列表和黑名单等,采用Socket通信,同时还要和终端进行通信,获取消费记录,采用485通信。由于我对串口通信知之甚少,实在无奈,在大富翁上查的资料看的也是晕头转向,时间太短,所以非常非常着急,希望哪位大侠能救我于危难之中。本来打算倾尽所有送500,但最多只能300,所以对于帮助我的大侠,我会再找机会送出剩下的分数,如果您的帮助能让我完成工作,我会将另外一个帐号的500分全部奉上,绝不食言!
我请教以下问题:
1。MSCOMM,SPCOMM,CPORT这三个究竟哪个好,我应该用哪个?
2。哪位大侠能否发给我现成的代码可以让我学习。就是尤其是delphi关于485通信的代码。Socket的我看过一些,但是485的我不清楚。比如前置机程序用Socket与中心服务程序通信,下载黑名单,同时,他可以轮询下位的10个终端,采用485通信,获取消费记录,然后将获取的消费记录发送到中心服务程序。如果能有这些完整的代码就最好了,如果可以的话,给我发到loverofangel@163.com,在下万分感谢,一定送分!!!!!!!!!!
 
我个人感觉spcomm比较好,不过,如果你使用的终端设备超过10个的话,也就是说你用了多串口卡,建议你用pcomm,spcomm不支持10以上的端口号
 
终端是餐饮或者水控的,估计都要几十个呢,pcomm我不了解,那个cport又如何?
哪位大侠有程序源代码啊?能不能给小弟一份咯?:((((
 
SPCOMM控件本身好用,还有源代码,我比较喜欢这个控件
 
我这有pcomm的动态链接库和示例及帮助说明,你可以加我 q 313366,我传给你
 
delphi关于485通信的代码------不要研究了
买块研华或moxa的232/485转换卡就可以了,爽呆你,232的代码可以一点不改 !

楼上那位说:spcomm不支持10以上的端口号 ---错误!
可以的,但要改成 //./COM255的写法!
 
SPCOMM与cport264都不错
好象APRO更厉害啊
 
我觉得差不多,就看你熟悉程度.各有各的特点
 
我一直用APRO,感觉不错。入门很容易
 
485通信也就是读写串口,跟你的Sock原理差不多
发指令,接受指令
 
我刚问了,下位的终端,比如20个售饭机,是采用总线式的连接,用了一个232到485的转换器,但是我对232编程也不知道啥啊,哪里有资料或者代码?谢谢
 
1如果你知道与硬件的通讯协议的话,那就直接向串口收发
数据就可以,具体是用mscomm,pcomm,api大致都差不多,看你
比较熟悉那个.
2.上位机软件对下面的是232还是485没什么关系啊!
3.轮循的话可要考率响应速度、及其数据并发的问题哟!
你们是用哪家的机器啊,怎么好象和我们的很象啊!
qq:364076660
 
SPCOMM用着顺手,COM1到COM255都没问题
 
谁有SPCOMM与232编程的代码?
 
各位大虾,如何实现pc的串口与外置的RS-232接口进行通信,能否给我有关的源程序代码和简单的注释。希望能有人帮我,差不多我就要结贴了。
 
做了些删减,你大概看一下吧
补充一下:RichEdit显示 00H 会报错,不特别要求显示效果的话用Memo好一些。
interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,WINSOCK, Math, Spin, ExtCtrls,OleCtrls,
ComCtrls, Grids, Buttons, Menus, Mask, SPComm;


type
TForm1 = class(TForm)
RichEdit1: TRichEdit;
RichEdit2: TRichEdit;
Comm1: TComm;
BitBtn9: TBitBtn;
BitBtn2: TBitBtn;
procedure BitBtn9Click(Sender: TObject);

procedure Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);

procedure BitBtn2Click(Sender: TObject);

procedure FormClose(Sender: TObject; var Action: TCloseAction);

private
public
end;

var
Form1: TForm1;

implementation
{$R *.DFM}
{ TForm1 }


//------------------串口相关---------------
//打开串口
procedure TForm1.BitBtn9Click(Sender: TObject);
var i,j:integer;
ss:string;
begin
if BitBtn9.Caption='打开串口'//是否已经打开
then
begin
comm1.CommName:=ComboBox1.Text;//串口名
comm1.BaudRate:=StrToInt(ComboBox2.Text);//波特率
Try comm1.StartComm//尝试打开
except//未打开处理
BitBtn9.Caption:='打开串口';
ShowMessage('串口'+Comm1.CommName+'不存在或被占用');
Comm1.StopComm; // 关闭串口
exit;
end;
//打开后
BitBtn9.Caption:='关闭串口';
end
else
begin
BitBtn9.Caption:='打开串口';
Comm1.StopComm; // 关闭串口

end;
end;


//串口接收
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var i:integer;
rxbuf:array of byte;
s:string;
begin
setlength(rxbuf,bufferlength);
move(buffer^,rxbuf[0],bufferlength);
//ASC显示
s:='';
for i:=0 to bufferlength-1 do s:=s+Char(rxbuf);
RichEdit2.Lines.Add(s);
END;



//发送
procedure TForm1.BitBtn2Click(Sender: TObject);
var s:string;
begin
s:=RichEdit1.text;
Comm1.WriteCommData(PAnsiChar(s),Length(s));
end;

//退出
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if BitBtn9.Caption='关闭串口' then Comm1.StopComm; // 串口
end;

end.
 
我也是做IC卡设备公司的,加QQ43205955,我们可以互相学习学习
 
检索串口通讯有很多这样的例子的。
 
谁有SPCOMM与232编程的代码
--------------------------
unit PTCom232;
{
设计:张世平
时间:2005-6-24
注意:需要Config232.ini文件配合
}
interface
uses
StrUtils,
Classes,
windows,
Dialogs,
WinSock,
ScktComp,
IniFiles,
SysUtils,
ExtCtrls,
SPComm,
GlobalDefine;
resourcestring
StatusDateTimeFormat = 'yyyy/mm/dd" - "hh:nn:ss:zzz AM/PM';

type
TCFG = record

CommName: pchar;
BaudRate: integer;
ByteSize: pchar;
StopBits: pchar;
Parity: pchar;
NeedWriteLog: integer;
end;

PMyPobject = ^MyPobject;
MyPobject = record
Msg: PByte;
Len: Integer
end;

TCom232 = class
private
AComm: TComm;
TimerSend: TTimer; //如果com232 通,并且发送队列有数据,则发送

procedure TimerSendTimer(Sender: tobject);
procedure CommReceiveData(Sender: TObject; Buffer: Pointer; BufferLength: Word);
procedure CommReceiveError(Sender: TObject; EventMask: Cardinal);
function LoadUDPParameter(): BOOLEAN;
function SetUDPParameter(): BOOLEAN;

public
constructor Create();
destructor DESTROY; override;
function Open(): boolean;
function Execute(): BOOLEAN;
procedure WriteLog(ErrStr: string);
end;

function FreeBuf(Buffer: PTThreadList): Boolean;
function ReadFromBuf(var MyObject: PMyPobject; var
Buffer: PTThreadList): Boolean;
function HaveData(Buffer: PTThreadList): Boolean;
function WriteToBuf(var MyObject: PMyPobject; var
Buffer: PTThreadList; Capacity: Integer): Boolean;

procedure Log(LogFilename: string; ErrStr: string);
procedure SendLog(ErrStr: string);
procedure RecLog(ErrStr: string);

procedure HexStrToBytes(hHexStr: string; pbyteArray: Pointer);
procedure BytesToHexStr(var hHexStr: string; pbyteArray: PByte; InputLength: WORD);


const
iCapacity = 1024;
CONFIG = 'CONFIG232.INI';
SelfLog = 'log_232.Log';
SendDataQueue_log = 'log_232_send.log';
ReceiveDataQueue_Log = 'log_232_Rec.log';


var SendDataQueue: PTThreadList; //待发送数据队列
ReceiveDataQueue: PTThreadList; //接收数据
CurPath: string;
CFG: TCFG;


implementation

procedure HexStrToBytes(hHexStr: string; pbyteArray: Pointer);
{pbyteArray must point to enough memory to hold the output}
var
i, j: WORD;
tempPtr: PChar;
twoDigits: string[2];
begin
tempPtr := pbyteArray;
j := 1;
for i := 1 to (Length(hHexStr) div 2) do begin
twoDigits := Copy(hHexStr, j, 2);
Inc(j, 2);
PByte(tempPtr)^ := StrToInt('$' + twoDigits);
Inc(tempPtr);
end; {for}
if ((Length(hHexStr) mod 2) = 1) then
begin
twoDigits := '0' + RightStr(hHexStr, 1);
Inc(j, 2);
PByte(tempPtr)^ := StrToInt('$' + twoDigits);
end;

end;

procedure BytesToHexStr(var hHexStr: string; pbyteArray: PByte; InputLength: WORD);
const
HexChars: array[0..15] of Char = '0123456789ABCDEF';
var
i, j: WORD;
begin
hHexStr := '';
j := 1;
for i := 1 to InputLength do begin
hHexStr := hHexStr + Char(HexChars[pbyteArray^ shr 4]);
inc(j);
hHexStr := hHexStr + Char(HexChars[pbyteArray^ and 15]);
inc(j);
inc(pbyteArray);
end;

end;


procedure Log(LogFilename: string; ErrStr: string);
var
LogFile: TextFile;
begin
if CFG.NeedWriteLog <> 1 then exit;
AssignFile(LogFile, LogFilename);
if FileExists(LogFilename) then Append(LogFile)
else Rewrite(LogFile);
Writeln(LogFile, ErrStr);
CloseFile(LogFile);
end;


procedure TCom232.WriteLog(ErrStr: string);
begin
LOG(CurPath + selflog, DateTimeToStr(now) + ': ' + ErrStr);
end;


procedure SendLog(ErrStr: string);
begin
LOG(CurPath + SendDataQueue_log, ErrStr);
end;

procedure RecLog(ErrStr: string);
begin
LOG(CurPath + ReceiveDataQueue_Log, ErrStr);
end;


function GETINIkey(IniFile: pchar; MAINKEY: pchar; SUBKEY: pchar): pchar; stdcall; //export;
var
myini: Tinifile;
s: string;
begin
// curpath:=extractfilepath(Application.exename);
myini := Tinifile.Create(IniFile);
// result := PCHAR(Myini.readString(mainkey, subkey, ''));
s := myini.readString(MAINKEY, SUBKEY, '');
getmem(result, length(s) + 1);
strcopy(result, pchar(s));
myini.Free;
end;

constructor TCom232.Create();
begin
if not LoadUDPParameter() then EXIT;

New(SendDataQueue);
SendDataQueue^ := TThreadList.Create;

New(ReceiveDataQueue);
ReceiveDataQueue^ := TThreadList.create;


TimerSend := TTimer.Create(nil); //如果winsock 通,并且发送队列有数据,则发送
TimerSend.Enabled := false;
TimerSend.Interval := 1; //时间可以自己定义
TimerSend.OnTimer := TimerSendtimer;

ACOMM := TCOMM.Create(nil);
ACOMM.OnReceiveData := CommReceiveData;
Acomm.OnReceiveError := CommReceiveError;

if not SetUDPParameter() then EXIT;

end;

function TCom232.Open(): boolean;
begin
result := false;
try
AComm.StartComm();
except
writelog(AComm.CommName + ' 打开失败,请确信电缆正确...');
exit;
end;
//是否判断已经打开,重复打开
// writelog(AComm.CommName + ' 打开失败...');
result := true;
end;

destructor TCom232.DESTROY;
begin
if TimerSend <> nil then
begin
TimerSend.Enabled := FALSE;
TimerSend.Free;
end;
if ACOMM <> nil then
begin
Acomm.StopComm;
AComm.Free;
end;
WRITELOG('COM232 服务正常关闭!');
end;

function TCom232.Execute: BOOLEAN;
begin
timerSend.Enabled := true;
RESULT := TRUE;
end;

function TCom232.LoadUDPParameter(): BOOLEAN;
var inifile: pchar;
begin
RESULT := FALSE;
inifile := pchar(CurPath + CONFIG);
try
CFG.CommName := GETINIkey(inifile, 'com232', 'CommName');
CFG.BaudRate := strtoint(GETINIkey(inifile, 'com232', 'BaudRate'));
CFG.ByteSize := GETINIkey(inifile, 'com232', 'ByteSize');
CFG.StopBits := GETINIkey(inifile, 'COM232', 'StopBits');
CFG.Parity := GETINIkey(inifile, 'COM232', 'Parity');
CFG.NeedWriteLog := STRTOINT(GETINIkey(inifile, 'COM232', 'NeedWriteLog'));
RESULT := TRUE;
except
RESULT := FALSE;
EXIT;
end;

if (CFG.ByteSize <> '_5') and (CFG.ByteSize <> '_6') and (CFG.ByteSize <> '_7') and (CFG.ByteSize <> '_8') then
begin
Writelog(config + ' is error:bytesize must in [_5, _6, _7, _8] . . ');
result := false;
EXIT;
end;
if (CFG.StopBits <> '_1') and (CFG.StopBits <> '_1_5') and (CFG.StopBits <> '_2') then
begin
Writelog(config + ' is error:StopBits must in [_1, _1_5, _2] . . ');
result := false;
EXIT;
end;
//None, Odd, Even, Mark, Space
if (CFG.Parity <> 'None') and (CFG.Parity <> 'Odd') and (CFG.Parity <> 'Even') and (CFG.Parity <> 'Mark') and (CFG.Parity <> 'Space') then
begin
Writelog(config + ' is error:Parity must in [None, Odd, Even, Mark, Space] . . ');
result := false;
EXIT;
end;
end;

function TCom232.SetUDPParameter(): BOOLEAN;
begin
RESULT := FALSE;
try
WriteLog('COM232 全双工通信服务正在加载...');
WriteLog('commname:' + cfg.CommName);
WriteLog('BaudRate:' + inttostr(cfg.BaudRate));
WriteLog('ByteSize:' + cfg.ByteSize);
WriteLog('StopBits:' + cfg.StopBits);
WriteLog('Parity:' + cfg.Parity);
AComm.CommName := '//./'+cfg.CommName;
AComm.BaudRate := cfg.BaudRate;

if cfg.ByteSize = '_5' then AComm.ByteSize := tbytesize(0);
if cfg.ByteSize = '_6' then AComm.ByteSize := tbytesize(1);
if cfg.ByteSize = '_7' then AComm.ByteSize := tbytesize(2);
if cfg.ByteSize = '_8' then AComm.ByteSize := tbytesize(3);

if cfg.StopBits = ' _1' then AComm.StopBits := TStopBits(0);
if cfg.StopBits = ' _1_5' then AComm.StopBits := TStopBits(1);
if cfg.StopBits = ' _2' then AComm.StopBits := TStopBits(2);

if cfg.Parity = 'None' then AComm.Parity := TParity(0);
if cfg.Parity = 'Odd' then AComm.Parity := TParity(1);
if cfg.Parity = 'Even' then AComm.Parity := TParity(2);
if cfg.Parity = 'Mark' then AComm.Parity := TParity(3);
if cfg.Parity = 'Space' then AComm.Parity := TParity(4);

writelog('Set Com232 Parameter success...');
RESULT := TRUE;
except
writelog('Set Com232 Parameter fail...');
RESULT := FALSE;
end;
end;



procedure TCom232.TimerSendTimer(Sender: tobject);
var
wmsg: PMyPobject;
TmpStr: string;
buf: array of byte;
begin
if not HaveData(SendDataQueue) then exit;
//现在如何确信com依然打开呢?否则readfrombuf 读了就被删除了
try
wmsg := nil;
if not ReadFromBuf(wmsg, SendDataQueue) then exit;
if wmsg = nil then exit; //如果成功会自动从队列删除
// buf[0]:=byte($A1);
// buf[1]:=byte($A2);
// buf[2]:=byte($A3);
// buf[3]:=byte($f1);
//AComm.WriteCommData(@buf[0],4);
//winsock.SendBuf(wmsg.msg^, wmsg.Len);
setlength(buf, wmsg.Len);
copymemory(buf, wmsg.Msg, wmsg.Len);
AComm.WriteCommData(@buf[0], wmsg.Len);
BytesToHexStr(TmpStr,wmsg.Msg, wmsg.Len);
//也可以BytesToHexStr(TmpStr, @buf[0], wmsg.Len);完全正确
SendLog(TmpStr);
finally
if wmsg <> nil then
begin
if wmsg^.Msg <> nil then
FreeMem(wmsg.Msg, wmsg.Len);
Dispose(wmsg);
end;
end;
end;

procedure TCom232.CommReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
TmpStr: string;
wmsg: PMyPobject;
begin
new(wmsg);
getmem(wmsg.Msg, BufferLength);
CopyMemory(wmsg.Msg, Buffer, BufferLength); // wmsg.Msg^ := MsgOfWrite^;
WriteToBuf(wmsg, ReceiveDataQueue, BufferLength);
BytesToHexStr(TmpStr, wmsg.Msg, BufferLength);
RecLog(Tmpstr);
end;

procedure TCom232.CommReceiveError(Sender: TObject; EventMask: Cardinal);
begin
writelog(ACOMM.CommName + ' ReceiveError...');
end;

function FreeBuf(Buffer: PTThreadList): Boolean;
var
tmpList: TList;
wmsg: pMyPobject;
begin
result := true;
tmpList := Buffer^.LockList;
while tmpList.Count > 0 do
begin
wmsg := PMyPobject(tmpList.Last);
tmpList.Delete(tmplist.Count - 1);
tmplist.Pack;
if wmsg <> nil then
begin
if wmsg^.Msg <> nil then
FreeMem(wmsg.Msg, wmsg.Len);
Dispose(wmsg);
end;
end
end;

function ReadFromBuf(var MyObject: PMyPobject; var
Buffer: PTThreadList): Boolean;
var
tmpList: TList;
begin
result := true;
tmpList := Buffer^.LockList;
try
if tmpList.Count > 0 then
begin
MyObject := tmpList.First;
tmpList.Delete(0);
tmpList.Pack;
end
else
begin
MyObject := nil;
result := false;
end;
finally
begin
Buffer^.UnlockList;
end;
end;

end;

function HaveData(Buffer: PTThreadList): Boolean;
var
tmpList: TList;
begin
tmpList := Buffer^.LockList;
if tmpList.Count > 0 then
result := true
else
result := false;
Buffer^.UnlockList;
end;

function WriteToBuf(var MyObject: PMyPobject; var
Buffer: PTThreadList; Capacity: Integer): Boolean;
var
tmpList: TList;
wmsg: PMyPobject;
begin

tmpList := Buffer^.LockList;
try
while tmpList.Count >= Capacity do
begin
wmsg := tmpList.First;
tmpList.Delete(0);
tmpList.Pack;
if wmsg <> nil then
begin
if wmsg^.Msg <> nil then
FreeMem(wmsg.Msg, wmsg.Len);
Dispose(wmsg);
end;
end;
tmpList.Add(MyObject);
tmpList.Pack;
finally
begin
Buffer^.UnlockList;
end;
end;
result := true;
end;



end.
 
后退
顶部