求助,串口通讯,

tetsuya 2003-10-16 08:21:48
那位兄弟,可以帮我做个通讯接口的动态连接库,,我这个方面不熟,,考勤软件又要明天交货。急死我了!!
协议如下:
设日期时间:
1、随机发送20个’0’-‘9’之间的数
2、发机器号('A'-'J')。
3、发’?’ 。
4、 12位的日期时间数据(ASC码,加延时),如:'0','0','1','2','3','0','0',8'','3','0','1','2'。表示2000年12月30日8点30分12秒
5、2位的星期,如星期1用’0’,’1’来表示
6、接收到应答信号'Y' 。则表示时间已设好。
7、退出。
接收数据:
1、随机发送25个’0’-‘9’之间的数
2、发机器号('A'-'J')。
3、发'>' 。
4、发6位的年月数据(ASC码,加延时),如: '1','9','9','8','1','2'。表示1998年12月
5、接收连机应答'Y' 。若不是则退出。
6、接收数据应答'Y' 。若不是则退出(为'N'则表示没有当有)。
7、接收小于或等于260字节的数据块。
格式为0xBB + 数据 + 0xBB(或0xCC) + 检验和(2字节)
其中 :整个块为二进制数据
:0xBB为数据块起始和结束标志
:0xCC为数据传输结束标志
:检验和为数据(不加标志位)的二进制和对256的余数
8、如果数据正确接收则发块应答Y ,保存数据,继续过程6,直到结束(收到0xCC或在5秒之内只收到
1个0xBB)。否则发非应答'N' ,错误计数器加1(如超过5次,则整个过程无效,退出),继续过程5。
数据格式
(例子): 3A3A393831323031 30303031 30383330 30303032 30383330
3A3A393831323032 30303031 31343030 30303032 31343030
注: 1、空隔只是为了查看方便,实际上没有
2、上述情况为1号和2号卡在98年月12月1号-2号的考勤数据,列表则为:
卡号/日期 1998/12/01 1998/12/02
0001 08:30 12:00
0002 08:30 12:00
Evan_G@163.com
...全文
89 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
shiufurong007 2003-11-13
  • 打赏
  • 举报
回复
up
jpyc 2003-10-23
  • 打赏
  • 举报
回复
http://218.56.11.178:8020/web/technology.aspx

->串口通讯应用程序的解决方案


http://218.56.11.178:8020/web/technology.aspx

-> 下载基地->例程-硬件控制->串口通讯控制器/spcom事例程序

->控件-硬件控制->TurboPower Async Professional/spcom
lxhong1980 2003-10-23
  • 打赏
  • 举报
回复

发送D1 应答为 CC 握手成功 再发送其他
unit TiQianL_Set_Frm;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, Buttons,IniFiles, SPComm;

type
TForm_Set_TiQianLiang = class(TForm)
Panel1: TPanel;
GroupBox1: TGroupBox;
Bbtn_Exit: TBitBtn;
Bbtn_Sure: TBitBtn;
GroupBox2: TGroupBox;
Edt_Right: TEdit;
EdT_Left: TEdit;
Pnl_Left: TPanel;
Pnl_Right: TPanel;
Comm1: TComm;
procedure Bbtn_ExitClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Bbtn_SureClick(Sender: TObject);
procedure EdT_LeftKeyPress(Sender: TObject; var Key: Char);
procedure Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form_Set_TiQianLiang: TForm_Set_TiQianLiang;
sRece1:string; //接收到的字符串
rbuf:array[1..20] of byte;//把接收到的二进制转化为整数,存储在数组里
pDataToWrite:array[1..20] of char; // 要发送的,转化为字符
LDate:Integer;//发送字符长度
implementation

uses Globe_Frm;

{$R *.dfm}

procedure TForm_Set_TiQianLiang.Bbtn_ExitClick(Sender: TObject);
begin
pDataToWrite[1]:=chr(byte($F3));
LDate:=1;
Comm1.Inx_XonXoffFlow:=false;
Comm1.Outx_XonXoffFlow:=false;
Comm1.WriteCommData(@(pDataToWrite),LDate);
Close;
end;

procedure TForm_Set_TiQianLiang.FormCreate(Sender: TObject);
var
IniF:TIniFile;
begin
IniF:=TIniFile.Create('.\HJKZ.ini');
EdT_Left.Text:=IniF.ReadString('TiQianLSet','Left','10');
EdT_Right.Text:=IniF.ReadString('TiQianLSet','Right','20');
IniF.Free;
end;

procedure TForm_Set_TiQianLiang.Bbtn_SureClick(Sender: TObject);
var
IniF:TIniFile;
dtTmp:TDateTime;
begin
IniF:=TIniFile.Create('.\HJKZ.ini');
IniF.WriteString('TiQianLSet','Left',EdT_Left.Text);
IniF.WriteString('TiQianLSet','Right',EdT_Right.Text);
IniF.Free;

pDataToWrite[1]:=chr(byte($D1));
LDate:=1;
Comm1.Inx_XonXoffFlow:=false;
Comm1.Outx_XonXoffFlow:=false;
Comm1.WriteCommData(@(pDataToWrite),LDate);

dtTmp:=Now;
while ((not (sRece1='CC'))do
begin
Application.ProcessMessages;
end;

if sRece1<>'CC' then
begin
Application.MessageBox('握手失败!','提示',MB_OK+MB_ICONINFORMATION);
Exit;
end;

pDataToWrite[1]:=chr(byte($A8));
pDataToWrite[2]:=chr(byte($02));
pDataToWrite[3]:=chr(byte (StrToInt('$'+ Edt_Left.Text )));
pDataToWrite[4]:=chr(byte (StrToInt('$'+ Edt_Right.Text)));
LDate:=4;
Comm1.Inx_XonXoffFlow:=false;
Comm1.Outx_XonXoffFlow:=false;
Comm1.WriteCommData(@(pDataToWrite),LDate);
end;

procedure TForm_Set_TiQianLiang.EdT_LeftKeyPress(Sender: TObject;
var Key: Char);
begin
if((key<#48 ) or(key>#57)) and (key<>#8) then
begin
key:=#0;
end;
end;

procedure TForm_Set_TiQianLiang.Comm1ReceiveData(Sender: TObject;
Buffer: Pointer; BufferLength: Word);
var
i:integer;
begin
sRece1:='';
move(buffer^,pchar((@rbuf)^),bufferlength);
for i:=1 to bufferlength do
begin
sRece1:=sRece1+ inttohex(rbuf[i],2);
end;
end;

procedure TForm_Set_TiQianLiang.FormShow(Sender: TObject);
begin
Comm1.CommName:=Glb_Com;
Comm1.StartComm;
end;

procedure TForm_Set_TiQianLiang.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
Comm1.StopComm;
end;

end.
OrientOh 2003-10-16
  • 打赏
  • 举报
回复
可以找我,我有一个已封装好的动态库,当然不免费哪!
yaven365 2003-10-16
  • 打赏
  • 举报
回复

procedure TComm.FreeComm;
begin
if hCommFile=0 then exit;

//Now close the comm port handle.
PurgeComm(hCommFile, PURGE_RXABORT + PURGE_RXCLEAR
+ PURGE_TXABORT + PURGE_TXCLEAR);
CloseHandle(hCommFile);
hCommFile := 0;
bOpened := False;
end;

function TComm.WriteData(pDataToWrite: PChar; dwSizeofDataToWrite: DWORD): Boolean;
var
nSent: DWORD;
begin
Result := WriteFile(hCommFile, pDataToWrite^, dwSizeofDataToWrite,
nSent, Nil);
end;

procedure TComm.SendStr(str: String);
begin
str := str+ Chr(13) + Chr(10);
WriteData(PChar(str), Length(str));
end;

function TComm.ReadData(pBuffer: PChar; BufferSize: DWORD): boolean;
var
nRead: DWORD;
begin
Result := ReadFile(hCommFile, pBuffer^, BufferSize, nRead, Nil);
end;

//
// FUNCTION: GetModemState
// PURPOSE: Read the state of modem input pin right now
// RETURN VALUE:
// A DWORD variable containing one or more of following codes:
//
// Value Meaning
// ---------- -----------------------------------------------------------
// MS_CTS_ON The CTS (clear-to-send) signal is on.
// MS_DSR_ON The DSR (data-set-ready) signal is on.
// MS_RING_ON The ring indicator signal is on.
// MS_RLSD_ON The RLSD (receive-line-signal-detect) signal is on.
//
// If this comm have bad handle or not yet opened, the return value is 0
//
function TComm.GetModemState : DWORD;
var
dwModemState : DWORD;
begin
if not GetCommModemStatus(hCommFile, dwModemState) then
Result := 0
else
Result := dwModemState
end;

function TComm.BytesInInQue: DWORD;
var
stat: TCOMSTAT;
errs: DWORD;
begin
ClearCommError(hCommFile, errs, @stat);
Result := stat.cbInQue;
end;

function TComm.BytesInOutQue: DWORD;
var
stat: TCOMSTAT;
errs: DWORD;
begin
ClearCommError(hCommFile, errs, @stat);
Result := stat.cbOutQue;
end;

function TComm.WaitForBytes(Bytes: DWORD; TimeLen: DWORD): boolean;
var
time1, time2: DWORD;
begin
time1 := getTickCount;
time2 := time1;
while (BytesInInQue<Bytes) and (hCommFile<>0) and ((time2-time1)<TimeLen)
do begin
Application.ProcessMessages;
time2 := GetTickCount;
end;
if BytesInInQue>=Bytes then Result := True
else Result := False;
end;

procedure TComm.ClearComm;
begin
PurgeComm(hCommFile, PURGE_TXABORT or PURGE_RXABORT or
PURGE_TXCLEAR or PURGE_RXCLEAR);
end;

function TComm.WaitOK(TimeLen: DWORD): boolean;
var
time1, time2: DWORD;
flag: integer;
TempByte: Byte;
begin
flag := 0;
time1 := GetTickCount();
time2 := time1;
Result := False;
while (flag<>2) and ((time2-time1)<TimeLen) do
begin
if not WaitForBytes(1, 1000) then exit;
ReadData(@TempByte, 1);
if flag=0 then
begin
if TempByte=Ord('O') then flag := 1
end else begin
if TempByte=Ord('K') then
begin
flag := 2;
Result := True;
end else flag := 0; //clear flag
end;
time2 := GetTickCount();
end;
end;

end.
yaven365 2003-10-16
  • 打赏
  • 举报
回复

implementation

constructor TComm.Create(AOwner: TComponent);
begin
inherited Create( AOwner );

hCommFile := 0;
bOpened := False;

// Default size of the Input Buffer used by this code.
INQUESIZE := 40960;
OUTQUESIZE := 8192;
end;

destructor TComm.Destroy;
begin
FreeComm;
inherited Destroy;
end;

function TComm.InitComm(ThisCommName: string; BaudRate,DataByte,StopByte,ParityByte: integer): Boolean;
var
dcb: Tdcb;
begin
//Are we already doing comm?
if hCommFile<>0 then
begin
InitComm := False;
exit;
end;

hCommFile := CreateFile( PChar(ThisCommName),
GENERIC_READ or GENERIC_WRITE,
0, {not shared}
nil, {no security ??}
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);

if hCommFile=INVALID_HANDLE_VALUE then
begin
hCommFile := 0;
InitComm := False;
exit;
end;

//Is this a valid comm handle?
if GetFileType(hCommFile)<>FILE_TYPE_CHAR then
begin
CloseHandle(hCommFile);
hCommFile := 0;
InitComm := False;
exit;
end;

//Querying then setting the comm port configurations.
GetCommState(hCommFile, dcb);

dcb.BaudRate := BaudRate;
dcb.ByteSize := DataByte; //number of bits/byte, 4-8
dcb.Parity := ParityByte; //0-4=no,odd,even,mark,space
dcb.StopBits := StopByte; //0,1,2 = 1,1.5,2

{ dcb.Flags := 1; // Enable fBinary

if FParityCheck then
dcb.Flags := dcb.Flags or 2; // Enable parity check

if FOutx_CtsFlow then
dcb.Flags := dcb.Flags or 4;

if FOutx_DsrFlow then
dcb.Flags := dcb.Flags or 8;

if FDtrControl = DtrEnable then
dcb.Flags := dcb.Flags or $10;
else if FDtrControl = DtrHandshake then
dcb.Flags := dcb.Flags or $20;

if FDsrSensitivity then
dcb.Flags := dcb.Flags or $40;

if FTxContinueOnXoff then
dcb.Flags := dcb.Flags or $80;

if FOutx_XonXoffFlow then
dcb.Flags := dcb.Flags or $100;

if FInx_XonXoffFlow then
dcb.Flags := dcb.Flags or $200;

if FReplaceWhenParityError then
dcb.Flags := dcb.Flags or $400;

if FIgnoreNullChar then
dcb.Flags := dcb.Flags or $800;

if FRtsControl = RtsEnable then
dcb.Flags := dcb.Flags or $1000;
else if FRtsControl = RtsHandshake then
dcb.Flags := dcb.Flags or $2000
else if FRtsControl = RtsTransmissionAvailable then
dcb.Flags := dcb.Flags or $3000;
}
if not SetCommState(hCommFile, dcb) then
begin
CloseHandle(hCommFile);
hCommFile := 0;
InitComm := False;
exit;
end;

if not SetupComm(hCommFile, INQUESIZE, OUTQUESIZE) then
begin
CloseHandle(hCommFile);
hCommFile := 0;
InitComm := False;
exit;
end;

//purge any information in the buffer
PurgeComm(hCommFile, PURGE_TXABORT or PURGE_RXABORT or
PURGE_TXCLEAR or PURGE_RXCLEAR);

InitComm := True;
bOpened := True;
CommName := ThisCommName;
end;
yaven365 2003-10-16
  • 打赏
  • 举报
回复
最近太忙了,不然就帮你写一些,这些api的代码

给你,自己看看改改!

unit MyComm;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

const
//
// Modem Event Constant
//
ME_CTS = 1;
ME_DSR = 2;
ME_RING = 4;
ME_RLSD = 8;

type
TComm = class( TComponent )
private
hCommFile: THandle;
public
bOpened: boolean;
CommName: string;
INQUESIZE, OUTQUESIZE: integer;

constructor Create(AOwner: TComponent); override;
destructor Destroy; override;

function InitComm(ThisCommName: string; BaudRate,DataByte,StopByte,ParityByte: integer): Boolean;
procedure FreeComm;

function WriteData(pDataToWrite: PChar; dwSizeofDataToWrite: DWORD): Boolean;
function ReadData(pBuffer: PChar; BufferSize: DWORD): boolean;
function BytesInInQue: DWORD;
function BytesInOutQue: DWORD;
function WaitForBytes(Bytes: DWORD; TimeLen: DWORD): boolean;
procedure ClearComm;
function GetModemState: DWORD;

procedure SendStr(str: String);

function WaitOK(TimeLen: DWORD): boolean; //wait for OK till timeLen(in seconds)
end;

const
// This is the message posted to the WriteThread
// When we have something to write.
PWM_COMMWRITE = WM_USER+1;

implementation
tetsuya 2003-10-16
  • 打赏
  • 举报
回复
:(
yaven365 2003-10-16
  • 打赏
  • 举报
回复
你直接调用api函数吧,应该不是很难,难的只是调试
tetsuya 2003-10-16
  • 打赏
  • 举报
回复
写了,后我自己来,我及时在线
yaven365 2003-10-16
  • 打赏
  • 举报
回复
老大,这个东西没有硬件,没有调试环境,没谁能做出来

除非特别熟悉,否则怎么也得2个礼拜左右!
tetsuya 2003-10-16
  • 打赏
  • 举报
回复
ding
saien 2003-10-16
  • 打赏
  • 举报
回复
不是很难,将业务封装一个类,然后利用spComm控件即可。
tetsuya 2003-10-16
  • 打赏
  • 举报
回复
谁能帮我解释一下,传过来传过去的东西因该是这么样的萨,

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧