你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 编程语言
一种基于Windows环境的设备驱动程序设计与实现
 

  :本文介绍了Windows下可安装的设备驱动程序的消息和框架,并给出了调用设备驱动程序的的方法,我们运用该方法将DOS环境下的实时数据采集中断驻留程序移植到Windows下,取得了较理想的实时数据采集效果。

关键字Windows设备驱动程序  中断驻留  实时数据采集

 

一、引言

Windows操作系统以其外观新颖精致、用户界面友好、操作方式简便快捷、能够处理多媒体信息、从底层支持网络性能,而逐步成为目前主流的操作系统。除此之外,Windows环境下的界面设计环境优美、使用方便,吸引了大量的应用程序开发者。Windows操作系统为支持其多任务功能,在系统运行后,Windows接管了计算机的所有资源,如键盘、鼠标等。同样,Windows也接管了计算机系统的中断服务,使得以前我们很容易实现的中断驻留程序无法在Windows环境下运行,这对于利用中断驻留程序实现实时数据采集的系统来说无疑是不幸的。为了能够在Windows环境下实现实时数据采集,我们设计了一种Windows环境下的设备驱动程序框架,将原来DOS环境下的中断驻留程序很方便地移植到Windows下,作为Windows的一种可安装驱动程序。本文所要讲述的就是可安装的设备驱动程序的设计与实现,以及它的应用。

二、Windows环境设备驱动程序的分类

Windows环境下,设备驱动程序分为两类:设备驱动程序和虚拟设备驱动程序。其中设备驱动程序又可分为两种,一种是标准的设备驱动程序,如键盘、鼠标等;另一种是可安装的设备驱动程序,它主要是用来处理非标准的硬件设备,如数据采集卡等用户自己设计的硬件设备。

三、设备驱动程序中的消息

Windows环境下,可安装设备驱动程序可能收到的消息和说明如表1所示。

1 可安装设备驱动程序的消息

序号

  

      

1

DRV_LOAD

在驱动程序第一次装载后,Windows发给它的消息就是DRV_LOAD消息,此时可以初始化实例数据。

2

DRV_ENABLE

当驱动程序首次装载后,Windows向它发DRV_ENABLE消息,利用该消息设置硬件并挂接中断。

3

DRV_OPEN

当驱动程序被OpenDriver调用打开时,Windows向它发该消息。

4

DRV_CLOSE

当驱动程序因CloseDriver调用而关闭时,Windows向驱动程序发出一个DRV_CLOSE消息。驱动程序常使用DRV_CLOSE通知来释放特定实例的数据结构。

5

DRV_DISABLE

当驱动程序被释放或从Windows进入DOS时,向驱动程序发DRV_DISABLE消息。因此,从Windows切换出来时,设备驱动程序不挂接任何中断,并复位硬件。

6

DRV_FREE

在驱动程序被丢弃前,Windows发给它的最后一个消息就是DRV_FREE

7

DRV_EXITAPPLICATION

当应用程序退出时,Windows向驱动程序发出该消息。

8

DRV_EXITSESSION

Windows退出前,向所有打开的驱动程序发出该消息。

9

DRV_PORWER

在符合Advanced Power ManageMent(APM)标准的系统中,当系统将进入或退出挂起模式时,设备驱动程序将收到一个DRV_PORWER消息。

10

DRV_INSTALL

在驱动程序安装过程中,它将收到该消息。

11

DRV_QUERYCONFIGURE

驱动程序的安装程序利用该消息来确定驱动程序是否能由用户配置。对于对该消息返回TURE的驱动程序,安装程序会使能“configure”或“Setup”按钮。

12

DRV_CONFIG

当驱动程序完成初始化安装,以及每当用户要求重新配置驱动程序时,驱动安装程序会发送该消息。

13

DRV_REMOVE

当驱动程序将从安装的驱动程序列表中删除时,将会收到该消息。

14

DRV_USER

用户自定义的消息。

四、设备驱动程序框架

Windows的设备驱动程序实质上也是一个动态连接库,它也有LibMain_WEP函数,利用这两个函数,可以完成驱动程序的加载和释放。可安装的设备驱动程序与一般的DDL的不同在于它有一个驱动程序事件处理过程DriverProc,有了DriverProcWindows就可以向驱动程序发送消息和从驱动程序得到消息。下面是DriverProc的框架实例,程序给出的中断号为0x0d(对应IRQ5),我们开发的硬件设备的定时中断信号就是接在此中断号,定时信号每5ms引起一次中断,采集一个数据。

1DriverProc的框架

#include <windows.h>

#include <stdio.h>

#include <io.h>

#include "instdrv.h"

 

unsigned int    data[800];          ①数据区

unsigned int    int_num = 0x0d;     ②中断向量(对应IRQ5

HWND Hand_Send=NULL;

HWND Hand_Rec=NULL;

 

void interrupt  (*oldhandler)(void);

void interrupt  handler(void);

 

int _export WINAPI LibMain(HINSTANCE hInstance,WORD wDataSeg,WORD cbHeapSize,LPSTR lpszCmdLine)

{   return(1);}

 

int _export WINAPI _WEP(int bSystemExit)

{   return(1);}

 

LRESULT CALLBACK DriverProc(DWORD dwDrvid,HDRVR hDrv,UINT msg,LPARAM lParam1,LPARAM lParam2)

{

    HWND    Hand=NULL;

 

    switch( msg )

    {

        case DRV_LOAD: oldhandler = getvect(int_num);return (TRUE);

③保护旧的中断向量

        case DRV_ENABLE:

            setvect(int_num, handler);                         

④设置新的中断向量

            asm{        cli

                    in al,21h

                and  al,11011111B                          

⑤打开IRQ5中断

                    out 21h,al

                    sti }

            return (TRUE);

        case DRV_OPEN:      return( TRUE );

        case DRV_CLOSE: return( TRUE );

        case DRV_FREE:      return( TRUE );

        case DRV_DISABLE:

            asm{        cli

                    in al,21h

                or al,00100000B                        

⑥关闭IRQ5中断

                    out 21h,al

                    sti }

            setvect(int_num,oldhandler);

            return (TRUE);

        case DRV_QUERYCONFIGURE:    return( FALSE );

        case WM_SEND:                                  

WM_SEND应用程序发过来的消息

             switch((WORD)lParam1)

             {

              case  GET_BUF_PTR:                       

⑧得到缓冲区地址指针

                        Hand  = (HWND)lParam2;

SendMessage(Hand,WM_INT, SBUF_PTR ,(LPARAM)(int far *)data);

                    break;

              case RESET:                              

⑨此处可以控制采集设备复位

                    break;

             }

             return (TRUE);

        default:        return DefDriverProc(dwDrvid,hDrv,msg,lParam1,lParam2);

    }

}

 

void interrupt handler(void)

{

   

此处加入中断处理程序(实时数据采集程序),编写方法与DOS下相同。

}

2.驱动程序的模块定义文件

LIBRARY         instdrv

DESCRIPTION     'Installable Device Driver '

EXETYPE         WINDOWS

STUB            'WINSTUB.EXE'

CODE            PRELOAD MOVEABLE DISCARDABLE

DATA            PRELOAD MOVEABLE SINGLE

HEAPSIZE        1024

EXPORTS

         WEP        @1 RESIDENTNAME

         DriverProc @2 RESIDENTNAME

五、设备驱动程序的使用

前面给出了一个完整的可安装设备驱动程序的框架,我们可以用下面的三个函数使用可安装设备驱动程序:

1OpenDriver函数:在应用程序使用可安装设备驱动程序之前,用该函数打开驱动程序。

2.  CloseDriver函数:在应用程序不再需要该驱动程序时,用该函数关闭它。

3.  SendDriverMessage函数:驱动程序打开之后通过该函数与之通讯。

一个简单的使用上述设备驱动程序的框架如下所示:

#include <windows.h>

HINSTANCE   hInst;

HDRVR       hDrv = NULL;

HWND        hWND = NULL;

int         far* pointer = NULL;                ①指向数据区的长指针

 

int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszCmd,int nCmdShow)

{  

    static char szAppName[] = "usedrv";

    HWND        hwnd ;

    MSG         msg ;

    WNDCLASS    wndclass ;

 

    if( !hPrevInstance ){

                wndclass.style         = CS_HREDRAW | CS_VREDRAW;

        wndclass.lpfnWndProc   = (WNDPROC)WndProc;

        wndclass.cbClsExtra    = 0;

        wndclass.cbWndExtra    = 0;

        wndclass.hInstance     = hInstance;

        wndclass.hIcon         = LoadIcon( NULL, IDI_APPLICATION );

        wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);

        wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

        wndclass.lpszMenuName  = "MainMenu";

        wndclass.lpszClassName = szAppName;

        RegisterClass (&wndclass);  }

    hwnd = CreateWindow (szAppName, "Example",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,

                                          CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);

    ShowWindow( hwnd, nCmdShow );

    UpdateWindow(hwnd);

    while(GetMessage( &msg, NULL, 0, 0))   

    {   TranslateMessage(&msg);

DispatchMessage(&msg);}

    return msg.wParam;

}

long FAR PASCAL _export WndProc(HWND hWnd, WORD message,WORD wParam,LONG lParam)

{

    HDC hdc;

    HWND    = hWnd;

switch (message)

    {

       case WM_DESTROY:                        ②关闭驱动程序

if( hDrv ){ CloseDriver( hDrv,0,0 );    hDrv=NULL;}

                PostQuitMessage(0);

                return(0);

        case WM_INT:            ③收到WM_INT消息后,得到数据区指针

                pointer = (int far *)lParam;

               

数据处理程序。

                break;

        case WM_COMMAND:

                switch( wParam )

                {

                    case IDM_OPEN:          ④打开驱动程序

         if( !hDrv )    { hDrv = OpenDriver(InstDrvName,NULL,NULL);}

                        break;

                   case IDM_CLOSE:     ⑤关闭驱动程序

          if( hDrv ){ CloseDriver(hDrv,0,0); hDrv = NULL; PostQuitMessage(0);}

                        break;

    case IDM_SEND:          ⑥发出消息WM_SEND给驱动程序,需要得到数据区指针

                        if( hDrv ) SendDriverMessage(hDrv,WM_SEND,GET_BUF_PTR,(LPARAM)hWND);

                        break;

                    default:        return(DefWindowProc(hWnd,message,wParam,lParam));

                }

                return (0);

    }

    return(DefWindowProc(hWnd,message,wParam,lParam));

}

上述程序中设备驱动程序与应用程序之间是通过消息来传递信息的,当要进行数据采集时,应用程序首先打开设备驱动程序,然后发送WM_SENDGET_BUF_PTR)消息给设备驱动程序,通知设备驱动程序将数据区地址指针传送给应用程序;设备驱动程序收到WM_SEND消息后,向应用程序发送WM_INT消息,同时将数据区指针传送给应用程序。应用程序收到数据区地址指针后,即可从数据区读实时采集的数据进行显示。

六、结束语

Windows环境下开发用户自己的驱动程序,是许多硬件开发者所面临的最大困难。本文给出了一种简单实用的设备驱动程序框架,在实际工作中,我们将原来在DOS环境下的设备驱动程序移植到Windows环境,实现了原来实时采集数据的功能,同时在Windows下编写的界面程序比以前更加方便美观,达到了预期的效果。

参考文献

1Microsoft Windows API大全                     北京科海培训中心

2Asael Dror       Windows 奥秘               学苑出版社 19949

3.傅 勇等    发动机自动测试台架的数据采集系统   工业控制计算机1998年第6

 

  推荐精品文章

·2024年12月目录 
·2024年11月目录 
·2024年10月目录 
·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089