各位大虾,我现在想用Delphi实现计算机与仪表之间采用RS485通讯协议进行串口通讯,小弟不懂的串口通讯这方面的知识,那位有这方面的原代码(用delphi)或哪网站可提供下载的介绍给我好吗?先谢谢拉,很急的,在线等待!

解决方案 »

  1.   

    我也没做过,不过可给你一点提示:
    1、找几本Delphi做数据通信的书,市面上非常多。
    2、上Google用Delphi和RS485为关键字搜一搜,当然最好英文好一点。
      

  2.   

    你要找一個轉換器, 或轉換卡, 可以提供232<->486輸出的, 然後, 确實編程開發時與rs232沒有區別, 如果, 你想簡單點, 那就使用控件 spcomm, mscomm....都是很簡單的就可實現復雜的通訊
      

  3.   

    来晚了,楼上的都说完了。
    如aiirii(ari) 所说,不用关心是什么方式的串口,系统的api接口都一样。
    我以前写过一个多线程的,记得发过一次,找不到了,再发一边。一个自动控制机的硅控板检测程序,用多线程和API,没有用控件,少做改动就能用,供你参考吧!
    Unit CommThread;InterfaceUses
      Windows, Classes, SysUtils, Graphics, Controls, Forms,
      Dialogs, ComCtrls, ExtCtrls;
    Type
      TThreadParam = Record
        SusPended: Boolean;
        BaulSpeed: integer;
        Port: Byte;
        Parity: Boolean;
        StopBit: byte;
        StartBit: Byte;
        SB: TStatusBar;
        LEDs: Array[0..24] Of TShape;
      End;Type
      TReadThread = Class(TThread)
      Private
        { Private declarations }
        hComm: THandle;
        Port: integer;
        FErr: Boolean;
        FPortDescription: String;
        FShape: Array[0..24] Of TShape;
        FSB: TStatusBar;
        cc: TCOMMCONFIG;
        Data: String;
        Procedure ReadPort; //读取串行端口数据
        Procedure UpdateUI;
      Protected
        Procedure Execute; Override;
      Public
        Constructor Create(ThdPrm: TThreadParam);
      End;Implementation
    //uses Unit1; // 声明引用Unit1,必须放在implementation区段Constructor TReadThread.Create(ThdPrm: TThreadParam);
    Var
      i: integer;
    Begin
      Port := thdprm.Port;
      FSB := thdprm.SB;
      For i := 0 To 24 Do
      Begin
        FShape[i] := thdPrm.LEDs[i];
      End;
      FreeOnTerminate := True;
      Inherited Create(ThdPrm.SusPended);
    End;Procedure TReadThread.Execute;
    Var
      PortToOpen: String;
    Begin
      PortToOpen := 'COM' + inttostr(Port); // 选择所要打开的COM
      hComm := CreateFile(PChar(PortToOpen), GENERIC_READ Or GENERIC_WRITE,
        0, Nil, OPEN_EXISTING, 0, 0); // 打开COM
      If (hComm = INVALID_HANDLE_VALUE) Then
      Begin //如果COM 未打开
        FErr := True;
        FPortDescription := '打开端口错误!';
      End
      Else
      Begin
        FErr := False;
        FPortDescription := '打开端口成功';
        GetCommState(hComm, cc.dcb); // 得知目前COM 的状态
        cc.dcb.BaudRate := CBR_9600; // 设置波特率为9600
        cc.dcb.ByteSize := 8; //字节为 8 bit
        cc.dcb.Parity := NOPARITY; // Parity 为 None
        cc.dcb.StopBits := ONESTOPBIT; // 1 个Stop bit
        If Not SetCommState(hComm, cc.dcb) Then
        Begin // 设置COM 的状态
          Ferr := True;
          FPortDescription := FPortDescription + ',设置错误!';
          CloseHandle(hComm); //关闭通信端口
        End
        Else
        Begin
          FErr := False;
          FPortDescription := FPortDescription + ',设置成功';
          While Not Terminated Do
          Begin
            Synchronize(ReadPort); //刚才所定义的读取数据函数
          End;
          Synchronize(UpdateUI);
        End;
      End;End;
    Procedure TReadThread.ReadPort;
    Var
      i: integer;
      inbuff: Array[0..29] Of Char;
      nBytesRead, dwEvent, dwError: LongWORD;
      cs: TCOMSTAT;
      Rights, Emptys, Errs: integer;
    Const
      RightColor = clBlue;
      ErrorColor = clRed;
      EmptyColor = clWhite;
    Begin
      Rights := 0;
      Emptys := 0;
      Errs := 0;
      If (hComm = INVALID_HANDLE_VALUE) Then
      Begin
        Fsb.Panels[3].Text := FPortDescription;
        Terminate; //先判断是否已打开通信端口
        Exit;
      End
      Else
      Begin
        Fsb.Panels[3].Text := FPortDescription;
        ClearCommError(hComm, dwError, @CS); //取得状态
        ReadFile(hComm, inbuff, cs.cbInQue, nBytesRead, Nil); // 接收COM 的数据
        //串行在读取数据后,会自动将缓冲区中已被读取的数据清除掉
        If cs.cbInQue = 0 Then exit;
        // 数据是否大于我们所准备的Buffer
        If cs.cbInQue <> sizeof(inbuff) Then
        Begin
          PurgeComm(hComm, PURGE_RXCLEAR); // 清除COM 数据
          exit;
        End;
        Data := Copy(inbuff, 1, cs.cbInQue); //取出数据
        For i := 1 To 25 Do
        Begin
          If (UpperCase(Data[i]) = 'Y') Then
          Begin
            FShape[i].Brush.Color := RightColor;
            Rights := Rights + 1;
          End
          Else
            If (UpperCase(Data[i]) = 'N') Then
            Begin
              FShape[i].Brush.Color := EmptyColor;
              Emptys := Emptys + 1;
            End
            Else
              If (UpperCase(Data[i]) = 'E') Then
              Begin
                FShape[i].Brush.Color := ErrorColor;
                Errs := Errs + 1;
              End;
        End;
        Fsb.Panels[0].Text := '正确:' + IntTostr(Rights);
        fsb.Panels[1].Text := '空槽:' + IntTostr(Emptys);
        fsb.Panels[2].Text := '错误:' + IntTostr(Errs);
        Fsb.Panels[3].Text := FPortDescription;
        Fsb.Panels[4].Text := '数据:' + Data;
      End;
    End;Procedure TReadThread.UpdateUI;
    Begin
      Fsb.Panels[0].Text := '正确:' + IntTostr(0);
      fsb.Panels[1].Text := '空槽:' + IntTostr(0);
      fsb.Panels[2].Text := '错误:' + IntTostr(0);
      Fsb.Panels[3].Text := '';
      Fsb.Panels[4].Text := '数据:' + Data;
    End;End.
      

  4.   

    首先,应该有一个RS232-RS485的转换器(哪里都有买的!)
    然后,利用API编写串口程序,用控件也可以,但是API可以节省很多的资源,直接可以控制串口,没有必要再用控件转发,但是如果你对API不是很熟悉,用不好的话,还是用控件比较方便,不用费脑筋。推荐MSCOMM控件。API的方法楼上已经说了,下面我用MSCOMM控件编写的程序。
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Buttons, OleCtrls, MSCommLib_TLB, ExtCtrls;type
      TForm1 = class(TForm)
        EdSend: TEdit;
        BitBtnSend: TBitBtn;
        MemoRec: TMemo;
        LSend: TLabel;
        Label2: TLabel;
        MemoSend: TMemo;
        Label1: TLabel;
        Bevel1: TBevel;
        MSComm1: TMSComm;
        Button1: TButton;
        BSendClear: TButton;
        BRecClear: TButton;
        procedure FormShow(Sender: TObject);
        procedure BitBtnSendClick(Sender: TObject);
        procedure Button1Click(Sender: TObject);
        procedure BSendClearClick(Sender: TObject);
        procedure BRecClearClick(Sender: TObject);
        procedure MSComm1Comm(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormShow(Sender: TObject);
    begin
      EdSend.Text:='';
      MemoRec.Text:='';
      MemoSend.Text:='';
      MsComm1.CommPort:=1;
      mscomm1.PortOpen:=true;end;procedure TForm1.BitBtnSendClick(Sender: TObject);
    var
      SendStr:String;begin
      SendStr:=Trim(EdSend.Text);
      MsComm1.Output:=SendStr;
      MemoSend.Lines.Add(SendStr);end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      Mscomm1.PortOpen:=flase;
      close;end;procedure TForm1.BSendClearClick(Sender: TObject);
    begin
      MemoSend.Clear;end;procedure TForm1.BRecClearClick(Sender: TObject);
    begin
      MemoRec.Clear;
    end;procedure TForm1.MSComm1Comm(Sender: TObject);
    Var
      buffer,str :String;
      i,j:integer;begin
      case mscomm1.commEvent of
          comEvReceive:
            begin
              buffer:=mscomm1.Input;
              i:=MemoRec.Lines.Count;
              if not (i=0) then i:=i-1;
              MemoRec.Lines.Strings[i]:=MemoRec.Lines.Strings[i]+buffer;        end;
    end;
    end;
    end.
      

  5.   

    如果是半双工的,则直接如 RS232 编程一样。
    如果是全双工,则要用 RS-422 转换器
      

  6.   

    delphi中常用串口控件简介:
    mscomm:微软的东西,是VB中带的一个ActiveX控件,使用简单,性能一般,由于是ActivX控件,打包时需要注册好多信息,在Delphi中使用,建议使用VCL控件,编译程序时直接编入程序中,再不需任何其它处理。
    spcomm:比较好的vcl控件,算是比较专业的,解剖了一下,功能比较完善。
    TurboPower:公认的专业通讯vcl控件。可以到其站点下载,开放源码了。
    我在制作串口通讯软件时三种都用过,最终全部使用TurboPower!所以也推荐大家使用它。
    写了个例子,基本的串口通讯都可以实现,可提供参考:
    下载基地-》文件名称:串口通讯控制器
    版权声明:以下本文只允许在本站观看,不得以任何媒体方式进行传播。
    发表意见请到留言版。TurboPower串口通讯实际应用:
    在串口通讯时有字符和十六进制两种数据传输方式,不论使用哪种方式,只要能正确收到数据就是目的,至于收到数据后如何处理,就要根据具体的情况来定了。1.接收数据的方法:
    轮询和中断(利用windows消息激发事件)。
    1)轮询:每间隔一定的时间查询一下串口接收缓存中有无数据,有就读出来。这种方法是很毫资源的,即没事找事。
    2)中断:在控件中有OnTrigger事件,当串口收到数据后,即触发此事件,无数据时什么都不做,在这个事件中接收数据就比较科学了。
    所以,提倡使用控件中的OnTrigger事件接收数据。2.通讯协议的制定:
    接收数据的一般处理方法,最基本的思路就是通过协议进行分析,所以协议的制定是至关重要的:
    1)首先要确定指令的起始点,从大量的数据流中将指令分离出来,没有起始标志的话,结果就可想而知了,一串无效的费数据!
    2)然后就是指令结束识别点,可以利用指令的长度(如果长度一定或有表示长度的数据)或结束标志来确定,当然还可以利用下一条指令的指令头。
    3)既然头尾都明确了,指令的截取想来不是什么问题了吧!但还有一种情况就是数据错误是的容错,如何容错呢,最简单的办法:发现不符合格式的指令,就将其抛掉或特殊处理(如要求重发)一下!
    4)有效数据中如果增加一些校验,通讯将会更加可靠!
    例:#(指令头)**(指令功能)0123456789(有效数据)**(有效数据校验和)%(指令尾)
    注:**代表变动值。3.接收数据的分析技巧:
    通讯协议制定好后,一切将以通讯协议为中心。一套协议中的所有指令可能长度都是统一的,也有可能是长短不同的,并且在OnTrigger事件中实际反应速度及快,可能一条指令数据还没有完全收齐就已经触发了此事件,即收到了半截指令,并且有可能继续收取的数据中除了下半截指令外,还有下一条指令的前半截,如何处理?
    我在做这种处理时是利用全局变量,将串口收到的所有数据都收到该串中,然后按指令格式进行截取,发现不合法指令做一下特殊处理(如要求重发)或抛弃。
    如收到的数据串为:
    #**0000012000**%#**0000000343#**000000540560**%#**0002200000**%
    分段截为:
    #**0000012000**%
    #**0000000343
    #**000000540560**%
    #**0002200000**%
    四条指令,其中:#**0000000343不完整,检测到后进行抛弃处理。调试技巧篇:
    对于已了解协议的支持串口产品,要想进行编程控制,可以使用“串口通讯控制器”进行调试,以摸清具体实现数据,可按如下步骤进行:
    1.确定硬件连接无误,这是首要条件,如果错误将没有成功的可能;
    连线必须正确,必要时可以使用计算机自带的多个端口相互进行测试,已保证硬件的连接无误。串口通讯线有9针和25针,多用9针,其中最重要的是2(RXD)、3(TXD)、5(GND)线,对应关系如下:
    9针 25针
    2 -- 3
    3 -- 2
    5 -- 72.确定通讯参数正确,如:波特率、奇偶校验位、数据位、停止位等,以及收发的是十六进制还是字符串:3.以上确保正确,则使用“串口通讯控制器”,按协议输入数据进行收发控制了。
    注意:有的仪器需要进行初始化,即先发一段激活指令,然后才能进入工作状态,这种设置主要是为了实现利用硬件为软件加密,即类似加密狗,需要有激活方法才行,不过该类方法使用较少。http://218.56.11.178:8018/FileDown.aspx?FID=160http://218.56.11.178:8018/FileDown.aspx?FID=167