高分求解串口通讯设置(800)(200分)

  • 主题发起人 主题发起人 87150
  • 开始时间 开始时间
8

87150

Unregistered / Unconfirmed
GUEST, unregistred user!
请教
以下是用COMM API 截获的
--------------------------------------------------------------
IRP_MJ_CREATE Options: Open
IOCTL_SERIAL_SET_DTR
IOCTL_SERIAL_CLR_RTS
IOCTL_SERIAL_SET_WAIT_MASK Mask: RXCHAR RLSD ERR
IOCTL_SERIAL_GET_MODEMSTATUS
IOCTL_SERIAL_SET_RTS
IOCTL_SERIAL_GET_MODEMSTATUS
IOCTL_SERIAL_GET_MODEMSTATUS
IOCTL_SERIAL_CLR_RTS
IOCTL_SERIAL_SET_QUEUE_SIZE InSize: 4096 OutSize: 4096
IOCTL_SERIAL_PURGE Purge: TXABORT RXABORT TXCLEAR RXCLEAR
IOCTL_SERIAL_SET_TIMEOUTS RI:-1 RM:0 RC:1000 WM:0 WC:0
IOCTL_SERIAL_GET_BAUD_RATE
IOCTL_SERIAL_GET_LINE_CONTROL
IOCTL_SERIAL_GET_CHARS
IOCTL_SERIAL_GET_HANDFLOW
IOCTL_SERIAL_GET_BAUD_RATE
IOCTL_SERIAL_GET_LINE_CONTROL
IOCTL_SERIAL_GET_CHARS
IOCTL_SERIAL_GET_HANDFLOW
======================================================
IOCTL_SERIAL_SET_BAUD_RATE Rate: 16457
IOCTL_SERIAL_CLR_RTS
IOCTL_SERIAL_SET_DTR
======================================================
IOCTL_SERIAL_SET_LINE_CONTROL StopBits: ERROR Parity: ODD WordLength: 8
IOCTL_SERIAL_SET_CHAR EOF:0 ERR:0 BRK:0 EVT:0 XON:11 XOFF:13
IOCTL_SERIAL_SET_HANDFLOW Shake:1 Replace:0 XonLimit:2048 XoffLimit:512
-----------------------------------------------------------------------------
以上的设置用MSCOMM,SPCOMM,COMPORT都服务实现,我用以下代码
hCommFile := CreateFile
( PChar(s),GENERIC_READ+GENERIC_WRITE,
0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if(hCommFile = INVALID_HANDLE_VALUE)or
(GetFileType( hCommFile )<>FILE_TYPE_CHAR)then exit;

EscapeCommFunction(hCommFile,SETDTR);
EscapeCommFunction(hCommFile,CLRRTS);

fdwEvtMask:=EV_RXCHAR+EV_ERR+EV_RLSD;
setcommmask(hcommfile,fdwEvtMask);
GetCommModemStatus(hcommfile,ModemStat);
EscapeCommFunction(hCommFile,SETRTS);

GetCommModemStatus(hcommfile,ModemStat);
EscapeCommFunction(hCommFile,CLRRTS);

SetupComm(hCommFile,4096,4096);

PurgeComm(hCommFile,PURGE_TXABORT+PURGE_RXABORT+PURGE_TXCLEAR+PURGE_RXCLEAR);

commtimeouts.ReadIntervalTimeout :=4294967295; //setup commtimeout
commtimeouts.ReadTotalTimeoutMultiplier :=0;
commtimeouts.ReadTotalTimeoutConstant :=1000;
commtimeouts.WriteTotalTimeoutMultiplier :=0;
commtimeouts.WriteTotalTimeoutConstant :=0;
SetCommTimeouts(hCommFile,commtimeouts);

fillchar( dcb, sizeof(dcb), 0 ); //setup dcb struct
GetCommState(hCommFile,dcb);

// dcbstr:='16457, O, 8, 2';
// BuildCommDCBW(dcbstr,dcb);
// SetCommState(hCommFile,dcb);

dcb.DCBLength :=sizeof(dcb);
dcb.BaudRate:=16457;
dcb.Flags:=$9C140003;
dcb.XonLim:=2048;
dcb.XoffLim:=512;
dcb.bytesize:=8;
dcb.Parity:=ODDPARITY;//2;
dcb.StopBits:=TWOSTOPBITS;//0;
dcb.XonChar:=#11;
dcb.XoffChar:=#13;
SetCommState(hCommFile,dcb);
出来的结果中
======================================================
IOCTL_SERIAL_SET_BAUD_RATE Rate: 16457
IOCTL_SERIAL_CLR_RTS
IOCTL_SERIAL_CLR_DTR
======================================================

请教如何实现上述COMM API设置结果?
 
我晕,,,哪儿跑来个原始人啊?

最上面的IOCTL_SERIAL_SET_BARUD_RATE什么的严格说起来是个数据。表征不同时候的数据
IOCTL就是IOCTRL,SET_BARUD_RATE设置波特率。其实就是IO的设置波特率的控制符。

因为你用COMM API拦截,所以出现的是底层的东西。

串口通讯,你可以参看SPCOMM的源代码。这是DELPHI的代码。

如果你还想走底层的,那么你参看MSDN的帮助,用C写把。

你的COMM API不是你写的?快点上交。。。。嘿嘿[:D]

 
去 www.51delphi.com 下载SPCOMM,其中的源代码可以给你带来帮助。
 
给你一段吧
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;
.......................
 
Win 9x/nt/2000 中使用GetCommSate 函数获取串口当前配置,使用SetCommStatr 函数从新分配串口资源的各个参数
windows sdk 中有详细的介绍。
 
你截获的是一些IRP的东西。
为什么要截获I/O请求包呢?直接用SPCOMM不就可以了吗???很方便的。到时给你一段代码。
 
下面是我写的一段向串口超市的客户显示牌发送数据的例子:
if Length(Content)<12 then
begin
Comm1:=TComm.Create(Application);
Comm1.StopComm;
Comm1.CommName:=Com;
Comm1.StartComm;
Comm1.BaudRate:=9600;
Comm1.Parity:=None;
Comm1.ByteSize:=_8;
Comm1.StopBits:=_1;
ShowStr:=chr(27)+chr(81)+chr(65)+Content+chr(13);
Sleep(5);
Send:=Comm1.WriteCommData(Pchar(ShowStr),Length(ShowStr));
if Send=false then
begin
Application.MessageBox('显示时出现错误,请检查','错误',MB_OK or MB_ICONERROR);
Comm1.StopComm;
Result:=false;
end;
end
else
begin
Application.MessageBox('您输入的字符长度超过11位','错误',MB_OK or MB_ICONERROR);
Result:=false;
end;
Comm1.StopComm;
Result:=true;
 
我不懂你为什么要用那么底层的东西比较做什么。
你说的 Comm Api 捕获是用什么软件,是不是 PortMon?
 
高手啊,佩服,写的程序我差点看懂了,哈哈
 
给你个方法用google搜索一下很多
 
没看懂要问什么?!
 
接受答案了.
 
后退
顶部