unit GetData;interface{ Units used by this unit }
uses
   Windows,
   Messages,
   SysUtils,
   Dialogs,
   ExtCtrls ;   { 调用此函数可以得到重量 ,调用成功返回true,失败返回false,取回的重量在sWeight
   内,返回值为string 型 }
function GetWeight(var sWeight:string;tmp:integer=4):boolean;implementationconst
   { Current port number 此值为串口号,根据实际情况可能要修改}
   int_PortNumber = 1;
   { Current baud rate }
   int_BaudRate = 1200;
   { Current Data bits per byts }
   int_DataBits = 7 ;
   { Current Stop bits per byte }
   int_StopBits = 2;
   { Current Parity (No/Odd/Even/Mark/Space = 0-4) }
   byt_Parity = 2 ;
   { Response terminator string }
   sInTerminator = chr($0A);   //chr($02);
var
   { Handle of currently open port }
   int_PortHandle: Cardinal =INVALID_HANDLE_VALUE;
   //int_PortHandle: LongInt =INVALID_HANDLE_VALUE;
   { Set true when a timeout occurs }
   boo_TimerExpired: Boolean;
   { True while port is blocked, waiting for response }
   boo_InUse: Boolean = False;
   { Wait for the timer to time-out when polling for response }
   boo_WaitForResp : boolean = False;
procedure CloseComm;
begin
 if int_PortHandle <> INVALID_HANDLE_VALUE then
   begin
     CloseHandle(int_PortHandle);
     int_PortHandle := INVALID_HANDLE_VALUE;
   end;
end;function OpenComm: Boolean;
var
 str_Com: String;
 dcbPort: TDCB; {device control block }
 commtimeouts:TCommTimeouts;
begin
{ close port if open already }
 if int_PortHandle <> INVALID_HANDLE_VALUE then CloseComm;
{ try to open the port }
   str_Com := 'COM' + IntToStr(int_PortNumber);
   int_PortHandle := CreateFile(PChar(str_Com),
   GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,LongInt(0));
{ If created stream ok, set the baud rate and other parameters }
   if (int_PortHandle <> INVALID_HANDLE_VALUE) then
    begin
      SetupComm(int_PortHandle,1000,1000);
      if GetCommState(int_PortHandle, dcbPort) then
       begin
       { fill in the fields of the structure }
         dcbPort.BaudRate := int_BaudRate;
        dcbPort.ByteSize := int_DataBits;
       dcbPort.Parity := byt_Parity;
       dcbPort.StopBits := int_StopBits;
       dcbPort.Flags := 0 ;
         dcbPort.Flags := dcbPort.Flags or $10 or $1000;
         { UNSUPPORTED flag bit fields:
 dcb_Binary, dcb_Parity, dcb_OutxCtsFlow, dcb_fOutxDsrFlow,
 dcb_fOutX, dcb_fInX, dcb_DtrFlow, dcb_RtsFlow}
    SetCommState(int_PortHandle, dcbPort);
        end;
        GetCommTimeouts( int_PortHandle, commtimeouts );
        commtimeouts.ReadIntervalTimeout:=100;
        commtimeouts.ReadTotalTimeoutMultiplier:= 0;
        commtimeouts.ReadTotalTimeoutConstant:= 0;
        commtimeouts.WriteTotalTimeoutMultiplier:= 0;
        commtimeouts.WriteTotalTimeoutConstant:= 0;
        SetCommTimeouts(int_PortHandle,commtimeouts );
    end;
    { return True if handle is valid }
    Result := (int_PortHandle <> INVALID_HANDLE_VALUE);
end;
{------------------------------------------------------------------------------
Flush the port by reading any characters in the queue
}
procedure Flush;
begin
 if int_PortHandle <> INVALID_HANDLE_VALUE then
  begin
   PurgeComm(int_PortHandle, PURGE_TXABORT);
   PurgeComm(int_PortHandle, PURGE_RXABORT);
   PurgeComm(int_PortHandle, PURGE_TXCLEAR);
   PurgeComm(int_PortHandle, PURGE_RXCLEAR );
  end;
end;
{------------------------------------------------------------------------------
Write a string out the COM port, return true if all chars written
}
function WriteComm(const sData: String): Boolean;
var
 dwCharsWritten: DWord;
 dcbPort : TDCB ;
begin
 Result := False; { default to error return }
 if GetCommState(int_PortHandle, dcbPort) then
  begin
  { fill in the fields of the structure }
  dcbPort.Flags := dcbPort.Flags  or $10;
  SetCommState(int_PortHandle, dcbPort);
  end;
  if int_PortHandle <> INVALID_HANDLE_VALUE then
   begin
    dwCharsWritten := 0;
    flush;
    WriteFile(int_PortHandle, PChar(sData)^, Length(sData), dwCharsWritten, nil);
    if dwCharsWritten = Cardinal(Length(sData)) then Result := True;
   end;
end;

解决方案 »

  1.   

    {------------------------------------------------------------------------------
    Return the number of bytes waiting in the queue
    }
    function GetInCount: LongInt;
    var
     statPort: TCOMSTAT;
     dwErrorCode: DWord;
    // b:BOOLEAN;
    begin
     Result := 0;
     if int_PortHandle <> INVALID_HANDLE_VALUE then
      begin
       if (ClearCommError(int_PortHandle, dwErrorCode, @statPort))then
        Result := statPort.cbInQue
       else
        Result := 0;
      end;
    end;function ReadComm: String;
    const
     BUF_LEN = 1024;
    var
     cbCharsAvailable, cbCharsRead: DWord;
     boo_FoundTerm: Boolean;
     sBuffer: String;
     TimeCount : integer;
     dcbPort: TDCB;
    begin
     Result:='';
     { check boo_InUse in case of rentrancy }
     if not boo_InUse then
      begin
       boo_InUse := True;
       if GetCommState(int_PortHandle, dcbPort) then
        begin
        { fill in the fields of the structure }
         dcbPort.Flags := dcbPort.Flags  or $1000;
         SetCommState(int_PortHandle, dcbPort);
        end;
        if int_PortHandle <> INVALID_HANDLE_VALUE then
         begin
         { if no terminator is defined, simply read any available data and return }
          if (Length(sInTerminator) = 0) AND (NOT boo_WaitForResp) then
           begin
             cbCharsAvailable := GetInCount;
     if cbCharsAvailable > 0 then
      begin
       SetLength(sBuffer, cbCharsAvailable + 1); { allocate space }
       ReadFile(int_PortHandle, PChar(sBuffer)^, cbCharsAvailable, cbCharsRead, nil);
       SetLength(sBuffer, cbCharsRead); { adjust length }
               Result := sBuffer;
      end;
    end
        else { a terminator is defined, so read port until terminator found or timed out }
         begin
          boo_FoundTerm := False;
          boo_TimerExpired := False;
          { loop until timeout or terminator recieved }
          TimeCount := 100;
          repeat
           cbCharsAvailable := GetInCount;
           if cbCharsAvailable > 0 then
            begin
             if cbCharsAvailable >= Cardinal(Length(sBuffer)) then
               SetLength(sBuffer, cbCharsAvailable + 1); { allocate space }
               { Read what's waiting at the port }
       try ReadFile(int_PortHandle, PChar(sBuffer)^, cbCharsAvailable, cbCharsRead, nil)  ;
               except
                dec(TimeCount);
            end;
    { append chars read to end of result buffer }
    Result := Result + Copy(sBuffer, 0, StrLen(PChar(sBuffer)));
            if (Pos(sInTerminator, Result) <> 0) and (Length(sInTerminator) <> 0) then
            begin
      boo_FoundTerm := True;
     end
          end
          else dec(TimeCount);
            if (TimeCount<0)then boo_TimerExpired := true;
             until (boo_TimerExpired) or (boo_FoundTerm);
            end;
          end;
          boo_InUse := False;
    end;
    end;{if ok return true else return false}
    function GetWeight(var sWeight:string;tmp:integer=4):boolean;
    var
    sTemp : string;
    begin
    { store the '' for failure}
     sWeight := '';
     Result := true;
     { open the port }
     if not(OpenComm) then
      begin
       Result := false;
       closecomm;
       ShowMessage('串口打开失败!');
       exit;
      end;
    //  sTemp:='C';
    //  WriteComm(sTemp);
      sTemp:='P';
    { send the command 'P' to scale }
      WriteComm(sTemp);
    { wait for scale data ready }
      sleep(200);
    { read the data from port }
      sTemp:=ReadComm;
    { see if it gets the data }
      if (Length(sTemp)=0) then
        begin
         Result := false;
         closecomm;
         MessageDlg('取数失败!请等待电子秤重量数据稳定后继续...', MtError,[mbOk], 0);
         exit;
        end;
    { get the weigth ,unit ,price ,Amount from the result. They are string type }
      sWeight:=copy(sTemp,8,7);//这里现在不知怎么取,如果上面取对了,这里我就可以确定了。
    { close the port}
      closecomm;
    end;end.
    //
    //sInTerminator = chr($0A);   //我不能确定这里应该是什么值?
    我在button的click事件中调用GetWeight(sWeight);取到数但总取不对,总是乱码。大侠帮我改改,急!!!(const部分波特率等参数设置没问题的)
      

  2.   

    估计是copy(sTemp,8,7)里的8和7不对。你show出来看看啊
      

  3.   

    是不是sTemp有0呢,认为是字符串的结尾了。ReadComm的返回确认都是字符串吗?程序太长了。
      

  4.   

    我今天回来看也觉得像天书,那天太着急了+我自己也看不懂。 fbincrazy(全职流氓@改) :show出来每次不同,是乱码 gzmhero(hihihi) :大概就是这个问题,可我不知道解决办法。
      

  5.   

    可能是传递字符串的格式不对...up,study
      

  6.   

    如果你的ReadComm可能读取到为0的字符的话,那你的这个函数就不能用返回String来实现。换成其他格式。譬如function ReadComm(var buf:array of char):integer,把读到东西写到buf中,
    返回值是读取的数据个数。