小弟现在要做一个侦听串口的程序,以便根据侦听内容进行处理
因为以前没搞过这方面的东东,所以要请教一下各位高手
不需要通过串口发送,只需要接受就行了,希望各位能给我个源程序`
另外我想问问如果单机的话应该怎样调试程序呢,如果同时有两个程序对串口数据进行读取,会不会有冲突呢,需不需要用hook钩子来获得数据呢,拜托了~谢谢

解决方案 »

  1.   

    Borland Delphi2.0/3.0以其强大的功能及方便快捷的程序设计
    而为广大程序员所喜爱。但是在用它来编写工业控制程序时,需要对
    计算机所连接的外部设备进行操作,即直接对I/O地址进行读写操作,
    这时该软件就显得有些美中不足了。
    针对这一问题,笔者使用Delphi 2.0/3.0以内嵌汇编的方式编写
    了一个模块PORT95. PAS,可方便地实现直接对I/O地址的读写操作,代
    码简捷且执行速度较快。
    使用时只要将PORT95.PAS加到工程文件中,并在users中加上Port
    95,就可以在应用程序中直接对I/O端口进行操作。
    具体的实现方法及PORT95.PAS的源代码如下:
    unit Port95;
    interface
    function PortReadByte(Addr:Word) : Byte;
    function PortReadWord(Addr:Word) : Word;
    function PortReadWordLS(Addr:Word) : Word;
    procedure PortWriteByte(Addr:Word; Value:Byte);
    procedure PortWriteWord(Addr:Word; Value:Word);
    procedure PortWriteWordLS(Addr:Word; Value:Word);
    implementation
    {*
    * Port Read byte function
    *Parameter:port address
    *Return: byte value from given port
    *}
    function PortReadByte(Addr:Word) : Byte; assembler; regi
    ster;
    asm
    MOV DX,AX
    IN AL,DX
    end;
    {*
    * HIGH SPEED Port Read Word function
    * Parameter: port address
    * Return: word value from given port
    * Comment:may problem with some cards and computers that
    can't to access whole word, usualy it works.
    *}
    function PortReadWord(Addr:Word) : Word; assembler; regi
    ster;
    asm
    MOV DX,AX
    IN AX,DX
    end;
    {*
    * LOW SPEED Port Read Word function
    * Parameter: port address
    *Return:word value from given port
    *Comment:work in cases,only to adjust DELAY if need
    *}
    function PortReadWordLS(Addr:Word) : Word; assembler; re
    gister;
    const
    Delay = 150;
    // depending of CPU speed and cards speed
    asm
    MOV DX,AX
    IN AL,DX
    //read LSB port
    MOV ECX,Delay
    @1:
    LOOP @1 //delay between two reads
    XCHG AH,AL
    INC DX
    //port+1
    IN AL,DX //read MSB port
    XCHG AH,AL //restore bytes order
    end;
    {* Port Write byte function*}
    procedure PortWriteByte(Addr:Word; Value:Byte); assemble
    r; register;
    asm
    XCHG AX,DX
    OUT DX,AL
    end;
    {*
    * HIGH SPEED Port Write word procedure
    * Comment:may problem with some cards and computers that
    can't to access whole word, usualy it works.
    *}
    procedure PortWriteWord(Addr:word; Value:word); assemble
    r; register;
    asm
    XCHG AX,DX
    OUT DX,AX
    end;
    {*
    * LOW SPEED Port Write Word procedure
    *}
    procedure PortWriteWordLS(Addr:word; Value:word); assemb
    ler; register;
    const
    Delay = 150;
    // depending of CPU speed and cards speed
    asm
    XCHG AX,DX
    OUT DX,AL
    MOV ECX,Delay
    @1:
    LOOP@1
    XCHG AH,AL
    INC DX
    OUT DX,AL
    end;
    end. //单元结束
    上述PORT95.PAS适用于Delphi 2.0/3.0、Windows 95 操作系统
    。 ///////////////////////////////////////function InPort(PortAddr: word): byte;
    {$IFDEF VER90}
    assembler; stdcall;
    asm
            mov dx,PortAddr
            in al,dx
    end;{$ELSE}begin
      Result := Port[PortAddr];
    end;{$ENDIF}procedure OutPort(PortAddr: word; Databyte: byte);
    {$IFDEF VER90}
    assembler; stdcall;
    asm
      mov al,Databyte
      mov dx,PortAddr
      out dx,al
    end;{$ELSE}begin
      Port[PortAddr] := DataByte;
    end;{$ENDIF}
    =========================================
    ---- 基 于WIN95/NT 的 串 行 通 信 机 制 ---- Windows 操 作 系 统 的 机 制 禁 止 应 用 程 序 直 接 访 问 计 算 机 硬 件, 但 它 为 程 序
    员 提 供 了 一 系 列 的 标 准API 函 数, 使 得 应 用 程 序 的 编 制 更 加 方 便 并 且 免 除 了
    对 有 关 硬 件 的 调 试 麻 烦。 在Windows95/NT 中, 原 来Windows3.X 的WM_COMMNOTIFY 消 息
    已 被 取 消, 操 作 系 统 为 每 个 通 信 设 备 开 辟 了 用 户 可 定 义 大 小 的 读/ 写 缓 冲
    区, 数 据 进 出 通 信 口 均 由 操 作 系 统 后 台 完 成, 应 用 程 序 只 需 对 读/ 写 缓 冲 区
    操 作 即 可。WIN95/NT 中 几 个 常 用 的 串 行 通 信 操 作 函 数 如 下: CreatFile
    打 开 串 行 口
    CloseHandle
    关 闭 串 行 口
    SetupComm
    设 置 通 信 缓 冲 区 的 大 小
    ReadFile
    读 串 口 操 作
    WriteFile
    写 串 口 操 作
    SetCommState
    设 置 通 信 参 数
    GetCommState
    获 取 默 认 通 信 参 数
    ClearCommError
    清 除 串 口 错 误 并 获 取 当 前 状 态
    ---- 除 上 述 几 个 函 数 外, 还 要 经 常 用 到 一 个 重 要 的 记 录DCB( 设 备 控 制
    块)。DCB 中 记 录 有 可 定 义 的 串 行 口 参 数, 设 置 串 行 口 参 数 时 必 须 先 用
    GetCommState 函 数 将 系 统 默 认 值 填 入DCB 控 制 块, 然 后 才 可 把 用 户 想 改 变 的 自 定
    义 值 设 定。 ---- 在WIN95/NT 中 进 行 串 行 通 信 除 了 解 基 本 的 通 信 操 作 函 数 外, 还 要 掌 握 多 线
    程 编 程。 线 程 是 进 程 内 部 执 行 的 路 径, 是 操 作 系 统 分 配CPU 时 间 的 基 本 实
    体。 每 个 进 程 都 由 单 线 程 开 始 完 成 应 用 程 序 的 执 行。 串 行 通 信 需 要 利 用 多
    线 程 技 术 实 现, 其 主 要 的 处 理 逻 辑 可 以 表 述 如 下: 进 程 一 开 始 先 由 主 线 程
    做 一 些 必 要 的 初 始 化 工 作, 然 后 主 线 程 根 据 需 要 在 适 当 时 候 建 立 通 信 监 视
    线 程 监 视 通 信 口, 当 指 定 的 串 行 口 事 件 发 生 时, 向 主 线 程 发 送
    WM_COMMNOTIFY 消 息( 由 于WIN95 取 消 了WM_COMMNOTIFY 消 息, 因 此 必 须 自 己 创
    建), 主 线 程 对 其 进 行 处 理。 若 不 需 要WM_COMMNOTIFY 消 息, 则 主 线 程 终 止 通
    信 监 视 线 程。 ---- 多 线 程 同 时 执 行, 将 会 引 起 对 共 享 资 源 的 冲 突。 为 避 免 冲 突, 就 要 用 同
    步 多 线 程 对 共 享 资 源 进 行 访 问。WIN95 提 供 了 许 多 保 持 线 程 同 步 的 方 法, 笔
    者 采 用 创 建 事 件 对 象 来 保 持 线 程 同 步。 通 过CraeteEvent() 创 建 事 件 对 象, 使
    用SetEvent() 或PulseEvent() 函 数 将 事 件 对 象 设 置 成 信 号 同 步。 在 应 用 程 序 中,
    利 用WaitSingleObject() 函 数 等 待 同 步 的 触 发, 等 到 指 定 的 事 件 被 其 它 线 程 设 置
    为 有 信 号 时, 才 继 续 向 下 执 行 程 序。 ---- Delphi 下 的 具 体 实 现 方 法 ---- Delphi 的 强 大 功 能 和 支 持 多 线 程 的 面 向 对 象 编 程 技 术, 使 得 实 现 串 行 通 信
    非 常 简 单 方 便。 它 通 过 调 用 外 部 的API 函 数 来 实 现, 主 要 步 骤 如 下: 首 先, 利
    用CreateFile 函 数 打 开 串 行 口, 以 确 定 本 应 用 程 序 对 此 串 行 口 的 占 有 权, 并 封
    锁 其 它 应 用 程 序 对 此 串 口 的 操 作; 其 次, 通 过GetCommState 函 数 填 充 设 备 控 制
    块DCB, 再 通 过 调 用SetCommState 函 数 配 置 串 行 口 的 波 特 率、 数 据 位、 校 验 位 和
    停 止 位。 然 后, 创 建 串 行 口 监 视 线 程 监 视 串 行 口 事 件。 在 此 基 础 上 就 可 以
    在 相 应 的 串 口 上 操 作 数 据 的 传 输; 最 后, 用CloseHandle 函 数 关 闭 串 行 口。 具 体
    的 程 序 如 下, 本 程 序 用Delphi3.0 编 制 在Win95 环t 境 下 调 试 通 过, 已 投 入 实 际 应 用
    中, 供 广 大 读 者 参 考。 ---- 程 序: unit comdemou;
    interface
    uses
      Windows, Messages, SysUtils, Classes, 
    Graphics, Controls, Forms, Dialogs;const
        Wm_commNotify=Wm_User+12;
    type
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
      private
        Procedure comminitialize;
    Procedure MsgcommProcess(Var 
    Message:Tmessage); Message Wm_commnotify;
        { Private declarations }
      public
        { Public declarations }
      end;  //线程声明
      TComm=Class(TThread)
      protected
        procedure Execute;override;
      end;var
      Form1: TForm1;
      hcom,Post_Event:Thandle;
      lpol:Poverlapped;
    implementation{$R *.DFM}Procedure TComm.Execute; //线程执行过程
    var
    dwEvtMask:Dword;
    Wait:Boolean;
    Begin
    fillchar(lpol,sizeof(toverlapped),0);
    While True do Begin
          dwEvtMask:=0;
          Wait:=WaitCommEvent(hcom,dwevtmask,lpol);  
    //等待串行口事件;
          if Wait Then Begin
            waitforsingleobject(post_event,infinite); 
    //等待同步事件置位;
            resetevent(post_event);  //同步事件复位;
            PostMessage(Form1.Handle,
    WM_COMMNOTIFY,0,0);//发送消息;
            end;
          end;
    end;procedure Tform1.comminitialize;  
    //串行口初始化
    var
    lpdcb:Tdcb;
    Begin
    hcom:=createfile('com2',generic_read or
    generic_write,0,nil,open_existing,
    file_attribute_normal or
    file_flag_overlapped,0);//打开串行口
        if hcom=invalid_handle_value then
        else
            setupcomm(hcom,4096,4096); 
    //设置输入,输出缓冲区皆为4096字节
            getcommstate(hcom,lpdcb); 
    //获取串行口当前默认设置
            lpdcb.baudrate:=2400;
            lpdcb.StopBits:=1;
            lpdcb.ByteSize:=8;
            lpdcb.Parity:=EvenP
      

  2.   

    谢谢 wuxuan(真心英雄) ,还想问问在单机上我应该怎样调试呢,而且关键我的程序不能影响原来程序对串口的操作,如果我的程序读取串口数据时,原来程序也读取,会有冲突吧,所以有没有其他方法,例如,用hook监视原有程序和串口的数据传递?