在Delphi中不通过第三方组件,直接利用系统函数(或者汇编语言)直接控制串口进行通讯。比如:我现在对串口发一个字节的数据,
有起始位(1 bit)、数据位(8 bit)、停止位(1 bit )、校验位(1 bit),这个比特流就11个数据位。
我怎样在发送这个数据包后改变“校验位(1 bit)”,也就是在其它通过此串口要得到的数据报以前,可改变这个数据包。说形象点就是,我要发一个字节的数据到串口,系统会把这个8ibt的数据组织成:  起始位(1 bit)+数据位(8 bit)+停止位(1 bit )+校验位(1 bit)=数据报(11 bit) 的数据流,我想在系统发送到串口时,我改变这个数据流。也就是,把校验位按照我的意图置任意位。不知能否实现。

解决方案 »

  1.   

    这不是通常意义的串口通信了,我想有两个办法可以处理
    1、Hook API
    2、自己编写驱动程序
      

  2.   

    不知道是我不明白你要表達的, 還是你理解根本是錯的>>我怎样在发送这个数据包后改变“校验位(1 bit)”,可改变这个数据包。
    我知道用vxd 是可以的, hook api 應該也可!問題是, 你改變了 校验位 後, 另一方收到的數據包, 校驗不正确, 可能會被丟棄的, 
    如果你真想做到這麼底層, 你應該選擇C++ 之類的開發工具, 而不應該選delphi
      

  3.   

    我先把我公司现在设计的产品大致描述一下:
    因为这个产品涉及到多个下位机(也就是多个单片机),比方说有六个单片机,其中有两类,上位机发送报文下去后,下面六个单片机根据检验位来决定是否执行。关于Delphi,我觉得应该可以解决这个问题。
      

  4.   

    汇编的话必须在98一下用,api函数就只能用CreateFile(),
    WriteFile,ReadFile了,自己查查资料,不难的
      

  5.   

    unit Global;interface
    uses
      Windows,Forms,Classes,SysUtils;Const
      rc_SerialError = 0;
      rc_CommError = 1;
      rc_NoDevice = 2;
      rc_HaveConnect = 3;Type
      TParity = ( None, Odd, Even, Mark, Space );
      TStopBits = ( _1, _1_5, _2 );
      TByteSize = ( _5, _6, _7, _8 );
      TDtrControl = ( DtrEnable, DtrDisable, DtrHandshake );
      TRtsControl = ( RtsEnable, RtsDisable, RtsHandshake, RtsTransmissionAvailable );  TCommState = Record
        FBaudRate:          DWORD;
        FParityCheck:       Boolean;
        FOutx_CtsFlow:      Boolean;
        FOutx_DsrFlow:      Boolean;
        FDtrControl:        TDtrControl;
        FDsrSensitivity:    Boolean;
        FTxContinueOnXoff:  Boolean;
        FOutx_XonXoffFlow:  Boolean;
        FInx_XonXoffFlow:   Boolean;
        FReplaceWhenParityError:    Boolean;
        FIgnoreNullChar:    Boolean;
        FRtsControl:        TRtsControl;
        FXonLimit:          WORD;
        FXoffLimit:         WORD;
        FByteSize:          TByteSize;
        FParity:            TParity;
        FStopBits:          TStopBits;
        FXonChar:           AnsiChar;
        FXoffChar:          AnsiChar;
        FReplacedChar:      AnsiChar;
      end;
    function StartComm(CommName:String;commstate:TCommState):Thandle;
    procedure StopComm(Hcomm:Thandle);
    function ReadComm(hComm:Thandle;SendStr:string;FirstWait,MiddleWait:Dword;
                      var Buffer:string;var dwBytesRead:DWORD):Word;implementation//********************************************/
    //  Open a Serial Port                        /
    //  The CommName Should Has Style of 'COMn'   /
    //  The return of INVALID_HANDLE_VALUE        /
    //  indicate the opening of serial port failue/
    //********************************************/
    function StartComm(CommName:String;commstate:TCommState):Thandle;
    var
      dcb:            Tdcb;
    begin
       Result :=CreateFile(Pchar(CommName),GENERIC_READ or GENERIC_WRITE,
                     0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
       if Result <> INVALID_HANDLE_VALUE then
       begin
         if GetFileType(Result) <> FILE_TYPE_CHAR then
         begin
           CloseHandle(Result);
           Result := INVALID_HANDLE_VALUE;
           Exit;
         end;
         if not SetupComm( Result, 4096, 4096 ) then
         begin
           CloseHandle(Result);
           Result := INVALID_HANDLE_VALUE;
           Exit;
         end;
       end else Exit;
       GetCommState( Result, dcb );   dcb.BaudRate := commstate.FBaudRate;   dcb.Flags := 1;       // Enable fBinary   if commstate.FParityCheck then
          dcb.Flags := dcb.Flags or 2;          // Enable parity check   // setup hardware flow control   if commstate.FOutx_CtsFlow then
          dcb.Flags := dcb.Flags or 4;   if commstate.FOutx_DsrFlow then
          dcb.Flags := dcb.Flags or 8;   if commstate.FDtrControl = DtrEnable then
          dcb.Flags := dcb.Flags or $10
       else if commstate.FDtrControl = DtrHandshake then
            dcb.Flags := dcb.Flags or $20;   if commstate.FDsrSensitivity then
          dcb.Flags := dcb.Flags or $40;   if commstate.FTxContinueOnXoff then
          dcb.Flags := dcb.Flags or $80;   if commstate.FOutx_XonXoffFlow then
          dcb.Flags := dcb.Flags or $100;   if commstate.FInx_XonXoffFlow then
          dcb.Flags := dcb.Flags or $200;   if commstate.FReplaceWhenParityError then
          dcb.Flags := dcb.Flags or $400;   if commstate.FIgnoreNullChar then
          dcb.Flags := dcb.Flags or $800;   if commstate.FRtsControl = RtsEnable then
          dcb.Flags := dcb.Flags or $1000
       else if commstate.FRtsControl = RtsHandshake then
            dcb.Flags := dcb.Flags or $2000
       else if commstate.FRtsControl = RtsTransmissionAvailable then
            dcb.Flags := dcb.Flags or $3000;   dcb.XonLim := commstate.FXonLimit;
       dcb.XoffLim := commstate.FXoffLimit;   dcb.ByteSize := Ord( commstate.FByteSize ) + 5;
       dcb.Parity := Ord( commstate.FParity );
       dcb.StopBits := Ord( commstate.FStopBits );   dcb.XonChar := commstate.FXonChar;
       dcb.XoffChar := commstate.FXoffChar;   dcb.ErrorChar := commstate.FReplacedChar;   SetCommState( Result, dcb )
    end;//********************************************/
    //  Close a Serial Port                       /
    //********************************************/
    procedure StopComm(Hcomm:Thandle);
    begin
      if Hcomm <> INVALID_HANDLE_VALUE then
        Closehandle(Hcomm);
    end;//**********************************************************/
    //send a command string to serial port to recive its answer /
    //  sendstring is the command string                        /
    //  the recieved string is saved in buffer                  /
    //  the dwbytesread will return  the number bytes of read   /
    //  set the dwbytesread to zero indicate no needing of      /
    //  recieve only send                                       /
    //  hcomm is the handle of the serial port                  /
    //
    //**********************************************************/
    function ReadComm(hComm:Thandle;SendStr:string;FirstWait,MiddleWait:Dword;
                      var Buffer:string;var dwBytesRead:DWORD):Word;
    var
      timeout:TCommTimeouts;
      dwWhereToStartWriting: DWORD;
      dwNumberOfBytesWritten:DWORD;
      dwNumberOfBytesToWrite:DWORD;
      Inchar: Char; //接收缓冲区
      st,et:Cardinal;
      HaveRecieved:boolean;
      internal:word;
    begin
      Result := rc_SerialError;
      PurgeComm( hComm, PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR
                 or PURGE_RXCLEAR ) ;
      timeout.ReadIntervalTimeout := MAXDWORD;
      timeout.ReadTotalTimeoutMultiplier := 0;
      timeout.ReadTotalTimeoutConstant := 0;
      SetCommTimeOuts(hComm,timeout);  //send the command string
      dwWhereToStartWriting := 1;
      dwNumberOfBytesWritten := 0;
      dwNumberOfBytesToWrite := Length(sendstr);
      repeat
        WriteFile( hComm,
                   sendstr[dwWhereToStartWriting],
                   dwNumberOfBytesToWrite,
                   dwNumberOfBytesWritten,
                   nil);
        Dec( dwNumberOfBytesToWrite, dwNumberOfBytesWritten );
        Inc( dwWhereToStartWriting, dwNumberOfBytesWritten )
      until (dwNumberOfBytesToWrite <= 0);  if dwBytesRead=0 then Exit;  //No Need Recieving  buffer := '';        //clear the buffer
      dwBytesRead := 0;    //initialize the number bytes of read to zero
      st := GetTickCount;
      HaveRecieved := false;
      while true do
      begin
        if ReadFile(hComm,InChar,1,dwNumberOfBytesToWrite,nil) then
        begin
          if dwNumberOfBytesToWrite > 0 then
          begin
            HaveRecieved := true;
            buffer := buffer + InChar;
            Inc(dwBytesRead);
            st := GetTickCount;
          end;
          et := GetTickCount;
          if HaveRecieved then
            internal := MiddleWait
          else
            internal := FirstWait;
          if ( et - st ) > internal then
          begin
            if internal = FirstWait then
              Result := rc_NoDevice
            else
              Result := rc_HaveConnect;
          end;
        end else begin
          Result := rc_CommError;
          Exit;
        end;
      end;
    end;
    Initializationend.
      

  6.   

    像你得应用,只需将 FParity设为MARK或SPACE即可