Cport 详细解释和应用



转载:http://www.cnblogs.com/Bung/archive/2011/05/20/2051636.html

通过comport获取计算机中的所有串口号:


procedure TForm1.FormCreate(Sender: TObject);  //获取计算机中的串口号

var

  Cnumber:TStrings;

  i:Integer;

begin

  cbb2.Items.Clear;

  Cnumber:=TStringList.Create;

  EnumComPorts(Cnumber);  //获取串口号函数:EnumComPorts

  for i:=0 to Cnumber.Count-1 do

  begin

  cbb2.Items.Add(Cnumber.Strings[i])

  end;

  cbb2.ItemIndex:=0;

  Cnumber.Free;

end;

 

procedure TForm1.btn7Click(Sender: TObject);  //打开串口

begin

  ComPort1.Port:=cbb2.Text;

  if ComPort1.Connected then

  begin

    ComPort1.Close;

    ComPort1.Open;

  end

  else

  ComPort1.Open;

end;


我开始用comport时发现它每次14个字符触发一次接收事件,而我要接收的一帧完整数据是82个字符,因此我在每帧的前后个加了开始码和结束码,共84个字符,当Count值大于84我才处理,程序片断如下:


procedure TFCOMM.ComPortRxChar(Sender: TObject; Count: Integer);

var

  ReceiveData:TDateRec;

  p:Pbyte;

  Block : array[0..85] of Char;

begin

  if (not Ready)  then

    begin

      ComPort.Read(p,1);   //开始码为$7FFE,接收时先收的是$FE

      move(p, SecondByte,1);

      if SecondByte = $FE then        //如果收到的字节是$FE,那就看看下一个是不是$7F

        begin

          FirstByte := SecondByte;

          ComPort.Read(p,1);;

          move(p, SecondByte,1);

        end;

    end;

 

  if (FirstByte = $FE) and (SecondByte = $7F) then

    Ready := True;

 

  if Ready and (count>=84) then

    begin

      。。。。

    end;

end;


Spcomm有的是定时查询的方式读COM口;而ComPort用Overlapped机制进行COM读写,只要COM有数据接收到,ComPort就能够从Event响应,并通知应用程序接收,所以,某种ComPort的实时性更好。但是,Overlapped的Event被触发,并不是COM接入一段完整的信息才触发,是Windows自己决定的,我在多个计算机和不同的Windows版本上试过,其触发后接收到的字符数并不一样。因此,需要自己建一个缓冲区来处理数据。


procedure TCustomComPort.CreateHandle;

begin

  FHandle := CreateFile(

    PChar('\\.\' + FPort),

    GENERIC_READ or GENERIC_WRITE,

    0,

    nil,

    OPEN_EXISTING,

    FILE_FLAG_OVERLAPPED,  // 以Overlapped方式打开COM口

    0);

 

  if FHandle = INVALID_HANDLE_VALUE then

    raise EComPort.Create(CError_OpenFailed, GetLastError);

end;

 

procedure TComThread.Execute;

var

  EventHandles: array[0..1] of THandle;

  Overlapped: TOverlapped;

  Signaled, BytesTrans, Mask: DWORD;

begin

  FillChar(Overlapped, SizeOf(Overlapped), 0);

  Overlapped.hEvent := CreateEvent(nil, True, True, nil);

  EventHandles[0] := FStopEvent;

  EventHandles[1] := Overlapped.hEvent; // COM口上的Overlapped事件

  repeat

    // 等待COM上的事件

    // wait for event to occur on serial port

    WaitCommEvent(FComPort.Handle, Mask, @Overlapped);

    Signaled := WaitForMultipleObjects(2, @EventHandles, False, INFINITE);

    // if event occurs, dispatch it

    if (Signaled = WAIT_OBJECT_0 + 1)

      and GetOverlappedResult(FComPort.Handle, Overlapped, BytesTrans, False)

    then

    begin

      // 通知应用程序接收数据

      FEvents := IntToEvents(Mask);

      DispatchComMsg;

    end;

  until Signaled <> (WAIT_OBJECT_0 + 1);

  // clear buffers

  SetCommMask(FComPort.Handle, 0);

  PurgeComm(FComPort.Handle, PURGE_TXCLEAR or PURGE_RXCLEAR);

  CloseHandle(Overlapped.hEvent);

  CloseHandle(FStopEvent);

end; 
Cport - 应用集合



通过comport获取计算机中的所有串口号:


procedure TForm1.FormCreate(Sender: TObject);  //获取计算机中的串口号

var

  Cnumber:TStrings;

  i:Integer;

begin

  cbb2.Items.Clear;

  Cnumber:=TStringList.Create;

  EnumComPorts(Cnumber);  //获取串口号函数:EnumComPorts

  for i:=0 to Cnumber.Count-1 do

  begin

  cbb2.Items.Add(Cnumber.Strings[i])

  end;

  cbb2.ItemIndex:=0;

  Cnumber.Free;

end;

 

procedure TForm1.btn7Click(Sender: TObject);  //打开串口

begin

  ComPort1.Port:=cbb2.Text;

  if ComPort1.Connected then

  begin

    ComPort1.Close;

    ComPort1.Open;

  end

  else

  ComPort1.Open;

end;


我开始用comport时发现它每次14个字符触发一次接收事件,而我要接收的一帧完整数据是82个字符,因此我在每帧的前后个加了开始码和结束码,共84个字符,当Count值大于84我才处理,程序片断如下:


procedure TFCOMM.ComPortRxChar(Sender: TObject; Count: Integer);

var

  ReceiveData:TDateRec;

  p:Pbyte;

  Block : array[0..85] of Char;

begin

  if (not Ready)  then

    begin

      ComPort.Read(p,1);   //开始码为$7FFE,接收时先收的是$FE

      move(p, SecondByte,1);

      if SecondByte = $FE then        //如果收到的字节是$FE,那就看看下一个是不是$7F

        begin

          FirstByte := SecondByte;

          ComPort.Read(p,1);;

          move(p, SecondByte,1);

        end;

    end;

 

  if (FirstByte = $FE) and (SecondByte = $7F) then

    Ready := True;

 

  if Ready and (count>=84) then

    begin

      。。。。

    end;

end;


Spcomm有的是定时查询的方式读COM口;而ComPort用Overlapped机制进行COM读写,只要COM有数据接收到,ComPort就能够从Event响应,并通知应用程序接收,所以,某种ComPort的实时性更好。但是,Overlapped的Event被触发,并不是COM接入一段完整的信息才触发,是Windows自己决定的,我在多个计算机和不同的Windows版本上试过,其触发后接收到的字符数并不一样。因此,需要自己建一个缓冲区来处理数据。



procedure TCustomComPort.CreateHandle;

begin

  FHandle := CreateFile(

    PChar('\\.\' + FPort),

    GENERIC_READ or GENERIC_WRITE,

    0,

    nil,

    OPEN_EXISTING,

    FILE_FLAG_OVERLAPPED,  // 以Overlapped方式打开COM口

    0);

 

  if FHandle = INVALID_HANDLE_VALUE then

    raise EComPort.Create(CError_OpenFailed, GetLastError);

end;

 

procedure TComThread.Execute;

var

  EventHandles: array[0..1] of THandle;

  Overlapped: TOverlapped;

  Signaled, BytesTrans, Mask: DWORD;

begin

  FillChar(Overlapped, SizeOf(Overlapped), 0);

  Overlapped.hEvent := CreateEvent(nil, True, True, nil);

  EventHandles[0] := FStopEvent;

  EventHandles[1] := Overlapped.hEvent; // COM口上的Overlapped事件

  repeat

    // 等待COM上的事件

    // wait for event to occur on serial port

    WaitCommEvent(FComPort.Handle, Mask, @Overlapped);

    Signaled := WaitForMultipleObjects(2, @EventHandles, False, INFINITE);

    // if event occurs, dispatch it

    if (Signaled = WAIT_OBJECT_0 + 1)

      and GetOverlappedResult(FComPort.Handle, Overlapped, BytesTrans, False)

    then

    begin

      // 通知应用程序接收数据

      FEvents := IntToEvents(Mask);

      DispatchComMsg;

    end;

  until Signaled <> (WAIT_OBJECT_0 + 1);

  // clear buffers

  SetCommMask(FComPort.Handle, 0);

  PurgeComm(FComPort.Handle, PURGE_TXCLEAR or PURGE_RXCLEAR);

  CloseHandle(Overlapped.hEvent);

  CloseHandle(FStopEvent);

end; 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值