• PCI总线仲裁器的设计与实现

     作者Email:  jie_yi@sohu.com         摘要:基于Altera的CPLD器件的PCI总线仲裁器设计,实现仲裁器的AHDL编程,并结合仿真结果对PCI总线的仲裁进行了论述。     关键词:PCI仲裁器,CPLD,仿真     PCI总线仲裁器通常是集成在PCI芯片组中。随着计算机应用的深入,尤其是嵌入式系统的不断发展,集成的仲裁器难以满足某些场合的应用。而采用CPLD技术实现的独立的PCI总线仲裁器,则较好的适应了这方面的需求。     一﹑PCI总线仲裁机制     PCI的仲裁是基于设备访问,而不是基于时间分配的。在任一时刻,总线上的一个主设备要想获得对总线的控制权,就必须发出它的请求信号(PCIreqN),如果此刻该设备有权控制总线,总线仲裁器就使该设备的总线占用允许信号(PCIgntN)有效,进而获得总线的使用权。当有多个主设备同时发出总线控制请求时,就必须由仲裁器根据一定的算法判定,当前应该由哪个主设备获得控制权。     二、仲裁算法     常用的仲裁算法有:公平算法、循环算法等。     本仲裁器设计采用的是循环算法,设备的优先级预先设定。目前的设计实现对四个PCI设备请求的仲裁,各设备优先级由高到低安排为:设备0 >设备1 > 设备2 > 设备3。     系统启动伊始,没有设备使用PCI总线,也没有设备请求使用PCI总线,仲裁器总是设定设备0拥有总线控制权,即将总线停靠于设备0。此时设备0的PCIgntN是有效的。而在此之后,仲裁器总是指定PCI总线的最后一个使用者为总线的停靠设备。     当有一个或多个设备提出拥有总线使用权的请求时,仲裁器将按照事先安排的设备优先级顺序逐一查询。对于只有一个设备请求的情况,该设备的请求将会马上得到响应;如果多个设备同时发出请求时,仲裁器裁定首先响应优先等级高的设备的请求,当此设备完成数据传输交出总线使用权后,再由优先等级低的设备使用总线。示意框图见图2。     如果一个设备已获得总线使用权并且正在进行地址、数据传输时,比它优先级别高的设备也发出了占用请求,仲裁器将会撤销优先级别低的设备的总线占用信号,并把总线使用权交给优先级别高的设备,同时还要确保在任一时刻不会出现多个设备同时占用总线的情况。具体见仿真分析。     三、编程设计与实现     本设计使用AHDL语言,在MaxplusII 10.0上编译通过,并进行了仿真。     1. 仲裁器信号定义 SUBDESIGN  PCI_arb(       -- 输入PCIclk         :INPUT  -- PCI时钟          Arbiter_rstN     :INPUT  -- 复位信号          PCIreqN[3..0]    :INPUT  -- 总线占用请求信号          frameN         :INPUT  -- 数据交易的启动或开始,主设备发出          irdyN           :INPUT  --交易数据准备好,主设备发出          -- 输出          PCIgntN[3..0]    :OUTPUT -- 总线占用允许信号     )     frameN和irdyN决定了总线的状态,只要两个信号中的一个有效,就表明总线上有数据通过,总线处于忙状态;当两个信号都无效时,则总线处于空闲状态。 2. 仲裁器状态机定义parb_sm : MACHINE  OF BITS ( PARB2 , PARB1 , PARB0 )  WITH STATES (    PARB_SLT0  = 0, -- PCIgnt0#有效,设备0拥有总线使用权,总线空闲    PARB_SLT0D = 1, -- PCIgnt0#有效,数据在总线上传输,总线处于忙状态    PARB_SLT1  = 2, -- 以下类同    PARB_SLT1D = 3,    PARB_SLT2  = 4,    PARB_SLT2D = 5,    PARB_SLT3  = 6,PARB_SLT3D = 7 );     3. 仲裁的实现    由于采用循环算法,对每一个设备而言状态的变换都是相同的,下面仅以设备0的状态转换为例:    CASE  parb_sm  IS       WHEN PARB_SLT0 =>           IF ( !frameN # !irdyN # frameN & irdyN & PARBtout4 ) THEN              IF ( !PCIreqN1 ) THEN                 PCIgntN1  = GND;                 parb_sm   = PARB_SLT1D;              ELSIF ( !PCIreqN2 ) THEN                 PCIgntN2  = GND;                 parb_sm   = PARB_SLT2D;              ELSIF ( !PCIreqN3 ) THEN                 PCIgntN3  = GND;                 parb_sm   = PARB_SLT3D;              ELSE                 PCIgntN0  = GND;                 parb_sm   = PARB_SLT0D;           ELSE              PCIgntN0  = GND;              parb_sm   = PARB_SLT0D;           END IF;       WHEN PARB_SLT0D =>          PCIgntN0    = GND;           IF ( frameN & irdyN ) THEN              parb_sm   = PARB_SLT0;           ELSE              Parb_sm   = PARB_SLT0D;           END IF;         为了避免AD线上和PAR线上出现时序竞争,一个设备的PCIgntN信号有效和另一个设备的PCIgntN的撤销,如果不是在总线空闲状态,则两者之间至少要有一个时钟的延迟。设计中,将每个设备占用总线的状态分为两部分,PARB_SLTx(总线空闲)和PARB_SLTxD(总线忙);状态机不能从一个设备的PARB_SLTxD状态直接转到另一个设备的PARB_SLTyD状态,中间必须经过至少一个时钟的PARB_SLTx状态的衔接,这样就避免了总线上竞争的出现。     代码中,PARBtout为一5位计数器,对PCI时钟个数进行计数,用来判别设备发出请求信号后是否在规定时间内(16个时钟,即PARBtout[4..0] = 10000)占据了总线,启动了数据的传输;如果超时,则撤销该设备的请求信号,并按预设的优先级顺序,对其余设备总线使用权进行新一轮的裁定。计数器的编程实现: IF ( PARBtout4 # PCIreqN0 & PCIreqN1 & PCIreqN2 & PCIreqN3 ) THENPARBtout [ ] = 0;     ELSIF ( frameN & irdyN ) THEN        PARBtout [ ] = PARBtout [ ] + 1;     ELSE        PARBtout [ ] = 0;     END IF; 四、仿真分析     1. 单一设备总线请求情况     系统初始化后自动将总线停靠于设备0上,总线处于空闲状态,frameN、irdyN均为高电平。需要强调的一点是,仲裁所用的PCI控制信号均在PCI时钟信号的上升沿采样而得。如图3所示,设备2发出总线占用信号,仲裁器在时钟上升沿A处采样到该信号,并开始启动PARBtout计数,此时的frameN、irdyN为高电平,设备0仍然拥有总线使用权;随后设备2驱动使得frameN和irdyN有效,在时钟上升沿B处,仲裁器采样到frameN和irdyN,计数器清零,使设备2的PCIgntN2信号有效,从而占用总线,设备把地址、数据驱动到总线上,总线处于忙状态。 之后,设备2撤销其PCIreqN2信号,放弃对总线的占用;接着frameN、irdyN信号相继无效,表明数据传输的完成,总线变为空闲,仲裁器在C处采样后,将总线停靠在设备2上。     2. 多个设备同时请求总线使用权(以两个设备为例)     设备3首先发出请求信号,仲裁器在时钟A处采样后,计数器开始计数,此时总线仍然为设备0占用着;在时钟B处的采样,检测到frameN有效,表明数据传输的开始,仲裁器使得PCIgntN3信号有效,设备3获得总线所有权;     在随后的一个时钟上升沿,仲裁器采样到设备2的总线请求信号,此时由于frameN、irdyN依然有效,表明数据传输正在进行中,必须等当前数据传输完成后,设备2才能占用总线进行自己的数据传输,此时仲裁器隐含设定设备2拥有总线使用权。设备3在时钟C之前使得frameN、irdyN无效,总线进入空闲状态,停靠在设备3上。设备2检测到总线空闲,驱动自己的frameN、irdyN信号,仲裁器在时钟D处采样到有效的frameN、irdyN信号后,使PCIgntN2有效,设备2占据总线,开始数据的传输。设备2使用完总线后,使总线回到空闲状态,停靠在设备2上;设备3检测到总线空闲,再次驱动frameN、irdyN有效,从而再次获得总线使用权(时钟上升沿F处)。所有传输完成后,总线将停靠在设备3上。     值得一提的是,如果设备3在被迫交出总线前不能完成所有数据的传输,它必须使自己的PCIreqN3信号持续有效,这样在设备2用完总线后,仲裁器能将使用权交回,从而完成剩余数据的传输。     图5为设备获得总线使用权,在设定的16个时钟周期内没有启动传输,仲裁器状态的变换。仍以两个设备为例。     五、应用CPLD进行PCI总线仲裁器的设计,系统结构简单;配置灵活,可以根据系统的需要,对有关信号进行裁减或者扩展;在线修改方便。本设计采用Altera的EPM3064实现,并应用于所设计的系统板中。  

    智能硬件 PCI 仲裁器 总线

  • 带USB接口的电子巡更系统的设计

     摘要:介绍一种具有数据传输速度快、支持热插拔和充电方便等特点的USB接口电子巡更系统;阐述电子巡更系统硬件电路及工作原野,并介绍该系统的软件组成及流程图。     关键词:电子巡更系统 信息钮扣 USB接口 设备驱动程序 电子巡更系统是智能楼宇中保安系统的一个子系统。保安巡更时,需按指定的路线和时间,依次以达各个巡更点进行巡更。在此系统中,各巡更点设有信息钮扣,保安用巡更机读取信息钮及当前时间。巡更完毕后,将巡更机交至安保中心,使之与计算机的USB接口相连,将存储在巡更机中的巡更数据输入计算机。所以,通过它可以了解保安的巡更情况,有效地管理和督促保安的工作。 1996年,Intel、Microsoft、IBM等七家公司共同推出USB1.0通用串行接口标准,随后带USB接口的产品陆续出现。USB接口具有速度快、支持热插拔和即插即用、易扩展、可提供总线供电等优点。 基于USB接口的诸多优点和本设计中巡更机的特点,我们在设计巡更系统时,采用了USB接口。该电子巡更系统具有使用方便、数据传输速度快、易扩展、充电方便、功耗低、性价比高等优点,有效地解决了传统巡更机的不足。图1 巡更机硬件原理框图1 电子巡更系统硬件设计 针对电子巡更系统的特点,为了降低开发成本,提高系统的性价比,本设计采用MCU+USB接口芯片的方案。MCU采用Atmel公司的AT89C52单片机,可以设置成低功耗方式。USB接口芯片采用Philips公司的PDIUSBD12。带USB接口的电子巡更系统硬件原理框图如图1所示。其中DS1302为高性能、低功耗、宽电压、带有RAM实时时钟芯片,它适合于工作电池供电设备的系统时钟。这里MCU通过它读了当前时间;24LC64为低功耗、宽电压、64Kb、支持I2C协议的串行CMOS电可擦除程序存储器EEPROM,这里用于存储巡更点信息钮扣的ID值和读取信息钮扣时间数据。DS1990A外形上是一种圆形不锈钢器件,内部存有64b的二进制代码,以此代码作为巡更点的ID值。DS1302和24LC64电压工作范围为2.5~5.5V,以I2C总线和MCU通信。DS1990A以单总线(1-Wire总线)和MCU通信。 本系统中巡更机采用3.6V可充电电池供电,充电电源由USB接口的5V电源线提供,电源电压监测电路如图2所示。其吕AMS1117是一个DC-DC电压变换器,其输入端为USB接口的5个电源线,输出端为3.3V电压,以此电压为3.6V电源充电。MAX9117是一个带有1.245V基准电压(Vref)的比较器。当电池电压下降到3V以下时,LED点亮,指示电量不足。    PDIUSBD12是一种性能优化的USB器件。它是一种与微控制器进行通信的高速爱用并行接口,它同时也支持本地DMA传输。设计人员可以在各种不同类型的微控制器中选择出最合适的微控制器,而且不需要专用的开发设备。这种组件方式增强了系统开发的灵活性,减少了开发时间、风险和费用,是开发USB外设的一种快捷和经济的途径。PDIUSBD12符合USB1.1规范,也符合大多数在规范,如成像类、大容量存储类、通信类、打印类和人工输入设备等。因此,PDIUSBD12非常适合数外围设备,如打印机、扫描仪、外部大容易存储器(Zip驱动器)和数码相机等的接口芯片。它使得当前使用SCSI的系统可以立即降低成本。 2 电子巡更系统软件设计 2.1 巡更机固件程序 巡更机固件程序从功能上主要分为两部分。 ①信息钮扣的读取操作程序。这一部分实现MCU主外围器件的初始化、读取信息钮以及对DS1302和24LC64的读写操作。调试时要注意I2C总线的时序问题。巡更机固件程序采用C语言编程。信息钮读取操作程序流程如图3所示。 ②MCU和USB接口的通信程序。这一部分程序要实现将24LC64中的数据经USB接口读入到上位计算机中。USB接口芯片PDIUSBD12的端点适用于不同类型的设备,可通过命令配置为4种不同的模式:模式0(非同步传输)、模式1(同步输出传输)、模式2(同步输入传输)和模式3(同步输入输出传输)。PDIUSBD12带有三个端点,即端点0、端点1和端点2。这里仅列出模式0(非同步传输)时各端点的配置表格,如表1所列。表1 模式0各端点配置 端点号 端点索引 传输类型 端点类型 方向 最大数据包容量/B 0 01 控制输出控制输入 缺少值 输出输入 1616 1 23 普通输出普通输入 普通普通 输出输入 1616 2 45 普通输出普通输入 普通普通 输出输入 64×2(双缓冲区)64×2(双缓冲区) 本程序设计时,使用PDIUSBD12的端点1和端点2进行上位计算机与巡更机MCU之间的命令和数据的传输。端点1和端点2设置成模式0,其中端点1进行命令的传输和应答,端点2用于数据的传输。端点1接收上位计算机发送过来的8字节的读指令,指令正确回应后,使用端点2返回读成功数据。通信中所使用的端点情况如图4所示(括号内为使用的端点号)。 PDIUSBD12收到上位计算机的数据包时,就以中断的方式通知巡更机的MCU。固件程序工作过程如下:当PDIUSBD12从USB收到一个数据包时,PDIUSBD12就会对MCU产生中断请求,MCU立即响应中断。巡更机固件程序将数据包从PDIUSBD12内部缓冲区移到数据缓冲区,并清零PDIUSBD12的内部缓冲区,以使之能接收新的数据包。在断处理程序中,MCU判断产生的中断类型,并进行相应的处理。其中断程序流程如图5所示。 2.2 巡更机驱动程序 Windows98和Windows2000已经为一些USB标准设备提供了驱动程序,巡更机目前还不是标准的计算机外设,所以必须针对巡更机的特点来编写驱动程序。本设计中巡更机驱动程序是通过Windows DDK来开发的,它是Microsoft公司提供的一个开发Windows驱动程序的工具,DDK提供了编译驱动程序的环境。该巡更机的驱动程序是WDM类型的,采用VC++编程。 驱动程序中对USB进行操作的请求都应调用系统例程,将其转化为一个URB结构,即USB请求块(USB Request Block),然后使用系统级的IRP将其提交。该驱动程序由四个模块组成:初始化模块、即插即用管理模块、电源管理模块和I/O控制模块。 ①初始化模块。DriverEntry为驱动程序的入口处,通过它来执行大量的初始化函数。 ②即插即用管理模块实现设备的热插拔和动态配置。驱动程序初始化完成后,接着对设备进行初始化,这主要是通过即插即用(PnP)管理器调用驱动程序中的AddDevice和IRP_MJ_PNP两个例程来完成的。当驱动程序从PnP管理器中收到IRP_MN_START_DEVICE请求时,驱动程序启动设备,并且准备好处理I/O操作。 ③电源管理模块负责设备的唤醒和挂起。电源管理器(powermanager)从整个系统的角度来管理电源,所有与电源相关的IRP都是由它发出的,它发出的请求包可以指定一种新的电源状态以及查询或更改一种状态。支持电源管理的驱动程序,在最大程序地帮助Windows合理地利用资源方面起着重要作用。值得注意的是,与电源相关的IRP必须在同步操作上有非常严格的要求。例如,任何时候在一个PDO(物理设备对象)中。只能有一个IRP_MN_QUERY_POWER或者IRP_MN_SET_POWER;电源IRP的处理要尽可能地快等。 ④I/O控制模块完成输入输出请求的大部分功能。设备的控制由设备控制例程(IRP_MJ_DEVICE_CONTROL)负责,主要是对设备进行一些操作命令的发送或者标志的读取。数据读写主要由IRP_MJ_READ和IRP_MJ_WRITE两个例程完成,只需在AddDevice中申请一个符号链接,并且在StartDevice中将此符号链接激活即可。    2.3 应用程序设计 在Win32系统中,每一个设备对象都抽象为文件,此时的应用程序只需通过几条简单的文件操作API函数,就可以实现与驱动程序中某个设备的通信。在本设计中,应用程序是该电子巡更系统的中心,采用Visual C++编程。其主要功能有:启动或关闭USB设备、检查USB设备、设置巡更参数、从巡更机中读取数据以及显示、比较、存储数据等。 结语 USB接口因其具有诸多优点,近年来为计算机外设的开发热点,尤其是USB2.0标准的推出,其传输速率可达480Mb/s,使其真正意义上成为了一种通用串行总线。而根据笔者的实际开发经验,Philips公司的PDIUSBD12是一种性能优良、经济、实用、高效的USB接口器件,很适合投资少、周期短的开发项目,而且可以根据自己的实际情况灵活地选择组件,相信其在各领域必有广阔的应用前景。

    智能硬件 USB 接口 电子巡更系统

  • 基于USB和多线程的实时数据采集系统

    摘要:说明基于USB技术的实时数据采集系统的硬件、软件实现;重点介绍PDIUSBD12带并行总线的USB接口器件以及基于多线程思想设计应用程序的方法。     关键词:USB PDIUSBD12 多线程 实时数据采集 1 问题的提出 随着信息技术的飞速发展,各种数据的实时采集和处理在现代工业控制中已成为必不可少的。这就为我们的设计提出了两个方面的要求:一方面,要求接口简单灵活且有较高的数据传输率;另一方面,由于数据量通常都较大,要求主机能够对实时数据做出快速响应,并及时进行分析和处理。 传统的外设与主机的通信接口难以满足上述第一个方面的要求。这些接口一般采用PCI部线或RS-232串行总线。PCI总线虽然有很高的传输率(可达132Mbps),还能“即插即用”,但是它们的扩充槽相当有限,且插拔并不方便。RS-232串行总线虽然连接方便,可是它的带宽非常有限,传输速度太慢,而且1条RS-232串口通信电缆只能连接1个物理设备。USB技术正是顺序这一要求提出的,它集PCI和RS-232的优点于一身:具有较高的传输速率(USB协议1.1支持最高传输速度达12Mbps,USB协议2.0支持最高传输速度可达148Mbps),实现了真正意义上的“即插即用”(Plug & Play),同时USB上最多可以连接127个外设。因此,将USB技术应用于数据的实时采集是非常适合的。 实时系统对多任务的要求比较普遍。往往在后台采集数据、进行数据显示的同时,还要在前台界面对用户的操作做出响应。在实时系统中,对实时数据做出及时而准确的反应是十分重要的。由于受A/D采集速度等因素的限制,从硬件上采用USB接口技术的确可以提高速度,但毕竟潜力有限,因此在现有硬件设计基础上充分发挥软件的作用就能进一步提升速度。使用传统的单线程编程技术效率较低,无法及时处理,必须充分利用Windows的多任务处理功能,采用多线程编程技术来处理数据。 在这个实时采集系统的设计上,我们将这两种技术结合起来:在硬件上采用USB技术;软件用VC++进行开发,采用多线程编程,使系统的效率从这两方面都得到提升。 2 系统体系结构 2.1 硬件结构 整个系统硬件结构如图1所示。 实时数据采集系统主要由多路选择开关、A/D转换、单片机系统、PDIUSBD12、微机组成。多路选择开关对多路信号进行选择,使其分时输入;A/D转换实现模拟信号的数字化;单片机系统主要完成信号采集、数据通信;PDIUSBD12实现USB接口;微机完成数据接收、存入数据库、数据处理、计算、显示等功能。 其中PDIUSBD12是系统USB技术得以实现的关键。它是Philips公司的一个带并行总线的USB接口器件,支持本地的DMA传输。它完全符合USB1.1版的规范,同时集成了SIE(串行接口引擎)、FIFO存储器、收发器以及电压调整器。其主端点的双缓冲配置增加了数据吞吐量并轻松实现实时数据传输,功能框图如图2所示。    在这个系统中,单片机采用的是80C52。PDIUSBD12与80C52的接口有2种方式:多路地址/数据总线方式、单地址/数据总线方式。我们采用的是前一种方式:使用了80C52的INT0、ALE、WR、RD和P0口,当PDIUSBD12接收到主机的有效信息时,会产生一个中断通知80C52进行处理。在此种方式下,PDIUSBD12在ALE下降沿的时候,对单片机的输出地址进行锁存。若输出地址为奇数,则表示对PDIUSBD12发送指令;若输出地址为偶数,则表示对PDIUSBD12进行数据传输。接口电路如图3所示。 80C52将A/D采集的数据经PDIUSBD12的并行接口送入FIFO存储器。当USB的传输速率达到12Mbps时,MMU(存储器管理单元)和集成RAM作为USB之间速度差异的缓冲区,这就允许单片机以它自己的速率对USB信息包进行读写。若FIFO中数据已满,SIE会立即对数据做处理:同步模式的识别、并行/串行转换、位填充/解除填充、CRC校验/产生、PID校验/产生、地址识别和握手评估/产生。SIE实现了全部的USB协议层,完全由硬件实现而不需要固件的参与。数据经处理后由收发器通过数据线D+、D-传送到主机。对一个单片机而言,PDIUSBD12看起来就像1个带8位数据总线和1个地址位的存储器件。 2.2 软件结构 USB的软件系统包括三部分:客户应用软件、设备固件以及USB设备驱动程序。其中,设备固件和USB设备驱动程序又被称为主机软件。软件层次如图4所示。 2.2.1 固件设备 设备固件(firmware)是储存在程序内存中的代码。它使得USB接口芯片与主机和外设中其它电路能够通信。固件由USB驱动程序(USBD)、主控制器驱动程序(HCD)两部分组成。USBD的功能可以概括为:配置管理、总线管理、数据传输管理、提供客户服务。USBD把IRP划分为USB和设备需要大小的块,确保每一个设备能分配到它所要求的USB资源,这样它就可以支持USB设备配置。USBD提供了一个编程接口USBDI(USB驱动程序接口),给客户驱动程序一种方式,用于传输请求,传输的方向可以是来自或发往USB的功能单元。大量的客户服务是由USB的驱动程序提供的,它帮助USB的客户控制和访问它们的功能单元。HCD提供了对USB的低级支持,通过把IRP转换成为单独的事务处理后在USB上执行。    本系统固件设计的目标是使PDIUSBD12达到最高的传输速度。微处理器主要忙于多路数据的采集及处理,PDIUSBD12的固件设计成完全的中断驱动。USB的传输可在后台进行,这确保了最佳的传输速率和更好的软件结构,同时简化了编程和调试。它的基本思想是:后台ISR(中断服务程序)和前台主程序循环之间的数据交换通过事件标志和数据缓冲区来实现。当PDIUSBD12从USB收到一个数据包时,就对单片机产生一个中断请求,单片机立即响应中断。在ISR中,固件将数据包从FDIUSBD12内部缓冲区移到循环数据缓冲区,并在随后请求清零PDIUSBD12的内部缓冲区,以使其能接收新的数据包。然后返回到主循环,检查循环缓冲区内是否有新的数据并开始其它的前台任务。 基于这种结构,主循环不关心数据是来自USB、串口还是并口,只检查循环缓冲区内需要处理的新数据。这样,主循环程序专注于数据的处理而ISR能够以尽可能高的可能高的速度进行数据的传输。 这部分程序结构可包括: 主循环程序——发送USB请求,处理USB总线事件和用户功能处理等; 硬件提以层——对单片机的I/O口、数据总线等硬件接口进行操作; PDIUSBD12命令接口——对PDIUSBD12器件进行操作的模块子程序集; 请求处理程序——对USB的标准设备请求进行处理和对用户添加的厂商请求进行处理; 中断服务程序——当PDIUSBD12向单片机发出中断请求时,读取PDIUSBD12的中断传输来的数据,并设定事件标志和Setup包数据缓冲区,传输给主循环。 2.2.2 USB设备驱动设计 在Windows下,与USB外设的任何通信必须通过USB设备驱动,这个驱动知道如何与系统的USB驱动和访问设备的应用程序通信。设备驱动是保证应用程序访问硬件设备的软件组件,使得应用程序不必知道物理连接、信号和与一个设备通信需要的协议等的细节,可以保证应用程序代码只通过外设名字访问外设或端口目的地。应用程序不需要知道外设连接端口的物理地址,不需要精确监视和控制外设需要的交换信号。 设备驱动通过在应用层和硬件专用代码之间的转化来完成它的任务。应用层代码一般使用一套操作系统支持的函数,硬件代码则处理那些访问外设电路的必要协议。设备驱动能与应用程序之间相互通信是通过Windows提供的API函数,这些函数使应用程序能够控制显示器、处理信息、访问存储器、读写磁盘和其它设备。对于一些标准设备,Windows提供通用驱动;不过,这个实时数据采集系统是自定义的设备,对此Windows并不提供通用的驱动,需要对设备编写自定义的驱动,并且必须遵循微软在Windows98和更新版本中为用户定义的Win32驱动模式。Windows98和Windows2000中,USB总线驱动是WDM驱动,扩展名为.sys。编写USB设备驱动需要使用Visual C++,此外还需要Windows 98或2000设备开发包(98DDK/NTDDK)。USB设备驱动的编写通常不是一项简单的任务,驱动开发包就提供一种途径,通过做尽可能多的工作为跳过驱动开发,这些开发库有Blue Water Systems的WinDK和Compuware NuMega的DriverWorks。这些工具包能够集成到Visual C++编程环境中。运用这些工具包只需很少的时间就能生成一个高效的驱动程序。 这一部分可以包括4个模块:初始化模块、即插即用管理模块、电源管理模块和I/O功能模块。初始化模块提供一个DriverEntery入口点来执行大量的初始化函数。即插用模块实现USB设备的动态插拔及配置。当硬件检测到USB设备接入时,Windows查找相应的驱动程序,并且调用它的DriverEntery例程,PnP(即插即用)管理器调用驱动程序的AddDevice例程,通知它添加了一个设备。驱动程序会收到一个包含有设备分配资源信息的启动设备的IRP,在对设备进行正确配置后,开始与硬件的对话。在运行过程中,如果设备被拔除,PnP会发出相应的IRP,驱动程序会进行盯应处理。USB设备的挂起和唤醒是由电源管理模块进行管理的。I/O功能模块完成I/O请求的工作。 2.2.3 应用程序设计 固件程序和USB设备驱动程序的设计是USB设备开发者的工作,对于广大用户而言,与系统的交互是通过应用程序实现,而且整个实时采集系统的主要数据处理都是在这里完成的。因此,运行效率高、界面友好、具有强大数据分析和处理的应用程序的设计,也是系统设计上一个不容忽视的关键因素。应用程序的主要功能有:启动/关闭USB设备,检测USB设备,设置USB数据传输管道/端口,设置A/D,采集数据,显示/分析数据。这里,我们采用Visual C++6.0作为程序的开发环境,并且充分运用了多线程的编程思想。 在这个设备中,设置4个线程:首先是1个主线程,负责用户界面,并保持中枢地位。它的生存周期也就是整个用户程序的主存期,用户的动作(例如鼠标事件、键盘事件)都会触发主线程的消息机制,从而完成对用户的响应;而3个分离的辅助线程分别负责数据的采集、数据的分析处理以及数据的显示这3个不同的任务。辅助线程是在主线程运行过程中产生的,它的生命就是线程函数本身,函数一旦return,线程就结束了。因此,辅助线程的生存周期只是整个程序生存期的一部分。 MFC程序只会有一个CwinApp对象,而CwinApp派生自CwinThread,即产生了应用程序的主线程。每当需要一个额外的线程时,应先产生一个CwinThread对象,再调用全局函数AfxBeginThread(),将线程产生出来。 对于辅助线程(worker thread),要为它准备一个线程函数,然后调用AfxBeginThread()。例如:CWinThread* pThread=AfxBeginThread(ThreadFunc,&param); UINT ThreadFunc(LPVOID pParam); //线程函数 对于用户界面线程(UI thread),不能够光由一个线程函数来代表,因为它要处理消息,它需要一个消息循环。应该先从CWinThread派生一个自己的类,再调用AfxBeginThread()产生一个CWinThread对象。具体程序见本刊网站(http://www.dpj.com.cn)。 结语 基于USB技术的实时数据采集系统,在编程上运用了多线程思想;从硬件和软件两方面录求较佳的解决途径,并将二者结合起来,在实际中取得了良好的运行效果。

    智能硬件 USB 多线程 实时数据 采集系统

  • 采用USBN9602的数据采集系统设计

    摘要:通用串行总线(USB)作为一种新的微机总线接口规范,具有便捷、易扩展、低成本、低干扰等特点,非常适合作为主机和外设之间的通信接口。本文介绍基于USB总线的数据采集设备的开发方法,包括硬件设计、Firmware(固件)设计、基于Windows驱动程序模型(WDM)的设备驱动程序设计以及应用软件的设计,同时还介绍基于USB的远程数据采集系统。     关键词:USB 软件狗 加解密技术 反破解 在工业生产和科学技术研究过程的各行业中,常常要对各种数据进行采集,现在常用的采集方式是在PC机或工控机内安装数据采集卡,如A/D卡及422卡、485卡、采集卡不仅安装麻烦,易受机箱内环境的影响,而且由于受计算机插槽数量和地址、中断资源的限制,不可能挂接很多设备;而用串行总线USB(Universal Serial Bus)能很发地解决以上这些冲突。 利用89C51设计基于USB总线的数据采集设备,还可与MAX485结合起来实现数据的远程采集。该系统具有可靠性高、性价比高和多点采集等优点。 1 系统硬件设计 USB数据采集系统硬件模块主要由串行A/D转换器、89C51芯片、USB接口芯片和多路模拟开关等组成。硬件总体结构框图如图1所示。 USB接口芯片采用National Semiconductor公司的一种专用芯片USBN9602。该芯片内部集成微处理器接口、FIFO存储器、时钟发生器、串行接口引擎(SIE)、收发器和电压转换器,支持DMA和微波接口。 多路模拟输入信号经多路模拟开关控制将其中的一路接入串行A/D转换器,A/D转换器经光电隔离后串行输出到移位寄存器,移位寄存器将此结果转为8位并行数据。89C51系统通过8位的并行接口传送A/D转换器采集的数据,存储在FIFO存储器中;一旦FIFO存满,SIE立刻对数据进行处理,然后89C51系统将数据从FIFO存储器中读出,由收发器通过数据线(D+、D-)送至主机。USBN9602与89C51的具体接口电路如图2所示。图中USBN9602的CLKOUT与89C51的XTAL1相连,即USBN9602的时钟输出为89C51提供时钟输入。USBN9602的复位端接RC电路,以保证复位电路可靠地工作。由于晶振频率较高,结合USBN9602内部网络,在XOUT端串接100μF电容及470μF电感,起稳定内部振荡频率的作用。2 系统软件设计 系统软件包括设备固件、USB设备驱动程序和应用程序。 2.1 设备固件(firmaware)设计 此处固件是指固化到89C51 Flash中的程序。其主要功能是:①控制A/D转换器的采样;②控制芯片USBN9602接受并处理USB驱动程序的请求及应用程序的控制指令。现主要介绍89C51系统如何控制USB控制器(USBN9602)与主机的通信。 89C51系统对USB控制器的操作是严格按照USB协议1.1进行的。按照USB协议1.1的规定,USB传输方式分为4种:控制传输、块传输、同步传输和中断传输。在实际开发中使用了控制传输和块传输。控制传输主要完成主机对设备的各种控制操作,也就是实现位于主机上的USB总线驱动程序(USBD.SYS)以及编写的功能驱动程序对设备的各种控制操作。块传输主要完成主机和设备间的大指数据传输以及对传输数据进行错误检测(若发生错误,它支持“重传”功能)。 89C51系统控制USB控制器的工作工程可以简单地概括为:当USB控制器从USB总线检测到主机启动的某一传输请求后,USB控制器通过中断方式将此请求通知89C51系统;89C51系统通过访问USB控制器的状态寄存器和数据寄存器,获得与此次传输有关的各种参数,并根据具体的传输参数,对USB控制器的控制寄存器和数据寄存器进行相应的操作,以完成主机的传输请求。理解了以上的工作过程就可以进行相应的固件设计。 2.2 USB设备驱动程序设计 USB系统驱动程序的设计是基于驱动程序模型WDM(Window Driver Model)的。WDM采用分层驱动程序模型:较高级的USB设备驱动程序和较低级的USB函数层。其中USB函数层由两部分组成:较高级的通用串行总线模块(USBD)和较低级的主控制器驱动程序模块(HCD)。 目前,Windwos98提供了多种USB设备驱动程序,但并不针对数据采集设备,因此需用DDK(设备驱动程序开发包)开发工具设计专用的USB设备驱动程序。目前,写USB驱动程序的软件也很多,它们均提供用于生成USB驱动的代码生成器,用户按照提示可以定义设备的配置和功能,然后做功能的修改即可。利用软件中提供的例子进行修改也是一个比较好的捷径。可以把USB设备驱动程序的功能划分成4个不同的模块来实现:初始化模块、即插即用管理模块、电源管理模块以及I/O功能实现模块。 初始化模块提供1个入口函数DriverEntry(),整个驱动程序的入口点为DriverEntry例程。在DriverEntry中,需要提供一个AddDevice例程,把驱动程序添加到驱动程序堆栈中去。另外,所有对各种IRP(I/O请求包,如:IRP_MJ_CREATE,IRP_MJ_WRITE,IRP_MJ_CLOSE,IRP_MJ_READ,IRP_MJ_DEVICE_CONTROL等)的处理例程都在此入口函数中作为定义,如: DriverEntry(IN PDRIVER_OBJECT DriverObject,…) //驱动程序入口 { DriverObject->DriverExtension->AddDevice=USBAddDevice; DriverObject->DriverUnload=USBUnload; DriverObject->MajorFunction[IRP_MJ_READ]=USBRead; DriverObject->MajorFunction[IRP_MJ_WRITE]=USBWrite; … }图2 USBN9602与89C51接口电路    即插即用管理模块用来实现USB设备的热插拔及动态配置。当硬件检测到有USB设备接入时,Windows98查找响应的驱动程序,并调用它的DriverEntry例程。PnP(即插即用)管理器调用驱动程序的AddDevice例程,告诉它添加了一个设备。在此处理过程中,驱动程序收到一个设备启动请求(IRP_MN_START_DEVICE)的IRP。同理,当要拔除时,PnP管理器会发出一个设备删除请求(IRP_MN_REMOVE_DEVICE)的IRP,由驱动程序进行处理。通过对这些PnP请求的处理,可支持设备的热插拔和即插即用功能。 电源管理模块负责设备的挂起与唤醒。 I/O功能实现模块完成I/O请求的大部分工作。若应用程序想对设备进行I/O操作,它便使用Windows API函数,对WIN32子系统进行WIN32调用。此调用由I/O系统服务接收并通知I/O管理器,I/O管理将此请求构造成一个合适的I/O请求包(IRP)并把它传递给USB设备驱动程序。USB设备驱动程序接收到这个IRP以后,根据IRP中包含的具体操作代码,构造相应的USB请求块并把此URB(USB请求块)放到一个新的IRP中。然后,把此IRP传递到USB总线驱动程序,USB总线驱动程序根据IRP中所含的URB执行相应的操作(如从USB设备读取数据等),并把操作结构通过IRP返还给USB设备驱动程序。USB设备驱动程序接收到此IRP后,将操作结果通过IRP返还给I/O管理器。最后,I/O管理器将此IRP中操作结果返还给应用程序,至此应用程序对USB设备的一次I/O操作完成。 2.3 应用程序设计 用户态的应用程序是数据采集系统的中心,其主要功能为:开启或关闭USB设备、检测USB设备、设置USB数据传输管道、设置A/D状态和数据采集端口、实时从USB接口采集数据、显示并分析数据。 由于USBN9602提供的FIFO不超过64字节,当它存满后,USBN9602自动将数据打包即时请求读入数据,由SIE自动发送数据包。另外,当系统启动A/D模块后,便会创建两个线程:采样线程和显示存盘线程。采样线程负责将采集数据写到应用程序提交的内存;而显示存盘线程负责给应用程序发送显示和存盘消息。当应用程序接收到此消息后,便从它提交的内存读取数据并显示和存盘。此处需要注意的是,采样线程和显示存盘线程在读写应用程序提交的内存时要保持同步。 3 远程数据采集系统设计 传输距离是限制USB在工业现场应用的一个障碍,即使增加了中继或Hub,USB传输距离通常也不超过几十m,这对工业现场而言显然太短了。现在,工业现场有大量采用RS-485传输数据的采集设备,其优点主要为传输距离可达到1200m以上,并且可以挂接多个设备;但传输速度慢,且需要板卡支持,安装麻烦。将RS-485与USB结合起来,可以优势互补,产生一种快速、可靠、低成本的远程数据采集系统。 设计这样一个系统的关键设备是RS-485~USB转换器,可以采用USBN9602+89C51+MAX485实现这一功能。整个系统的基本思想是:将传感器采集到的模拟量数字化以后,利用RS-485协议将数据上传。RS-485~USB转换器在主机端接收485的数据。并通过USB接口传输到主机处理;而主机向USB发送数据时,数据通过RS-485~USB转换口转换为485协议向远端输送,从而实现远程数据的双向传输如图3所示。软件方面的设计与上面所述类似。 结语 目前,基于USB外设的应用在国外处于高速发展阶段,在国内的应用也已经日见扩大;利用USB进行数据采集和工业控制已得到成功应用,特别是随着USB协议2.0的推出,数据传输速率高这480Mbps。如此高的传输速率,必将使USB在数据采集中的优势更加充分地体现出来,同时会使其在更广阔的领域得到更深层次的应用。

    智能硬件 系统设计 数据采集 usbn 9602

  • 基于CH371的USB接口虚拟示波器设计

     作者Email:  violit@netease.com     摘要:本文介绍一款USB接口的虚拟示波器的设计方案,重点介绍了USB总线接口芯片CH371的原理及应用,降低了USB系统开发的门槛,并达到令人满意的效果。     关键词:USB接口,虚拟示波器,CH371,高速数据采集     一、引言     对于学校教学实验以及某些特定需求来说,目前市场上的模拟及数字示波器也许并不适用,价格高昂、体积较大且很多专业功能并不实用。而现在电脑的普及程度也达到了相当的规模,利用电脑以及附加的数采模块实现一个灵活便捷的虚拟示波器能够满足大多数的工作、学习和开发需要,并且可以通过较低代价的硬件和软件升级实现相当复杂的信号处理功能,能够以较低的成本、较小的体积实现配置灵活的智能仪器组合;完全可以与便携电脑结合,构成便携式检测维修工作站。目前已经有计算机并口通信的数据采集器,但是USB的应用日趋广泛和深入,如果将USB功能融合在里面则可以实现更高的数据传输率、更方便的使用方式,更为优越的体现出虚拟仪器的性能。     二、硬件设计     此虚拟示波器的数据采集器由以下功能模块组成:前端信号变换模块、高速模数转换模块、高速数据缓冲模块、单片机控制模块、USB接口模块和电源模块。前端信号变换、高速数据采集有成熟的方案并且可根据需要的指标,譬如采样率、量程控制、采样深度等进行设计,我们这里主要讨论USB接口部分的开发。     USB接口的开发以往都是一个令人头痛的问题,尽管很多设计者向往USB接口高速传输、自主供电、即插即用的优点,但较难逾越它的协议固件开发和驱动程序开发的障碍。在这个方案里,笔者选用了一款不需要开发协议固件和驱动程序的USB总线接口芯片。     南京沁恒公司(www.winchiphead.com)推出的CH371是一个USB总线的通用接口芯片,它利用硬件逻辑屏蔽了USB 通讯中的所有协议,在计算机应用层与本地端控制器之间提供端对端的连接。基于CH371,设计者不需要了解任何USB协议、固件程序以及驱动程序,可以轻松地将原来的并口、串口的产品升级到USB接口,以较低的风险和成本享用USB接口带来的优越性。     使用时在本地端,CH371具有8位数据总线和读、写、片选控制线以及中断输出,就像操作一般外设芯片一样方便地挂接到DSP、MCU等控制器的系统总线上;在计算机端,CH371的配套软件包括通用驱动程序以及应用软件包,提供了简洁易用的操作接口,与本地端的单片机通讯就如同读写硬盘中的文件一样简单,开发者可以使用VB、VC、C++Builder等高级语言进行开发。一般情况下,基于CH371设计USB产品不必考虑USB通讯协议、固件程序、驱动程序、配置过程、底层数据传输过程。设计者所要做的工作与设计并口、串口的产品一样,包括两件事:一是从计算机的应用层发出数据传输请求并接收应答;二是当USB 产品的控制器被通知有数据传输请求时,作出应答。     同时,CH371在提供了透明的USB协议的基础上还提供了I2C器件的直接管理、16个地址的直接读写以及复位、看门狗等功能,本地端甚至不使用单片机就可完成简单的控制功能,因此具有较强的功能适应性,能够满足不同场合的需要,有效的降低系统成本。     在本系统中使用的是SOP28封装的产品,他的管脚定义如下表:         根据不同的工作方式,芯片的接口类型可以有以下几种:被动并行接口、I2C主接口、主控方式接口。其中被动并行接口是最常用的方式,它提供单片机与计算机的连接,CH371作为单片机的一个被动外设;I2C主接口是CH371在计算机端程序的控制下不经过单片机直接读写一个EEPROM器件(譬如24C04等),经常用于USB外设的产品信息纪录;主控方式接口是不使用单片机,由计算机端程序直接控制CH371提供的16个地址的8位数据读写或者是十几根IO口线,此方式主要用于完成相对简单的外部控制任务。这几种接口方式并非完全对立的,可以根据需要灵活配置。在此虚拟示波器中则将其使用为单片机的一个外设器件,同时将A3~A0用于主控方式由计算机控制四只LED。     单片机对于CH371的控制依靠对其内部的16个寄存器的操作来实现。这16个寄存器的地址有两种定义方式。一种是上电复位后默认为直接地址方式,A3~A0四个管脚为寄存器地址,这种方式较为简单,但是需要使用单片机较多的IO口资源;另一种是当CH371检测到ALE脚上的上升沿信号后,切换到复用地址方式,寄存器地址由数据总线的D3~D0来控制,根据ALE的跳变来判断是寄存器操作还是数据读写。在此设计中由于大容量数据缓冲需要使用到74373作为地址锁存,所以即使使用直接地址方式也无需多占用单片机资源,但是为了将A3~A0节省出来驱动LED所以选用复用地址方式。     根据系统的要求我们设计硬件如下。     USB接口提供数据交换及电源供应(经适当变换后供高速AD使用),CH371在12M晶振下倍频工作,提供与单片机接口的同时提供看门狗复位输出功能,I2C主控功能没有使用,A3~A0可以由计算控制驱动4只LED作为工作显示信号。单片机89C52的P1口组用于控制数据采集模块,包括量程转换控制、AD触发信号、采集数据溢出信号等;高速缓存62256通过低功耗的CPLD控制存放高速AD采集的结果,单片机定时将其中数据读出经CH371传送到计算机的数据显示和分析软件,实现虚拟示波器功能。单片机、CH371和RAM部分原理图如下: 图三 单片机、CH371和RAM部分原理图     三、软件设计     单片机端软件:     单片机端软件主要完成数据采集控制、数据报告这两个功能。其中数据采集控制根据计算机端软件设定的增益、时基、触发等参数控制数据采集模块,这里面要用到计算机向单片机发送少量的控制信息;数据报告功能则需要单片机将缓存中的一个采集周期的所有数据传送给计算机端软件,这属于大批量数据的传输。我们把介绍的重点放在单片机与计算机的通信上面。     单片机与计算机通信是通过对CH371的寄存器操作实现的,有关其寄存器定义的具体情况请参考数据手册。     在应用中需要注意的是,CH371提供的单片机接收缓冲区为8个字节,多于8个字节的计算机下传数据被切分;而单片机的发送缓冲区也是8个字节,多于8个字节的上传数据需要分多次上传。另外,CH371的中断包括了上传及接受成功,中断发生后具体的情况需要由传输状态寄存器来辨别;同时其中断电平是单稳态的,一个事件发生后中断信号跳变,但仅维持一个短暂的脉冲便恢复,这是为了配合不同速度的处理器而作的处理。     单片机与计算机的USB通信主要功能子程序示例如下:(请在使用时加入CH371的相应寄存器的地址定义)file://********** CH371初始化程序******************************void ch371_init()   {       CH371_INT_SET=0;  file://CH371中断数据设定寄存器的地址偏移       CH371_LENGTH=0X0F;  file://置上传数据长度寄存器为15,表示暂时没有数据上传   save_length=0;   file://保存下传数据长度   IT0=1;      file://外部信号为下降沿触发   IE0=0;      file://清中断标志   PX0=1;      file://置高优先级   EX0=1;      file://允许中断}file://***********上传数据子程序********************************void ch371_upload(unsigned char len) file://参数传入数据长度{    unsigned char i;   unsigned char *up_buf;   unsigned char *ch371_buf;   if(len!=0){     up_buf=&ret_buffer;    file://指向数据的地址                        ch371_buf=&CH371_BUFFER;  file://指向数据缓冲区     for(i=0;i

    智能硬件 USB 接口 ch 371

  • USB接口芯片FT245AM的原理

    USB接口芯片FT245AM的原理及航空ARINC429总线测试仪中的应用     摘要:介绍了一种USB总线接口芯片FT245AM及其在航空ARINC429总线测试仪中的应用方法,同时介绍了FT245AM的内部结构、管脚说明以及与微处理器的接口电路,给出了航空ARINC429总线测试仪的总体框图、部分原理和接口逻辑的Verilog HDL源代码及仿真时序。     关键词:USB总线 ARINC429总线 FT245AM CPLD MCU 随着计算机的广泛就算,与计算机通信的方式也越来越多,对通信速度和易用性要求也越来越高,这使得USB通信方式显得越来越突出,应用领域也越来越广泛。因此,在鼠标、键盘、游戏杆、数据采集卡、数码相机、掌上电脑中都有USB的应用。 FT245AM是美国FTDI公司生产的一种USB专用芯片。它具有功能强、体积小、传输速度快、符合USB1.1技术规范、易于一微处理器接口等特点,因而倍受用户的青睐。笔者采用FT245AM成功地开发了航空ARINC429总线测试仪。    FT245AM集成了USB1.1通信协议和外设接口,可以方便地实现USB主机与外设MCU、CPLD的接口,其数据传输速率可达1MB/s。FT245AM内部128字节的接收FIFO和384字节的发送FIFO大大提高了USB主机与外设的通信质量。另外,FT245AM还具备3.3V的LDO调整器、8位频器、USB数据时钟恢复PLL、USB数据收发器,且EEPROM接口逻辑单元可外接串行存储器93C46,以实现USB VID、PID、序列号和设备说明字符串的存储。使用FT245AM可大大简化其外围电路,使用户设备更趋于小型化。 1 FT245AM简介 1.1 FT245AM内部结构和引脚功能 FT245AM芯片的内部结构如图1所示。该芯片采用QFP32封装,其各管脚说明如下: USBDP(7脚):USB差分数据正端; EEDATA(2脚):串行存储器数据; USBDM(8脚):USB差分数据负端; TEST(5脚):厂商测试管脚; 3V3OUT(6脚):3.3V电源输出; D[7:0](25~18脚):外设接口数据总线; XTIN(27脚):晶体振荡器输入; RD(16脚):外设读数据信号输入; XTOUT(28脚):晶体振荡器输出; WR(15脚):外设写数据信号输入; RCCLK(31脚):RC定时器; TXE(14脚):发送FIFO空标志输出; RESET(4脚):芯片复位输入; RXF(12脚):接收FIFO非空标志输出; EECS(32脚):串行存储器片选; EEREQ(11脚):串行存储器读取请求; EESK(1脚):串行存储器时钟; EEGNT(10脚):串行存储器读取允许; VCC,AVCC(3、13、26、30脚):分别为芯片电源和电路模拟电源; GND,AGND(9、19、29脚):芯片地和模拟地。 1.2 FT246AM与外设的数据传输方法 FT245AM具有外设接口控制单元,可以方便地与MCU、CPLD接口来实现数据交换。    当外设从FT245AM中读取USB主机数据时,如果FT245AM的管脚RXF为高电平,则表明FT245AM没有接收到USB主机发送的数据,此时外围MCU(CPLD)不能读取数据。而当MCU(CPLD)检测到RXF为低电平时,表明FT245AM的接收FIFO中已有USB主机发送的数据,此时外围MCU(CPLD)便可以通过外设数据总线读取数据。外设通过FT245AM读取USB主机数据的时序图如图2所示。 当外设通过FT245AM写数据到USB主机时,如果FT245AM的管脚TXE为高电平,则表示FT245AM内部正忙,外围MCU(CPLD)不能向FT245AM的发送FIFO中写数据。而当外围MCU(CPLD)检测到TXE为低电平时,则表明FT245AM的发送FIFO空闲,外围MCU(CPLD)可以向FT245AM中写数据到USB主机。图3所示是外设通过FT245AM向USB主机发送数据的时序图。 2 在ARINC429总线测试仪中应用 ARINC429总线在航空领域有着广泛的使用,该总线采用差分数据传输方式,支持12.5kbps和100kbps两种传输速率。由于ARINC429总线设备的应用领域比较特殊,因此需要较高的可靠性,同时其测试设备也显得尤为重要。为了方便该总线设备的测试,摆脱专用测试设备的不灵活性,急需一种方便快捷的通信方式来实现计算机与该总线设备的互连,使该总线设备的测试可以在计算机中自动完成,从而提供测试设备的灵活性和通用性。因此,提出了基于USB总线的ARINC429总线测试仪。 2.1 基于USB的ARINC429总线测试仪结构 考虑到USB总线为自供电试,最大可驱动500mA电流,故ARINC429测试仪选取4路接收、2路发送的结构。当然,如果允许外接电源,还可以实现更多的收发路数,但这样会降低USB总线的方便性。由于ARINC429总线的传输速率最大为100kbps,而USB1.1的通信能力可达12Mbps。,考虑到协议的额外开销,一路USB总线同时完成2路ARINC429总线的发送和4路接收。 为了提高ARINC429总线测试仪的实时性,可选用高速MCU控制USB接口芯片FT245AM,但MCU没有足够的I/O数,无法满足与ARINC429控制芯片连接的I/O管脚,因此,可选用CPLDEPM7128S来完成FT245AM的控制和数据传输。 基于USB的ARINC429总线测试仪结构如图4所示。图5所示是FT245AM部分的外围电路。 在谝测试仪电路中,EPM7128S用于完成ARINC429总线控制芯片DEI1016与USB控制芯片FT245AM的逻辑变换,以使USB主机可以实时发送数据到ARINC429总线设备,并实时接收设备返回的数据,以供主机中的测试软件进行记录和检测,从而满足设备故障的诊断和定位之需。    2.2 EPM7128S与FT245AM的接口实现 EPM7128S与FT245AM的接口电路主要完成从FT245AM的接收FIFO中读数据和向FT245AM的发送FIFO中写数据。采用纯硬件实现方式可使FT245AM的接口延时和整个测试仪通信环节的延时达到最小。 EPM7128S可与FT245AM共享工作时钟,它使用12条I/O与FT245AM相连,分别对应于FT245AM的D0~D7、TXE、RXF、RD、WR等。 对EPM7128S的编程可采用VerilogHDL语言,并采用Synplify综合,最后使用MAXPlus II进行布线和仿真。与FT245AM的接口设计代码如下: //------------- //产生FT245AM读信号 always@(posedge clk or negedge reset) begin if(reset = =1'b0) usb_rd<=1'b1; else if(usb_rxf= =1'b1) usb_rd<=1'b1; else if(usb_rd= =1'b0) usb_rd<=1'b1; else if((usb_rxf = = 1'b0)&&(usb_rden= =1'b1)&&(cnt= =2'd0)) usb_rd<=~usb_rd; end //--------------------- //计数器,控制FT245AM读写时序 always@(posedge clk or negedge reset) begin if(reset = =1'b0) cnt<=2'd0; else if(cnt !=2'd0) cnt<=cnt+1'b1; else if((usb_txe = =1'b0)&&(data_valid = =1'b1)&&(usb_rden= =1'b0)) ent<=cnt+1'b1; end //--------------------- //产生FT245AM写信号 always@(posedge clk or negedge reset) begin if(reset= =1'b0) usb_wr<=1'b0; else usb_wr<=(cnt= =2'd1); end //--------------------- //读取USB主机数据 always@(posedge clk or negedge reset) begin if(reset= =1'b0) rx_data<=8'b00; else if(usb_rd = = 1'b0) rxdata<=usb_data; end //--------------------- //向USB主机写数据 always@(posedge clk or negedge reset) begin if(reset = =1'b0) tx_data<=8'h00; else if(cnt[0] = =1'b1)tx_data<=data_429; end //--------------------- //FT245Amgn EPM7128S的数据三态接口 assign usb_data=(cnt[1] = =1'b1)?tx_data:8'hzz; //----------------------图5 FT245AM外围电路图3 结束语 本文介绍了USB接口芯片FT245AM的原理和在航空ARINC429总线测试仪中的具体应用实例方法。笔者将EPM7128与FT245AM的接口逻辑在MAXplus II环境下进行了仿真,结果表明:使用该设计完全可满足实际要求,因此,使用USB通信接口的航空ARINC429总线测试仪,大大便利了429总线设备与计算机的通信,有效提高了429总线设备的检测效率。

    智能硬件 USB am ft 245

  • 基于串行外设接口(SPI)的CAN总线隔离扩展设计

    作者Email: christinxl@hotmail.com     摘要:介绍了利用SPI口实现CAN总线隔离扩展的一种通信控制系统,详细叙述了此通信控制系统中主从通信模块的硬件设计控制,软件设计流程及实现方法。     关键词: CAN总线  SPI口  XINT1中断     一、引言     CAN总线是一种有效支持分布式控制和实时控制的串行数据通信协议,它是一种多主总线,网络上任意一个节点均可以在任意时刻主动地向网络上的其它节点发送信息,而不分主从,节点之间有优先级之分,因而通信方式灵活;CAN可以点对点、一点对多点(成组)及全局广播等几种方式传送和接收数据 ;CAN采用非破坏性位仲裁技术,优先级发送,可以大大节省总线冲突仲裁时间,在重负荷下表现出良好的性能。     CAN上的节点数实际可达110个,通信介质可以是双绞线、同轴电缆或光导纤维,直接通信距离最远可达10km(传输速率为5kbps);最高通信速率可达1Mbps(传输距离为40m)。CAN协议的一个最大特点是废除了传统的站地址编码,而代之以对通信数据块进行编码,CAN数据链路层采用短帧结构,每一帧为8个字节,易于纠错。可满足通常工业领域中控制命令,工作状态及测试数据的一般要求。同时,8个字节不会占用总线时间过长,从而保证了通信的实时性。     CAN总线具有较强的纠错能力,每帧信息都有CRC校验及其它检错措施,有效地降低了数据的错误率。CAN节点在错误严重的情况下,具有自动关闭的功能,使总线上其它节点不受影响。支持差分收发,因而适合高干扰环境。     我们设计的一种CAN总线主从通信控制系统如图1所示,该控制系统采用内外两层隔离控制形式,主控台向主CAN网络发送指令和数据,通过主从通信模块与从CAN网络中的节点通信,对分系统控制单位进行数据采集和控制。此系统使CAN总线的节点数增加了n倍;CAN总线的传输速率和通信距离大幅度的提高;抗干扰能力也大幅度的增强。     本文讨论的是CAN总线主从通信控制系统中主从通信模块的硬件、软件设计及实现方法。主从通信模块实现了主控台和从控制单元之间CAN网络数据通信的隔离扩展,对通信数据处理、传输和CAN网络控制有一定的借鉴作用。     二、硬件设计     主从通信模块控制原理框图如图2所示,核心芯片是TI公司TMS320C2000系列的适合于数字控制的一种DSP。它的单个芯片内包含了10位ADC转换器、片内flash程序存储器、事件管理器、数字输入输出I/O口等。为了便于与各种外围设备进行通信,DSP还提供了一些接口:CAN接口、串行外设接口(SPI)、串行通信接口(SCI)等。其中,SPI接口是工业标准的同步串行接口,是一种全双工、三线通信的系统。它允许DSP与各种外围设备以串行方式(可配置成1~16位数据同时、同步地被发送和接收)进行通信。在SPI接口中,数据的传输需要1个时钟信号和两条数据线。SPI可工作在主模式或从模式下。在主模式下,每一位数据的发送/接收需要1次时钟作用;而在从模式下,每一位数据都是在接收到时钟信号之后才发送/接收。     三、SPI的工作原理     1)SPI的信号说明     如图2通信控制部分原理图,两片DSP芯片的SPI使用4条线直接接口:串行时钟线(SPICLK)、主片输入/从片输出数据线SPISOMI、主片输出/从片输入数据线SPISIMO和低电平有效的从片选择线SPISTE。     SPICLK是主片的时钟线,为MISO数据的发送和接收提供同步时钟信号。每一位数据的传输都需要1次时钟作用,因而发送或接收1个字节的数据需要1~16个时钟的作用。主片的时钟是通过主片的硬件设置的,并和从片的SPICLK相连。     MISO是主片的输入/从片的输出数据线。主片的MISO应与从片的MISO相连进行高位在前的数据交换。MOSI是SPI接口的SPI主片输出/从片输入数据脚。这一引脚应当连接主片的数据输出和从片的数据输入端MOSI,进行高位在前数据的交换。     SPISTE只在从方式中用于低电平选中从片,对应的主片SPISTE脚被配置为I/O口作为从片的SPI片选输入脚。    2)主模式     发送和接收可以同时工作在主模式下。主模式的显著特征是不论是发送还是接收始终有SPICLK信号,发送操作是由向SPIDAT(或SPITXBUF)中写数据而触发的。在主模式下,时钟信号的1次作用对应一位数据的发送(M0SI)和另一位数据的接收(MISO)。如图3所示,在主片中数据从移位寄存器中自左向右发出送到从片(MOSI),同时从片中的数据自右向左发到主片(MISO),经过16位时钟周期完成1个字节的发送。输入字节保留在移位寄存器中,此时SPI INT FLAG位自动置位(如果有中断设置,则产生中断),移位寄存器的数据将被锁存到SPIRXBUF中,此后对SPIRXBUF的读操作将把数据读出。    3)从模式     发送和接收同时工作在从模式下。从模式的显著特征是:不论是发送还是接收始终必须在SPICLK信号作用下进行,并且SPISTE信号必须有效。当SPISTE信号无效时,数据的发送无法进行并且输入的数据视为无效。这是因为输入的时钟信号是与SPICLK的逻辑与操作,而SPICLK信号是SPISTE的反转。这样当SPISTE为高时,就没有时钟信号输入。数据的发送和接收的过程见图3所示,与主模式下基本相似,只是移位寄存器的数据移出和输入方向与之相反。     四、软件设计     SPI通信以一帧CAN报文5个字节为一个传送单元进行信息交换。主片控制着SPICLK信号可在任一时刻启动报文传送;从片在传送报文之前,通过口线向主片发送一个外部中断请求,请求成功后主片输出SPICLK信号来启动从片的报文传送。从片在SPI中断中接收主片传送来的报文;主片在外部中断中完成从片报文的接收。当主片和从片同时都有报文传送时,系统优先传送主片报文,然后再传送从片报文。     1、主片发送,从片接收报文      主片发送报文,从片接收报文软件流程图如图4所示。主片在向从片传送报文前禁止外部中断,也就是禁止从片发送报文。然后从CAN传送缓冲区取一帧报文放入SPI发送暂存器中,再从SPI发送暂存器中取一个字节的数据写到SPITXBUF寄存器中启动SPISIMO引脚上的数据发送,同时,从片响应一个SPI中断开始接收主片发送来的数据,当从片接收到一个字节后,通过口线触发主片的XINT1外部中断来告知主片数据已接收,主片响应了此XINT1外部中断后,再发送下一个字节的数据,当一帧报文传送完成后,主片将外部中断使能,以便接收报文。从片接收完报文后,置报文接收完成标志,以便CPU进行报文的处理。     2、从片发送,主片接收报文     从片发送报文,主片接收报文软件流程图如图5所示。从片在发送报文前,通过口线向主片发送一个XINT1外部中断,请求报文的发送,当主片响应了此中断时,发送一个伪数据(如#0FFFFh)来告知从片可以开始报文的发送,从片测试到报文请求受理标志置位后,再从CAN传送缓冲区取一帧报文放入SPI发送暂存器中,再从SPI发送暂存器中取一个字节的数据写到SPITXBUF寄存器中,通过口线向主片发送XINT1外部中断,请求主片取数据,主片在XINT1中断服务程序中监测到中断标志置位时,发送伪数据#0FFFFh(启动从片数据发送的SPICLK时钟),然后将收到的字节存入SPI接收缓冲区,从片依次将一帧报文传送完成后,清报文受理标志。主片完成一帧报文接收后,置报文接收完成标志,并退出外部中断,以便CPU进行报文的处理。          3、关键技术的处理      CAN总线上信息的传送都是没有规律随机的,所以用SPI口实现主从系统间信息的传递时,必须考虑当有数据正在从DSP1向DSP2传送时,应该禁止数据从DSP2向DSP1传送,反之也然。否则数据在互传过程中就会出错或丢失,影响CPU的正常工作。为了避免主从报文在发送过程中产生冲突,主片在XINT1中断服务程序中完成一帧报文的接收,从片在SPI中断服务程序中完成报文的接收。在进行报文传送时,不管是主片还是从片只有当一帧报文传送完成后,才能进行下一帧报文的传送。主、从片每发送完一个字节的数据,都有一个应答信号返回标志位(见标志位意义)的判断,以便确认数据是否完整的发送或接收。     由于主片掌握着报文传送的时钟信号,即主动权,所以主片随时都可以进行报文的传送。从片在报文传送前,首先要确认主片此时是否传送空闲,若此时主片正在传送报文,从片等待主片将报文传送完成,再进行报文的传送;若主片正处于传送空闲状态,从片可以开始传送报文。     五、结束语     此CAN总线主从通信控制系统外加一些辅助控制单元(如显控单元,操作键盘等)后可作为从CAN网络的主控制器使用,在主控台CAN网络发生异常不能正常工作时,能够辅助控制分系统的运行,此项设计已经在控制系统中得到了应用。

    智能硬件 串行 can spi 外设接口

  • EPP模式500ksps数据采集接口

    作者Email: whxcds@hotmail.com     摘 要: 文章通过对微机并行口EPP模式下数据读取时序的深入实验分析,研究了实现500ksps数据连续采集及传输涉及的软件和硬件相关因素,并采用CPLD器件结合大容量SRAM构成FIFO,实现WIN98环境下EPP模式高速数据采集接口。     关键词:   EPP  CPLD    FIFO   数据采集     数据采集系统中,通过微机COM端口的RS-232串行通讯及通过微机并行端口的并行通讯具有开发使用方便的特点,前者可与工作于11.0592MHz晶振下的8052单片机在波特率115200时,实现10ksps(samples per second)的连续数据采集和传输而不丢失数据,若要达到更高速率的数据采集,可以通过并行口通讯方式实现。当前微机均可通过配置CMOS,将基地址为378H的并行口设置为EPP模式以支持通过数据口双向传输通讯,并由芯片硬件自动产生握手信号,实现高速传输的目的。     为充分实现EPP模式的高速特性,外设应当及时响应EPP的握手信号,当数据采集系统工作于非实时多任务的WIN98操作系统环境下,为实现数据高速、均匀性采样,还需要在外设配置必要的数据缓冲存储器。如果数据采集速率低于EPP模式数据读入平均速率,就可能实现数据的连贯有效性。有资料[1]说明在EPP模式,可实现500kBytes/s以上的传输速率,这表明通过EPP模式,可以实现500ksps的数据采集系统。通过对EPP模式的深入实验分析,发现要实现500ksps,外设硬件及微机软件程序均要采取一些策略:硬件上必须配置FIFO数据缓冲存储器,才能协调数据采集严格的时间间隔要求与数据传输给微机的非实时、非均匀性之间的矛盾;软件程序方面应当采取双字读的方法,否则EPP模式下仅能实现250kBytes/s数据读取可行性。     1  EPP模式读取速率的实验分析     图1为实验EPP模式读取速率的电路,实验程序为         Delphi结合内嵌汇编语言,涉及EPP读取的关键代码如下: FUNCTION READDATA:BYTE;VARSTARTTIME,STOPTIME,DELAY:INT64;NUMBER:LONGWORD;QUERYPERFORMANCECOUNTER(STARTTIME);FOR NUMBER:=0 TO 999999 DO  BEGIN    ASM    MOV DX,$37C    IN AL,DX    MOV RESULT,AL    END;  END;QUERYPERFORMANCECOUNTER(STOPTIME);DELAY:=STOPTTIME-STARTTIME;END;     此为循环1000000次读取EPP数据口程序,循环仅为方便用计时及示波器观察而设,并在执行前后分别读取系统计数值,DELAY值除以1.2后为执行花费的时间(单位为微秒),执行前先通过对地址379H的D0位写入高,使该位为低(注意:对该位写入低通常不能达到使该位变为低的目的,只有采取写入高才能使该位变为低),以清除EPP超时位,当A、B点均为低时,可实现最快的EPP握手,若A为高、B为低时,由于EPP周期开始时满足WAIT为低的要求,EPP自动在DATASTB处输出低,但因WAIT没有出现表示应答的高状态,EPP在延时10μs后,将DATASTB恢复为高以结束该次EPP访问过程,并置超时位。稍后因WAIT为低再次开始一次EPP访问过程,如果B为高,则WAIT为高,不能满足EPP的开始条件,故DATASTB保持为高,EPP在延时10μs后结束该次EPP访问过程,并置超时位。在发生超时情况下,数据仍然可正确读入(这一特性与笔者所查资料[1]有出入),此结论可通过对比循环前后时间差来及实际读入数据值证实。     注意程序循环中并未执行清除EPP超时位的指令,根据笔者实验,即使已发生EPP访问超时,也不影响下一次的EPP读周期(包括对37BH的地址读及对37CH的数据读),但超时对EPP写周期有影响,在清除超时位之前,EPP写周期无效(因本文不涉及EPP写周期的内容,此处不再展开探讨)。在图2所示意波形中,当有正确握手的EPP读周期执行时间约为1.5μs,此时间是字节模式下一次有效EPP访问所需最短时间,在这段时间内,“IN AL,DX”这一条指令占据了约90%以上的访问时间,验证此点仅需临时屏蔽“IN AL,DX”指令,并比较所花费的时间差别即可。1.5μs相当于接近700kBytes/s的数据读速率。如果以“IN EAX,DX”替代“IN AL,DX”指令,可以充分利用EPP模式下硬件将4个8位数自动合并为1个32位数的特性,在一次I/O访问中由硬件自动产生4个DATASTB负脉冲从而实现4个字节的输入。因为一次字节模式的I/O访问所费时大约间需要1.5μs,减少这类指令的执行次数有利于实现更高速的EPP访问过程,经实验发现以4字节方式访问的EPP过程可以在3.2μs内读取一次,即平均每字节需0.8μs,相当于1.2MBytes/s,此实验结果是基于外设可以连续不断的输送数据理想前提,实际上要实现有效的数据传输,可得到的速率要低于该值。     2 WIN98下高速EPP接口的构成     在WIN98环境下,由于非实时多任务的特性,运行于RING3的应用程序频繁被操作系统打断,这决定了靠软件无法实现连续均匀的数据采样,只有在硬件上配置数据缓冲存储器并及时传入微机以免数据缓冲存储器溢出。只要保证一定深度的数据缓冲存储器,且满足数据传输平均速率大于数据采样速率,就能将所采集的数据传入微机的大容量内存,以备处理。在硬件构成方面,为以较低代价获得大容量的FIFO数据缓冲存储器,采取CPLD器件结合512KB的SRAM方式,实现,由CPLD器件完成读写控制的FIFO特性及EPP模式的应答握手信号。接口结构及CPLD内部功能模块见图3所示,数据在CPLD控制下,以2μs 的固定速率存入SRAM环状连续增量地址,因为EPP模式读取速率与数据采样的固定速率是异步的,控制逻辑为保证2μs 的固定采样速率,当采样时间点到达时,不论当前是否处于EPP应答处理期间,优先执行数据采样,因为处理是在系统时钟脉冲驱动下的硬件行为,仅存在固定的传输延时,故两次采样间隔是严格保证的。     EPP模式的读取平均速率必须高于数据采样速率,一旦FIFO数据读空必须让微机正确处理,由前述实验可知,每次字节方式I/O执行时间约为1.5μs,如果通过在EPP的状态口(379H)的保留位输入代表FIFO读空的信号,则每完整读取均要执行两次I/O指令:EPP数据读及EPP状态读,至少需3μs完成读取一个字节,这也是通常方式能达到的最快有效读取速率。当采用双字读读及EPP状态读的方式时,需4.8μs完成4个数据字节读取,但此方式需要处理的一个问题:由于双字方式EPP数据读由硬件自动产生4个EPP数据读周期,当其执行完毕,执行EPP状态读发现FIFO已空,微机软件无法判别在从第几个EPP数据读周期开始FIFO为空,从而影响对数据队列的正确排序,故CPLD逻辑应当在FIFO队列还有至少4个未读数据时必须发出读空信号,微机程序应当在每次EPP开始前执行读取状态口的指令,以决定是否可以开始EPP数据读周期,从上分析可以看出为实现有效的EPP数据读取,平均每字节至少需要1.2μs,即可 以获得最快约800kBytes/s的数据传输速率。因500ksps的数据采集设计速率仅略低于800kBytes/s的数据传输速率,考虑WIN98工作环境,配置大容量的FIFO十分必要,采用大容量SRAM与CPLD器件构成FIFO,具有成本较低的优点,通过使用VHDL的行为描述,经CPLD器件开发软件的编译、综合、仿真、适配、下载,实现所需要的控制逻辑。根据设计,当数据锁存输出的下一个时钟脉冲(即83ns后),WAIT将输出为高电平,EPP在此时读取数据口信号,如果不采用外部缓冲驱动器,数据上升过程将耗时80ns,对EPP数据接收可靠性有不容忽视的影响,为减小电缆电容的影响,数据输出使用了74ALS574芯片作缓冲,其高电平输出能力达15mA,是ispLSI1032高电平输出能力的3.5倍,在电缆电容有100pF时,23ns可达到3.5V的逻辑高电平,保证数据接收可靠性。     仿真波形参见图4,出于方便,仿真时钟设置为12.5MHz。系统每24个时钟脉冲产生一次数据采集,仿真采样速率521ksps。数据由DIN[7:0]输入,通过CPLD内部数据输入触发时钟(该时钟同相缓冲后形成RAMOE脉冲,持续宽度为两个系统时钟)的上升沿锁存,并控制地址选择器将写地址输出到ABUS上,在RAMOE为高期间,DBUS开放三态数据触发器输出使能,使被锁存的8位数据经DBUS输出,数据输入触发时钟过后一个系统时钟,RAMWR产生一个系统时钟宽度的负脉冲,控制SRAM将DBUS上的数据写入,再下一个系统时钟的上升沿,RAMWR变高,RAMOE变低使SRAM输出有效,三态数据触发器恢复为高阻状态,ABUS变为待读数据地址,完成一次数据采集、存储过程。微机软件执行EPP数据读前先读取状态口(379H)以判别READ_EN是否有效,当READ_EN为高时,可以执行EPP数据读周期,CPLD在同步DATASTB_IN的下降沿后,产生一个宽度的OUTCLK输出锁存脉冲,其上升沿将相应待读地址的SRAM数据锁存于外部74ALS574,下降沿使WAIT_OUT上升,形成EPP模式的应答握手信号。WAIT_OUT在DATASTB_IN的上升沿异步复位以响应下一次EPP模式访问。数据写入优先于数据读取,当到达固定的采样间隔点时,CPLD总是推后OUTCLK及WAIT_OUT 的执行,待采样并存储完毕才继续被暂缓的EPP应答,在设计中,数据的采样及存储需要两个系统时钟周期共167ns,远低于EPP的超时参数,故有充分的时间正确地完成EPP握手。图4仿真了数据读空状态,在图中部,READ_EN信号存在一个低电平区域,此负脉冲前,根据RAMWR个数可知当时采样了11个数据,根据OUTCLK个数可知读取了8个数,剩下3个数不足以提供EPP执行双字读的操作,如果此时微机需要访问EPP,在其对状态口的读取中,因得知READ_EN无效而暂缓EPP的执行,当再次完成一次数据采样后,达到至少存在4个未读数据的条件,READ_EN重新变为有效,可供微机读取。     为与微机接口,附加部分其它口线,其中RESET使CPLD全局复位,74ALS574的OE脚由微机控制输出是否为高阻,在程序设定数据端口作为输入使用前,保持该脚为高电平,使74ALS574输出为高阻态,虽然使用的是EPP模式的地址选通信号脚作控制,但程序中并无EPP模式的地址读写指令,此脚的变化直接由EPP端口的控制口(37AH)的D3位控制,另外一般D5位为读写方向控制,将该位置为高,使数据端口作为输入使用。SYN与RAMWR有固定(芯片编程时设定)的相位关系,作为数据采集的同步控制用,当选用MAX114芯片且配置为流水线模式(Pipelined Mode)时,MAX114的WR及RD脚共同连接至SYN脚,此信号波形是与RAMWR同步下降但持续时间为500ns的负脉冲信号,由A/D芯片MAX114与SRAM及CPLD等器件可构成EPP模式下500ksps的连续数据采集接口。     微机的数据接收是个环状循环体后台程序,频繁对端口的访问占据大量CPU时间片,为保证对用户操作的响应,应采取多线程方式的程序结构。微机软件部分采用Delphi程序设计语言,端口访问使用内嵌汇编语言,程序中开辟一块20-100M字节或更大的环型数据区,可根据实际需要考虑。

    智能硬件 模式 500 epp ksps

  • 基于FT245BM的简易USB接口开发

    摘要:FT245BM的主要功能是进行USB和并行I/O口之间的协议转换。详细介绍FT245BM芯片的工作原理、内部结构、引脚分布及功能;给出基于FT245BM接口电路的典型设计及驱动和应用软件的编写方法。     关键词:FT245BM USB接口 并行I/O口 引 言 1 概 述   当前,USB外设的开发是一个热点。由于USB总线具有传输速度快、占用资源少及真正的即插即用等优点,越来越受到业界的青睐。可是,USB的开发要求设计人员对USB的标准、Firmware(固件)编程及驱动程序的编写等有较深入的理解,因此限制了USB的开发人员;而基于FT245BM芯片的USB产品开发,能够使研发人员在最短的周期内开发出相应的USB产品。该芯片由FTDI (Future Technology Devices Intl. Ltd.)公司推出,使用简单、性能卓越,只要熟悉单片机编程及简单的VB、VC应用程序编程,就可很容易地进行用户产品开发。2 FT245BM芯片功能简介   FT245BM的主要功能是进行USB和并行I/O口之间的协议转换。芯片一方面可从主机接收USB数据,并将其转换为并行I/O口的数据流格式发送给外设;另一方面外设可通过并行I/O口将数据转换为USB的数据格式传回主机。中间的转换工作全部由芯片自动完成,开发者无须考虑固件的设计。   FT245BM内部主要由USB收发器、串行接口引擎(SIE)、USB协议引擎和先进先出(FIFO)控制器等构成,如图1所示。USB收发器提供USB1.1/ 2.0的全速物理接口到USB总线,支持UHCI/OHCI主控制器;串行接口引擎主要用于完成USB数据的串/并双向转换,并按照USB1.1规范来完成USB数据流的位填充/位反填充,以及循环冗余校验码(CRC5/CRC16)的产生和检错;USB协议引擎管理来自USB设备控制端口的数据流;FIFO控制器处理外部接口和收发缓冲区间的数据转换。   FIFO控制器实现与单片机(如AT89C51等)的接口,主要通过8根数据线D0~D7及读写控制线(、WR、和)来完成和单片机的数据交互。FT245BM内含两个FIFO数据缓冲区,一个是128字节的接收缓冲区,另一个是384字节的发送缓冲区。它们均用于USB数据与并行I/O口数据的交换缓冲区。   另外,FT245BM还包括1个内置的3.3 V的稳压器,1个6 MHz的振荡器、8倍频的时钟倍频器、USB锁相环和EEPROM接口。FT245BM采用32脚的PQFP封装,体积小巧,易于和外设做到一块板上。其外形及引脚分布如图2所示,各引脚的功能描述如表1所列。表1 FT245BM引脚功能 引脚号 引脚名称 类  型 引脚功能 25 D0 I/O 双向数据总线 24 D1 I/O 双向数据总线 23 D2 I/O 双向数据总线 22 D3 I/O 双向数据总线 21 D4 I/O 双向数据总线 20 D5 I/O 双向数据总线 19 D6 I/O 双向数据总线 18 D7 I/O 双向数据总线 16 RD IN 由低变高时,允许从接收数据缓冲区读取数据 15 WR IN 由高变低时,允许将数据发送到数据缓冲区 14 TXE OUT 为低时,允许数据写入发送数据缓冲区 12 RXF OUT 为低时,允许数据缓冲区的数据被读取 7 USBDP I/O USB数据信号线D+,接1.5kΩ的上位电阻到3.3V 8 USBDM I/O USB数据信号线D- 32 EECS I/O EEPROM片选线 1 EESK OUT EEPROM时钟线 2 EEDATA I/O EEPROM数据线 10 PWREN OUT 电源使能线 11 SI/WU IN 发送立刻消息或唤醒信号线 4 RESET IN 复位脚 5 RSTOUT OUT 内部复位生成器的输出脚 27 XTIN IN 时钟输入脚 28 XTOUT OUT 时钟输出脚 31 TEST IN 测试脚 6 3V3OUT OUT 3.3V输出脚 3、26 VCC PWR 电池,+4.4~5.25V 13 VCCIO PWR 控制引脚10~12、14~16、18~25的信号电平,+3.0~+5.25V 9、17 GND PWR 电源地 30 AVCC PWR 内部模拟电源 29 AGND PWR 内部模拟电源地 3 硬件设计   FT245BM的典型硬件电路如图3所示。该电路采用总线供电模式,同时采用上电复位方式,通过的输出使单片机复位。时钟电路可采用4脚的6 MHz晶振模块或由1个6 MHz的晶体及2个33 pF的电容组成。脚和I/O 24脚相连,用于判断USB总线是处于挂起状态还是正常状态。在USB接口的电源端采用一个磁珠,以减少主机和设备的干扰;同时,电源端增加了去耦和旁路电容,以提高电路的抗干扰性能。在PCB板的设计中,数据线的走线应尽可能短并且长度相等。图3中的93C46(93C56或93C66)是一片EEPROM,用于存储产品的VID、PID、设备序列号及一些说明性文字等。这些需要用户自己编写,编写的应用程序由FTDI提供。用户只须运行相应的VB应用程序,写入自己相应的信息即可。该EEPROM是可选的。若没有EEPROM,FT245BM将使用默认的VID、PID、产品描述符和电源描述符,并且没有设备的序列号。图3 FT245BM的典型硬件电路4 软件编程   当FT245BM的USB接 口连接到主机后,必须在PC机上安装一个由FTDI公司免费提供的虚拟串行口VCP(Virtual COM Port)驱动程序。该驱动程序兼容Windows 98/ 98 SE、Windows 2000/ME/XP等不同版本。用户可以在这虚拟串口上进行应用程序的开发。该虚拟串口可以像一个标准的物理串口那样被访问,可本质上所有针对虚拟串口的数据通信都是通过USB总线完成的,在设备端则通过并行I/O口完成。   在PC端,应用VB对虚拟串口(通常为COM3)进行应用编程。我们直接应用MSComm控件,将MSComm3.CommPort置为3,MSComm3.Seetings置为“9600,n,8,1”(该速率为默认设置,实际上VCP驱动程序总是使数据以最快速率传输);通过MSComm3.PortOpen设置COM3的开关状态;通过MSComm3.Input和MSComm3.Output读入或输出数据。在读取数据时,设置MSComm3.Rthreshold的值为1。只要有数据传到PC机,就立即触发MSComm3.CommEvent事件,自动读取COM3的数据;而发送数据则可自动或手动发送,由用户自己设置。根据这些,用户就可以轻松编写自己的应用程序了。   在设备端,基于万利的Insight SE-52仿真器进行编程。根据图4所示接收数据时序图,首先,须采样到信号为低,若为低,表明有接收到来自PC机的数据,允许单片机通过八位数据总线D0~D7读取数据。接着,通过信号由低到高的变化锁存数据(读入数据)。最后,延迟一段时间,重新开始下一字节的读取。软件流程如图5所示。发送数据过程,可根据图6所示发送数据时序图,同理编写发送数据的程序。设备程序可以在此基础上进一步开发,即用户根据自己的具体项目进行编程。 5 结 论   利用FT245BM进行USB接口的开发,简单、容易,开发周期短,易于为工程实践所采用;同时,也可以直接用于新产品的开发,如数码相机的USB接口、MP3播放器的USB接口及无线Modem的USB接口等。

    智能硬件 USB ft 245 bm

  • 基于USB2.0的MPEG视频卡的设计与实现

     作者Email:  lql0607@163.com     摘  要: 本文介绍了一种基于USB2.0接口的MPEG视频卡的设计方案及其软硬件设计方法。     关键词 :USB; 视频卡; MPEG; WDM     通用串行总线(Universal Serial Bus,即USB)以其方便的即插即用和热插拔特性,以及较高的传输速率,成为PC领域广为应用的外设连接规范。目前,国内外普遍采用的是USB1.1规范,它支持两种传输速率:1.5Mbps和12Mbps,主要应用在低速传输要求的场合。2000年发布的USB2.0规范提供了480Mbs的传输速率,以满足更快的数据传输要求。     为了使MPEG视频卡快速地向PC机传送大量的数据,我们在设计MPEG视频卡与PC机的接口时采用USB2.0技术。对USB的设计与开发,我们是基于CYPRESS公司的EZ-USB FX2系列的CY7C68013芯片及其FX2开发包。     1、 硬件设计     传统的采用PCI接口的MPEG视频卡, 不但占用了有限的PCI插槽,安装不方便,而且不支持热插拔和即插即用。所以,在本设计中,我们选用USB2.0接口芯片对传统的MPEG视频卡进行了改进。     改进后的USB2.0接口的方案如图1所示。         该USB2.0接口的MPEG视频卡的工作原理为:音视频信号经AK4550音频处理芯片及AA7113视频处理芯片进行A/D转换,将模拟信号转换成8bit的PCM格式的数字信号,传入SZ1510音视频压缩采集芯片进行处理,将编码调制PCM格式的数据转化为符合格式MPEG-1的混合影视文件,最后MPEG-1数据经USB接口芯片送给PC机作进一步的处理,如存储、显示等。     设计中,我们选用的USB接口芯片是EZ-USB FX2 系列的CY7C68013芯片。该芯片是针对USB2.0的,而且和USB1.1兼容,它支持两种传输速率:全速(Full_speed)12Mbps和高速(High_speed)480Mbps,它不支持低速(Low_speed)1.5Mbps。该芯片的内部结构如图2所示。     CY7C68013-128AC内部集成了一个增强的8051内核,它既与标准的8051兼容,又有诸多的改进:最高工作频率48MHZ,一个指令周期只需4个时钟周期,比标准的8051平均提高了2.5倍;2个UARTS端口;3个定时/记数器;扩展的中断系统及其更多I/O口等。CY7C68013内部集成的USB2.0的SIE能完成大部分USB2.0协议的处理工作,减少了用户对繁杂的USB协议的处理。另外,用户在开发时,可以利用GPIF和FIFO方式实现与高速外围设备之间的逻辑连接,并进行高速数据的传输。在该改进方案中,我们选用的是GPIF方式,实现和Z1510之间的通信。    2、 软件设计     USB 软件设计包括三方面的工作:固件(Fireware)设计,驱动程序设计和主机端应用程序的设计。     (1) 固件设计     设计中,我们考虑到MPEG视频卡要求快速地持续地传送大量数据,并对数据的完整性要求不太高,我们采用ISO传输方式。另外,我们让CY7C68013工作在GPIF模式下的FIFO Read方式,最多可以传输4G byte(WORDWIDE=0)或word(WORDWIDE=1)。外设的数据由于不需8051的处理,我们采用自动打包的方式(AUTOIN=1),直接从FIFO到SIE,这样有利于提高传输速率。其主要实现代码如下:void  TD_Init( ){ CPUCS = 0X01;       file://CLKSPD[1:0]=10; for 48MHz operation.GpifInit( );   ……SYNCDELAY;EP6CFG = 0XDA;     file://端点配置: 同步IN方式、缓冲大小1024字节SYNCDELAY;FIFORESET = 0X80;    // activate NAK_ALL to avoid race conditionsSYNCDELAY;FIFORESET = 0X06;    file://reset, FIFO 6SYNCDELAY;FIFORESET = 0X00;    file://deactivate NAK_ALL SYNCDELAY;EP6FIFOCFG = 0X0D;   file://wordwide=1SYNCDELAY;……}    (2) 驱动程序设计     在WINDOWS平台下,USB 驱动程序由三部分组成:USB设备驱动程序,USB总线驱动程序和USB主控制器驱动程序,它们必须遵循WIN32驱动程序模型(WDM)。其中,WINDOWS操作系统已经提供了处于驱动程序栈底的USB总线驱动程序和USB主控制器驱动程序。而USB设备驱动程序由设备开发者编写,它通过向USB总线驱动程序发送包含URB(USB  Request Block)的IRP(I/O Request Packet),来实现USB外设之间的信息交换。当主机应用程序要对USB设备进行I/O操作时,它调用Windows API函数对Win32子系统进行Win32调用,由I/O管理器将此请求构造成一个合适的IRP,并把它传递给USB设备驱动程序。USB设备驱动程序接受到这个IRP后,根据IRP中包含的具体操作代码,构造响应的URB并把它放到一个新IRP中,然后把此IRP传递到USB总线驱动程序,USB总线驱动程序根据IRP中所包含的URB执行响应的操作,并把操作结果通过IRP返还给USB设备驱动程序。USB设备驱动程序接受到此IRP后,将操作结果通过IRP返还I/O管理器。最后,I/O管理器将此IRP中操作结果返还给应用程序,至此应用程序对USB设备的一次I/O操作完成。     开发USB设备驱动程序,可采用Numega公司的开发包Driver Works和 Microsoft公司的2000DDK,并以VC++6.0作为辅助开发环境。Driver Works提供的驱动向导,,可根据用户的需要,自动生成代码框架。减少了开发的难度,缩短了开发的周期。     在CYPRESS公司的EZ-USB FX2开发包中,有一个通用的驱动程序,该程序可不加修改经DDK编译后直接使用。在本设计中,由于时间关系,我们采用的就是这个通用驱动程序(GPD)。     (3) 应用程序设计     USB主机应用程序是计算机中完成特定功能的程序,其关键是实现从USB 外设读取或发送特定数量的数据,USB标准设备请求和特定的命令等。另外,可以对数据做进一步的处理,如:存储、显示、快速傅立叶变换等。在WINDOWS 2000下,我们所使用的应用程序开发工具是VC++6.0。     3、 结束语     该卡是对传统的PCI接口的MPEG视频卡的改进,它支持热插拔和即插即用。由于采用USB2.0接口,其传输速率也高于后者,满足了数据高速传输的要求,解决了USB1.1存在的传输瓶颈。相信随着各大电脑主板商对USB2.0的支持,USB2.0必将在PC机应用的各个领域得到广泛的应用。

    智能硬件 USB 视频 2.0 mpeg

  • 应用McBSP实现I2C总线控制器

      作者Email: dick_ligg@sohu.com     摘 要:提出了在TMS320C6000系列DSP上应用McBSP实现I2C总线接口协议的方法,使DSP可以接入其他需要I2C总线配置的智能器件,系统结构简单,硬件设计容易,资源消耗小。     关键字:I2C总线  GPIO  McBSP  DSP     1 引 言     TI公司的TMS320C6000[1,2]系列是高性能的DSP,可广泛的用于XDSL、无线基站、数字图像处理等方面。在进行数字图像处理时,通常需要视频解码器诸如SAA7111A之类的模拟视频前端,而大多数的视频解码器进行初始化通常是通过两线的I2C总线接口,但是现在的DSP和MCU大部分都没有I2C总线接口,在这种情况下我们可以应用两个通用的IO线,通过软件的方法来模拟I2C总线的协议,继而完成I2C总线的接口。在TMS320C6000中通常都有两个或两个以上的多通道缓冲串行接口McBSP,McBSP不仅可以配制成串行接口还可以独立的配制成通用的输入(GPI)、输出(GPO)和输入输出端口(GPIO)。     I2C[3]串行总线是用双向数据线(SDA)和串行时钟线(SCL)两根信号线,在连接到该总线的器件之间传送信息。总线上的每个器件均可设置一个唯一地址,然后根据所设的功能进行信息的发送或接收。除了作为发送器和接收器以外,在执行数据传输时,总线的器件还可以设定为主控器和受控器。通常由主控器启动总线上的数据传输,并产生数据传输所需的时钟信号。而被其寻址的其它器件均为受控器,这意味着总线上可连接多个有控制总线的器件。     I2C总线上的数据传输率为100kbit/s,快速方式下可达400kbit/s。连接到总线上的器件数仅受400pF的总线电容的限制。同时,为了避免总线信号的混乱,要求连接到总线上的各器件输出端必须是集电极开路或漏极开路,以便产生“线与”功能。I2C总线上的SDA和SCL线都是双向传输线,它们可通过一个电阻连接到正电源端,当总线处于空闲状态时,两条线均为高电平。     2 硬件设计     I2C总线的硬件设计非常方便,只需要将SDA 和SCL连接即可,在I2C总线上只允许有一个主控器,其余的都是受控器。当节点的个数大于了400pF的限制时,可以通过总线驱动器如82B715来进行总线扩展。连接见图1     3 软件设计     3.1 McBSP的配置     I2C总线应用McBSP的两个管脚,首先禁用McBSP功能以便将McBSP的管脚配制成GPI、GPO、GPIO。本文应用McBSP0的CLKX0作为I2C总线的SCL,FSX0作为I2C总线的SDA,McBSP的DX,DR,通常不能配置成I2C的SDA,因为SDA是双向的,而DX,DR只能配制成单一的输入或输出。     配置代码如下: McBSP0_SPCR=0x00000000;//McBSP0 发送和接收复位McBSP0_PCR=0x00003F00;// McBSP0的所有的管脚都配置为GPIO,CLKX0和FSX0为输出对于主机来说SCL总是输出,所以它的方向是保持不变的,SCL应该输出0,1作为接口的时钟,为了实现此功能我们定义一个宏(MACROS):SET_SCLHI( ) SET_SCLLO( )#define Set_SCLHi( ) McBSP0_SPSA = PCR; McBSP0_SPSA |= 0x00000002#define Set_SCLLo( ) McBSP0_SPSA = PCR; McBSP0_SPSA &= 0XfffffffdI2C总线的数据线SDA当写的时候是输入,读的时候是输出。为了改变SDA的方向可以定义Set_SDADirOut( ) Set_SDADirIn( )#define Set_SDADirOut( ) McBSP0_SPSA = PCR; McBSP0_SPSA | = 0x00000800#define Set_SDADirIn( ) McBSP0_SPSA = PCR; McBSP0_SPSA &= 0xFFFFF7FFSDA应该依照数据位的0,1来变化,为了输出1,0定义Set_SDAHi( ) Set_SDALo( )#define Set_SDAHi( ) McBSP0_SPSA = PCR; McBSP0_SPSA |= 0x00000008#define Set_SDALo( ) McBSP0_SPSA = PCR; McBSP0_SPSA &= 0xFFFFFFF7定义好之后可以模拟I2C总线的协议进行传送,例如在SAA7111A上的I2C总线接口是用来对SAA7111A进行初始化用的,SCL的频率可以从0到400KHZ,为了控制SCL的频率可以应用DSP的TIMER0来控制。当CPU为100MHZ时:TCR = 0x00000010; // 停止 TIMER0 and TDDR=0PRD = 6249; // TIMER0 rate = CPU-Frequency/(PDR+1) = 100MHz/6250 = 16kHz...TCR &= 0xFFFFFFEF; // 开始 TIMER0     3.2 I2C总线协议编程     3.2.1  I2C总线协议读写数据流的编程     为了进行I2C总线的通讯,我们选用每位数据流4帧(FRAMES),以便延迟和噪声干扰最小,4帧每位的数据流保证了SDA不会变化在SCL的边沿处,仅仅允许数据变化在FRAME0,读仅在FRAME2。如图2所示 I2C总线的写程序如下 void I2CWrite(unsigned int WriteBit){Set_SDADirOut( ); // 设置SDA为输出switch(FrameCount){case(0): // 起始帧Set_SCLLo( ); // SCL 为 0if (WriteBit == 0) // SDA = WriteBitSet_SDALo( );elseSet_SDAHi( );break;case(3): // 第4帧Set_SCLLo( ); // break;default: // 在第2,3帧Set_SCLHi( ); // SCL 为 1}FrameCount += 1; // 帧计数if (FrameCount > 3){ FrameCount = 0; BitIndex = (BitIndex >> 1); } // 准备下一个发送位}I2C总线的读程序与写程序很类似,只需要改变SDA为输入即可。     3.2.2 I2C总线的开始位和停止位的编程     I2C总线的开始位和停止位有3帧产生,在I2C总线传输过程中,仅当总线空闲(SCL线和SDA线均为高电平)时,数据传送才能开始,此时总线上的任何器件均可以控制总线。其中当SCL线为高电平且SDA线由高变低时为开始条件;而当SCL线为高电平且SDA线由低变高时为结束条件。如图3所示 开始位:void I2CSTA ( ){ // I2C 开始位Set_SDADirOut ( );//定义SDA为输出 switch ( FrameCount ){case (1): // 第2帧Set_SCLHi ( );Set_SDALo( );break;case (2): // 第三帧Set_SCLLo ( );Set_SDALo( );break;default: // 第一帧Set_SCLHi ( );Set_SDAHi ( );}FrameCount += 1; // 帧计数if ( FrameCount > 2 ){FrameCount = 0;BitIndex = 0x0080; } // 定义的低8位}停止位的编程方法只需要按照上面所说的将SCL线为高电平且SDA线由低变高即可。3.2.3 I2C总线的数据格式 起始位 受控器件地址 读写控制位0/1 应答位 数据 应答位 … 停止位     I2C总线数据传输格式[3]如图4。其中第一部分为数据传输起始信号,即由此开始进行数据传送;第二部分为受控器地址,用来选择向哪个受控器传送数据;第三部分为读/写控制位,用于指示受控器的工作方式,0表示写,1表示读;第四部分是被主控器选中的受控器向主控器回传的确认信号;第五部分是所传送的数据,每传送一个字节数据,都要求有一个应答位;第六部分是数据传输的结束信号。每个具有I2C总线接口的受控器件都有唯一固定的地址,当主控器发送数据时,I2C总线上挂接的受控器件都会将主控器发出的、位于起始信号后的8位地址信息与自己的地址进行比较,如果两者相同,则认为该受控器件被选中,然后按照读/写位规定的工作方式接收或发送数据。可以应用上面的程序来按照I2C总线的数据格式进行数据传送。     4 结论     应用DSP的McBSP来设计I2C总线接口,硬件接口简单,调试方便,并且可以节省硬件的花费,此方法已经应用在基于DSP的图像匹配机中,方法可行,并运行可靠。

    智能硬件 i2c 总线控制器 mcbsp

  • 采用VXD技术实现实的通信

     摘要:讨论Windows虚拟设备驱动(VXD)技术,并采用此项技术示范性地做出应用于PC串口实时通信的虚拟驱动程序,找到一种可以在PC中实现实时通信的途径。     关键词:VXD 实时 串口通信 引言 在微软的视窗操作系统中,系统内核掌管所有的应用程序,通过独特的任务调度算法实现CPU的分时多任务处理方式。多任务处理对大多数用户可能是件好事,但是对那些想把实时通信建立在Windows操作系统上的特殊用户来说,操作界面的图形化并不比MS-DOS的单任务更具吸引力。在视窗操作系统里可以进行实时通信和控制码?答案是:VXD技术可以帮我们在获取友好的人机界面的同时还拥有很强的实时性。 1 VXD技术解析 VXD技术可追溯到Windows3.1,它的引入就是要让操作系统实现多工以及硬件资源的共享。为了支持多个MS-DOS任务同时执行,Windows98让每个MS-DOS应用程序在各自的虚拟机(VM)上运行,各自互不相干;而所有的Widnows应用程序却都在一个虚拟机上运行。图1所示的结构框图很好地说明了Windows98的整体架构。 图1中,由众多的VXD组成系统级代码处于最底层。其中,处于中心地位的是一名为VMM32的VXD,它负责协调和管理所有的VXDs。其它VXDs则通过消息机制(这个消息机制由VMM32.VXD来维护)彼此联系。由所有VXDs开放出的服务接口(API)组成了一个服务网,它们彼此通过合作的方式,提供Windows98的系统底层驱动服务。 从以上Windows98系统架构可以看出,要想在视窗平台下获取很强的实时性,仅靠提升应用程序线程优先级的方法是不够的。因为Win32应用程序代码属于Ring3级,而VXD代码则属于Ring0级;采用VXD撰写的实时通信程序可以完全不受代码限制,可以直接对硬件进行操作。VXD的这个特点正是实时通信建立所必须的。 设计实时通信的VXD前,先解释以下几个问题: ①VMM32使用VPICD.VXD虚拟化每个硬件和软件中断。VMM32为每个虚拟机(VM)维护一个IDT结构,当中断发生时,CPU先保护中断现场,然后经由当前VM的IDT把这个中断引导至相应的中断处理程式。 中断的虚拟化,使我们有机会给每个中断提供新的中断处理函数,并可以让多个硬件共享同一个中断号。VPICD.VXD为我们提供这些服务。 ②VMM有两个调度器,用以在多个线程和VMs之间实现抢占式多工。主调度器负责选定下一个将被执行的线程。这个选择可以是一个,也可以是多个。然后,主调度器把选择结果送给所谓的时间片调度器,并由后者完成各个应用程序间的时间片分配。调度器也时应用程序经由呼叫Win32线程优先调整API(如SetThreadPriority和SetPriorityClass等)做出回应。当中断发生时,VMM32自动提升中断处理函数所在VM之优先级,保证中断处理函数能及时被执行。 ③VXD和Win32应用程序可直接通信。Win32应用程序可通过一个系统API(DevicelOControl(…))来呼叫位于底层的VXD为其服务。在呼叫VXD前,首先必须调用CreatFile(…)这个API加载该VXD(如果该VXD是一个静态VXD,则不用加载)。所有的呼叫动作其实都通过VMM32完成。VXD也可以通过消息方式和位于上层的Win32应用程序通信。She11.VXD为所有希望以消息机制和Win32应用程序通信的VXD提供了这一服务。 以上是编写一个串口通信驱动需要的系统层面知识。对于Windows底层的了解。 2 用VXD实现一个实时串口通信驱动 接下来用VXD技术实现一个实时串行通信的驱动。这个VXD是一个动态(Dynamic)VXD,当它的服务被呼叫时,VMM32会动态加载这个VXD。作者采用的工具是C+98DDK。当然也可以使用其它的工具,如MASM6.11(或更高版本)、VtoolsD。用C搭配DDK完成VXD构建的好处是,可以使用C语言完成绝大部分的程序,程序比较容易阅读和维护。 用C来实现一个VXD驱动,需要准备如下条件:一个.ASM的汇编语言接口文件(在其中定义VXD要处理的系统消息和输出API),一个.C的函数实现文件(在其中完成自己函数实体),一个.DEF的定义文件(在其中定义VXD中各个段的别名并汇成一个DDB)和一个.MAK档(用来编译并连接生成VXD,可有可无)。在这里,仅给出用C实现的函数档。至于其它的文件,可以从本文所列的参考书目或其它文献中找到相关文档的说明。 这个串口通信驱动程序的功能是:实时送出一个Byte的数据,实时接收一个Byte的数据。作为演示之用,并没有加入其它代码。该VXD驱动主要由如下3个系统消息(由VMM32来维护和管理)处理函数组成,其代码如下: (1)OnSysDynamicDeviceInit()函数 BOOL OnSysDynamicDeviceInit() { //OnSysDynamicDeviceInit irqhandle=VPICD_Virtualize_IRQ((DWORD)(&irq4)); if(irqhandle= =0){ return FALSE; } return TRUE; //OnSysDynamicDeviceInit } 该函数用来完成VXD初始化所做的工作。在本例中,由于实时监视串口中断的需要,要给COM1的中断安装一个自定义的断服务函数。98DDK已经提供了这个函数的C语言版,其原型是HIRQ static VPICD_Virtualize_IRQ(PVID pvid),在vpicd.h中。该函数需要一个指针作为参数(指向名为VPICD_IRQ_Descriptor的结构体),函数传回一个指向该虚拟IRQ的句柄(该句柄在后来的VPICD服务中需要提供)。VPICD_IRQ_Descriptor结构体的组成为: typedef struct VPICD_IRQ_Descriptor{ USHORT VID_IRQ_Number; //IRQ号(0~15) USHORT VID_Options; //标志位选项 ULONG VID_Hw_Int_Proc; //硬件中断服务程序的地址 ULONG VID_Virt_Int_Proc; //虚拟中断服务程序 ULONG VID_Mask_Change_Proc //Mask Change调用例程 ULONG VID_IRET_Proc; //IRET调用例程 ULONG VID_IRET_Time_Out; //在Vm的进程优先级提升之前的最大等待时间 ULONG VID_Hw_Int_Ref; //硬件中断服务程序的数据存放地址 }VID; 其中只用到三位。在本例中需要声明一个名为irq4的全局变量为VID结构,并付给如下初值:VID irq4={4,0,hwproc,0,0,0,0,500,0},表示将要虚拟化IRQ4,改变其中断处理函数为void hwproc(void),该函数的原型如下: void hwproc(void){ _asm{ mov dx,0x3f8 in al,dx mov byte ptr [readin],al clc } return; } 在这个中断处理中,仅仅从COM1的数据寄存器(地址为3F8h)中读取接收到的数值,并把该数值存放在一个类型为BYTE、名为readin的内存中。 (2)OnSysDynamicDeviceExit()函数 BOOL OnSysDynamicDeviceExit() { VPICD_Force_Default_Behavior(irqhandle); //解除IRQ4虚拟化 return TRUE; } //OnSysDynamicDeviceExit 该数提供了用于善后处理VXD在卸载时需要完成的事件。在本例中,和VXD初始化对应,需要解除对COM1的中断IRQ4的虚拟化。作者也是用98DDK在vpicd.h中提供的外包函数void static_inline VPICD_Force_Default_Behavior(HIRQ hirp)。该函数唯一需要的参数便是使用VPICD_Virtualize_IRQ函数传回的IRQ句柄。 (3)OnDeviceIoControl()函数 DWORD OnDeviceIoControl(PDIOCPARAMETERS p){ Switch (p->dwIoControlCode) { case 1: //端口写功能 if(!p->lpvOutBuffer||p->cbOutBuffer<1) { //输出缓存的有效性检查 return ERROR_INVALID_PARAMETER; } if(serial_out((DWORD)(p->lpvInBuffer))) { //数据发送 *(BYTE*)(p->lpvOutBuffer)=*(BYTE*)(p->lpvInBuffer); } else{ *(BYTE*)(p->lpvOutBuffer)=0; } open_int(); //打开com1中断 return 0; case 2: //端口读功能 if(*(BYTE*)reading= =0x00) { //数据读入 *(BYTE*)(p->lpvOutBuffer)=0x00; return 0; } *(BTYE*)(p->lpvOutBuffer)=*(BYTE*)(readin); return 0; } return 0; } return 0; } OnDeviceIoControl函数用来处理Win32应用程序对VXD的呼叫。Win32应用程序的呼叫会让VMM32送给该VXD一个系统信息,并传递进一个DIOCPARAMETERS结构的指针。该结构里包含Win32应用程序呼叫时传递进来的各个参数。这个结构的组成如下: Typedef stunct DIOCParams{ DWORD Internall; //指向客户寄存器的指针 DWORD VMHande; //该VM的句柄 DWORD Internal2; //指向DDB结构的指针 DWORD dwIoConrolCode; //DeviceIoControl例程中呼叫的控制码 DWOD lpvInBuffer; //DeviceIoControl例程呼叫所传递进来的输入缓冲区地址 DWORD cbInBuffer; //输入缓冲区的大小 DWORD lpvOutBuffer; //DeviceIoControl例程呼叫所传递进来的输出缓冲区地址 DWORD cbOutBuffer; //输出缓冲区的大小 DWORD lpcbBytesReturned; //拷贝到输出缓冲区中的字节数(可以为NULL) DWORD lpOverlapped; //DeviceIoControl例程呼叫所传递进来的重叠I/O块结构 DWORD hDevice; //Ring3层呼叫应用程序句柄 DWORD tagProcess; //例程标签 } DIOPARAMETERS; 其中,dwIoControlCode指明了Win32应用程序需要VXD提供的哪一项服务。在本例中采用一个switch-case语句作为服务入口,如下所示。其中服务1为让串口送出一个字节,服务2为读取一个已经由串口接收的字节。函数open_int()是用来初始化串口以便接收字节数据;函数BOOL serial_out(DWORD pBuffer)是让串口发出一个字节。它们的函数体分别如下: BOOL serial_out(DWORD pBuffer){ if(pBuffer= =NULL){ return FALSE; } _asm { pushfd cli push eax push edx mov dx,0x3fb ;设置COM1的波特率 mov al,0x83 out dx,al mov dx,0x3f8 mov al,12 out dx,al mov dx,0x3f9 mov al,0 out dx,al mov dx,0x3fb ;设置COM1的线控项 mov al,3 out dx,al mov dx,0x3f9 ;CMM1关中断 mov al,0 out dx,al mov dx,0x3fa ;关闭com1的FIFO功能 mov al,0 out dx,al mov dx,0x3f8 ;字节发送 mov al,byte ptr [pBuffer] out dx,al pop edx pop eax popfd sti } return TRUE; } serial_out这个函数体的实现是用汇编语言实现的。因为涉及到很多的端口提供以及CPU的标志(flag)和压栈操作,因此考虑到用汇编语言编写会简化代码。因为此串口传输中,用到了关闭中断的指令(cli),所以,当写操作所要求完成的任务很多时,此关中断指令会让程序的实时性很好地体现出来,但cli指令有效时间过长会导致系统问题,所以还是要谨慎使用。 Void open_int(void){ _asm{ mov dx,0x3f9 ;COM1开中断 mov al,0x05 out dx,al } return; } open_int函数用来把PC串口的中断设备按照需要设立起来。函数体很简单,仅改变了地址为3F9h的内容,意为设置Rx data ready和Line status中断位,以便让CPU可以及时在COM1的中断服务程序里读取串口接收到的字节。 以上涉及到串口输入和输出的函数体实现代码中,用到了PC16550 UART的资料。 至此,一个可用于实时串口通信的VXD驱动程序已经完成。由于篇幅所限,不能将其它必要的文档一同提出来讨论。 3 Win32客户测试程序 有了上述VXD驱动程序,还需要搭配一个Win32客户程序来进行测试。在网络补充版(http://www.dpj.com.cn)中,给出一个笔者在VC6下编制的一个控制台应用程序片断,以供参考。 现在编制VXD驱动还没有一个集成开发环境(IDE)。本文的驱动程序是用VC6.0自带的编译器编译的。由于要编译汇编文档,所以还需要把一个MASM汇编器(要求6.0以上版本)及其相关文档拷贝到VC6.0的vc98u30446目录下。 4 结论 通过以上对VXD技术的简要分析以及一个用VXD实现的通信驱动可以看出,在Windows操作系统中,采用VXD技术,可以很好地克服由多工带来的时延问题,很好地解决了在Windows平台下实时通信的问题。

    智能硬件 通信 技术实现 vxd

  • MicroWindows体系结构及应用程序接口

     摘要:MicroWindows是一个著名的开放源码的嵌入式GUI软件。本文简要论述了MicroWindows的体系结构和应用程序接口,并介绍其设备驱动特性、API、客户机/服务器模型和画图机制。     关键词:MicroWindows API Nano-X 图形用户界面 许多开发者在嵌入式设计中开始使用类似于桌面的操作系统。其中一个方案就是Linux操作系统。由于Linux在嵌入式系统上具有桌面电脑的全部功能和特性,作为一种免费的开放源码,它允许修改和根据用户的要求进行定制。 MicroWindows是一个开放源码的嵌入式GUI软件,目的是把图形视窗环境引入到运行Linux的小型设备和平台上。作为X Window系统的替代品,MicroWindows可以用更少的RAM和文件存储空间(100KB~600KB)提供相似的功能,允许设计得轻松加入各种显示设备、鼠标、触摸屏和键盘等;可移植性非常好,可用C语言实现;支持Intel 16位/32位CPU、MIPS R4000以及基于ARM内核的处理器芯片。 1 体系结构 1.1 分层结构设计 MicroWindows采用分层结构设计方法,在底层提供对屏幕、鼠标、触摸屏和键盘的驱动,在程序能访问实际的硬件设备和其它用户定制设备。在中间层有一个可移植图形引擎,提供绘制线程、区域填充、绘制多边形、裁减和使用颜色模式的方法。在顶层实现多种API以适应不同的应用环境。目前,MicroWindows中使用两种流行的图形编程接口:Microsoft Windows Win32/WinCE图形显示接口(GDI)和Xlib接口。前者应用于所有的Windows CE和Win32应用程序;后者就像Nano-X,应用于所有Linux X插件集的最底层,这样可让Linux图形程序员X接口开发图形应用程序。 1.2 驱动设备 device.h文件中定义设备驱动接口。MicroWindows已实现至少将一个屏幕、鼠标和键盘的驱动与系统相连。独立图形设备引擎的中间层可以使驱动设备直接完成对硬件的具体操作。 (1)屏幕驱动 MicroWindows可运行在支持Framebuffer的32位Linux系统上,也可使用SVGALib[45]库来进行图形显示。此外,还被移植到16位的ELKS和实模式的MSDOS上,实现1、2、4、8、16和32位的像素支持,以及实现VGA16平面模式支持。它的图形引擎能够运行在任何支持readpixel、writepixel、drawhorzline、drawvertline和setpalette的系统之上。如果底层驱动系统实现了Blitting,则上层可提供更多的增强功能。在底层函数的支持之下,上层实现了对位图、字体、光标以及颜色的支持。除了基于调色板的1、2、4和8位像素模式,也实现15、16和32位像素的真彩模式。 (2)鼠标驱动 MicroWindows有三个鼠标驱动程序。GPM驱动程序mou_gpm.c支持Linux系统,串口鼠标驱动程序mou_ser.c支持Linux和ELKS系统,int33驱动程序mou_dos.c支持MSDOS系统。鼠标驱动程序的基本功能,是将鼠标中的数据编码,然后返回关于鼠标位置和按键的相对或绝对数据。 在Linux下,MicroWindows的主循环是select()声明,如果运行的系统不支持select(),MicroWindows则提供Poll()入口。 (3)键盘驱动 MicroWindows提供两个键盘驱动程序:Kbd_tty.c适用于Linux和ELKS系统,键盘被当成文件描述符来读写;Kbd_bios.c用于MSDOS真彩模式下,它是对PC BIOS进行读写来对按键进行操作。 1.3 MicroGUI——独立图形设备引擎 MicroWindows的MicroGUI提供了对屏幕、鼠标、键盘驱动程序和硬件之间的接口。用户应用程序不能直接调用核心图形引擎,但是可通过API函数来实现。核心程序在客户机/服务器模型下常驻在服务器上,使用内部的文本字体和位图文本模式。此外,核心程序使用的是指针,这样不用靠转变成句柄来实现更多的复杂功能。 MicroWindows中的核心程序以GdXXX()开头,与之相连的是图形输出系统而不是窗口管理系统。此外,还控制所有的裁剪和颜色转换功能。以下是组成MicroWindows核心模块的文件: dvdraw.c——核心图形程序,关于绘制线段、圆、多边形及其填充,文本和位图文件的绘制和颜色转换; devclip.c——核心裁剪程序; devrgn.c——动态分配程序; devmouse.c——鼠标控制程序; devkbd.c——核心键盘控制程序; devpalX.c——连接到系统调色板。 1.4 应用程序接口 MicroWindows提供两个应用程序接口:MicroWindows API(源代码在win*.c中)和Nano_XAPI(源代码在nanox*.c中) 在MicroWidows上的API函数的基本模型都是用来初始化屏幕、键盘和鼠标的驱动程序,然后一直等待select()消息循环。当事件发生时,这条信息将送到用户程序。如果是用户请求图形操作,那参数将被编码后送到适当的GdXXX核心程序上。与原始图形操作相对的窗口概念是被该层所控制的,也就是说该层的API函数定义了窗口及其对应系统的概念。这样,系统坐标就能被转成屏幕上显示的坐标,并且可将数据传给GdXXX核心程序,由其作实际操作。该层亦定义图形/显示文件,并且会将此信息包括裁减信息送到核心程序上。 MicroWindows API支持大多数图形绘制、裁减、窗口工具条绘制以及拖拉窗口等这些程序。Nano_x API以mini-X服务器基础,类似于X的一个API,沿用X Window中的Xlib API,命名都是GrXXX()而不是X Windows中的X)。Nano-x API加入了基于网络的客户机/服务器功能,但是没有实现窗口管理,所以对窗口的处理需要使用系统提供的一个插件(widget)集,或者完全由应用程序员自已开发。 2 图形引擎特性与实现 图形引擎层的功能是完成图形在实虚屏之间的转换,以Gd...为开头,并将指针传给PSD作为它的首个参数。PSD参数将指定底层的显示模式,例如设备的垂直和水平尺寸、硬件使用的颜色模式。另外,真正执行画图的程序在这一层中作为功能指针使用。所有屏幕坐标都是COORD类型。 颜色在图形引擎中被指定RGB CILORVAL模式,然后被转换成颜色指针,以PIXELVAL模式传给显示硬件,在32bpp(bit per pixel)真彩显示器环境下不必转换。 (1)区域 区域用来描述屏幕上像素点的分布。在MicroWindows中,区域是用一些无交迭的矩形组成的数组来描述的。目前实现区域有两种方法,最初是用一个静态数组CLIPRECTs来描述复杂区域。在这个数组中任一矩形中的点都被认为是存在这个区域中的,另一个全局变量clipcount用来给这个数组中的矩形计数。这个方法没有给区域管理提供入口点,所以整个数组的数据直接被送到负责裁剪功能的函数数口。新方法则可以创建任何数目的区域。用来描述区域的数组CLIPREGION被定义成动态数据组,可动态分配它所包含矩形的数量,这样那些无交迭的矩形被存放在“y-x”类型的队列中。在同一队列中,所有矩形的垂直高度y是一样的,这意味着在每个队列中只有矩形的宽度可变。实际程序是利用Intersection、Union、Subtraction、Exclusive OR等方法来实现创建、删除一个区域或者是将几个区域或矩形合并。以下是这种方法设计的几个函数。 GdAllocRegion 创建一个区域 GdDestroyRegion 删除一个区域 GdCopyRegion 复制区域 GdUnionRectWithRegion 将一个矩形和一个区域合并 GdIntersectRegion 在两个区域的交集处创建一个新区域 GdSubtractRegion 在两个区域的差集处创建一个新区域 GdUnionRegion 在两个区域的并集创建一个新区域 GdXorRegion (2)裁剪 图形引擎中有一个由图形操作定义的由一些矩形组成的裁剪区,如果点被包含在这些裁减区内就会被绘制出来。有两个裁剪算法:devclipl.c针对静态矩形数组,devclipc2.c针对新的动态数组。GdSetClipRects是唯一删除区域并指定后来的图形操作的入口点。所有的绘图程序都要调用两个附加程序来决定是否画图。GdClipPoint获取屏幕坐标的(x,y)点,如果该点被绘制出来的话,则返回TRUE。GdClipArea获取屏幕上方最左的或者下方最右的点并回以下值:CLIP_VISIBLE(指定区域在原区域内)、CLIP_INVISIBLE(指定区域不在原区域内)、CLIP_PARTIAL(指定区域部分在原区域内)。 (3)画线 MicroWindows使用GdPoint画点,GdLine画线。画线时使用当前的前景色(DgSetForeground指定)。有两种绘制模式:MODE_SET和MODE_COR。 (4)矩形、圆和椭圆以及多边形 矩形、圆和椭圆的绘制分别调用GdRect和GdEllipse来实现。MicroWindows中定义了一个包含(x,y)多边形顶点的数组来表示多边形,调用GdLine函数画线,把这些点相连就可以实现画多边形。绘制时使用前景色。 (5)区域填充 MicroWindows中使用GdFillRect函数填充矩形区域,填充使用前景色。填充圆和椭圆使用GdFillEillpse函数,填充多边形使用GdFillPoly函数。填充的实现是在屏幕驱动中不断地调用GrawHorzLine函数。 (6)字体和文本输出 MicroWindows支持可变/不可变字体。文本输出时使用GdSetFont定义输出使用的字体,再调用GdText函数输出。 (7)颜色模式和调色板 MicroWindows支持RGB颜色,颜色匹配,真彩和调色板显示,3D效果的显示。 (8)图片绘制 MicroWindows支持两种格式的图片。单色图片用IMAGEBITS结构(1表示前景色,0表示背景色)来定义,绘制时调用GdBitmap程序。彩色图片可以分别定义为1、4、8 bpp的模式,用IMAGEHDR结构来表示。绘制时调用GdDrawImage函数。 (9)映射 映射功能在实虚屏的转换中使用。GdBlit可以实现上层的API将虚拟内存存复制到显示屏上,复制时调用GdBlit函数。 3 MicroWindows API MicroWindows API中的基本通信机制是消息机制。一个消息机制中包含了message number和两个参数:wParam、lParam。Message被存放在应用程序的message-queue中,GetMessage函数将其取出。WM_GHAR针对键盘输入,WM_LBUTTONDOWN针对鼠标键被按下。窗口创建时使用WMCREATE,删除时使用WM_DESTROY。DispatchMessage将消息传到处理程序的窗口。 以下是处理消息的有关函数: SendMessage 将消息传到窗口 PostMessage 将消息传到消息队列 PostQuitMessage 传递WM_QUIT消息到消息队列读时中断程序 GetMessage 得到消息后结束中断 TranslateMessage 将按键按下/弹起的消息传到WMCAR DispatchMessage 将消息传到为它分配的窗口程序 3.2 窗口的创建和删除 RegisterClass 定义新的窗口类型并启动窗口程序 UnRegisterClass 删除窗口类型 CreateWindowsEx 按窗口类型创建一个窗口 DeatroyWindow 删除一个窗口 窗口创建后产生WM_CREATE消息,删除产生WM_DESTROY消息。 3.3 窗口的显示、隐藏和移动 ShowWindow函数指定窗口是否可见。MoveWindow改变窗口的位置和大小。窗口位置改变时,产生WM_MOVE消息;窗口大小改变时,产生WM_SIZE消息。 3.4 窗口的绘制 窗口绘制时产生WM_PAINT消息。窗口的标题栏自动绘制,设置属性使用SetWinowText,察看属性使用GetWindowText。 (1)实虚屏切换 窗口绘制使用的坐标系统是屏幕上的绝对坐标系,MicroWindows API使用的是相对坐标系。GetClientRect和GetWindowRect函数各自返回虚屏和实屏的坐标值。 (2)Device Contexts 调用图形API之间要包含device context。它指定系统所使用的窗口和坐标系,同时还定义系统默认的前景色和背景色。 GetDC用来包含device context。在画标题栏还需调用GetWindowDC。GetDCEx定义子/兄弟窗口的裁剪操作。绘制结束时调用ReleaseDC释放DC。 (3)图形API 见网络补充版(http://www.dpj.com.cn) 3.5 其它实用函数 WndSetDesktopWallpaper 设置桌面的背景图片 WndSetCursor 为窗口创建光标 WndRaiseWindow 拉伸窗口 WndLowerWindow 缩小窗口 WndGetTopWindow 返回最上层窗口的句柄 Sleep 睡眠 (1)设置窗口中心 WM_SETFOCUS和WMKILLFOCUS分别用于获取/删除中心。GetActiveWindow返回ancestor窗口,GetDesktopWINDOW返回当前桌面窗口的句柄。 (2)鼠标捕获 WM_MOUSEMOVE用来表示鼠标被移动。SetCapture获取全部的鼠标移动信息,ReleaseCapture返回到程序,GetCaptrue返回到捕获区域。 (3)区域管理 SetRect 定义一个矩形结构 SetRectEmpty 定义一个空矩形 CopyRect 复制一个矩形 IsRectEmpty 为空矩形时返回TRUE InflateRect 放大矩形 OffsetRect 移动矩形 PtInRect 判断点是否在矩形区内 4 Nano-X API (1)Client/Server模型 Nano-X允许应用程序使用Client/Server网络协议或本地UNIX Domain Socket,可让几个应用程序运行在嵌入式设备或远端主机上,并连接到Server上显示出来。 (2)窗口的创建和删除 Nan0-X中使用GrNewWindow创建窗口。GrNewInputWindow定义窗口只允许用来输入。函数定义了窗口的边界和颜色。 (3)窗口的显示、隐藏和移动 GrMapWindow用来显示窗口,GrUnmapWindow用来隐藏,GrRaiseWindow用来拉伸,GrLowerWindow用来缩小,GrMoveWindow用来移动,GrResizeWindow用来改变窗口大小。 (4)窗口中的绘制 ①Graphics Context。GrNewGC用来分配graphics Context,删除时使用GrDestroyGC,GrCopyGC用来复制。创建一个Graphics Context后,服务器返回一个Graphics Context的ID,用来作为API的参数。GC中不存放裁剪区和系统坐标系。 ②绘图API。见补充版(http://www.dpj.com.cn)。

    智能硬件 接口 应用程序 microwindows

  • C8051F02X外部存储器接口和I/O端口配置

        摘要:介绍美国Cygnal公司生产的C8051F02X系列单片机的外部存储器接口、I/O端口配置方法和有关注意的问题;在此基础上列举两个关于EMIF、I/O的配置应用。     关键词:C8051F02X EMIF I/O 交叉开关 美国Cygnal公司C8051F02X系列单片机是集成在一起芯片上的混合信号系统级单片机。该单片机具有32/64位数字I/O端口(引脚)、25MIPS高速流水线式8051微控制器内核、64KB在系统可编程Flash存储器、64KB地址的外部存储器接口、4352(4096+256)B片内RAM、各自独立的SPI、SMBUS/I2C和两个UART串行接口等特点。其最突出的优点就是,通过设置交叉开关寄存器控制片内数字资源映射到外部I/O引脚,这就允许用户根据自己的特定应用,选择通用I/O端口和所需要数字资源。当然,在设置数字交叉开关寄存器时,应该首先考虑EMIF的配置问题。其配置不同,将导致单片机通过不同的端口(低或高)访问片外存储器和存储器映像的I/O部件,以及数字交叉开关是否分配外部设备给P0.7(WR)、P0.6(RD)、P0.5(ALE)引脚。(如图EMIF设置为多路器模式。) 1 EMIF和I/O配置方法 1.1 外部存储器接口(EMIF)配置 C8051F02X系列MCU有4KB的RAM可以只映射在片内,也可以映射在64KB外部数据存储器地址空间,还可以同时映射到片内和片外(4KB地址以内在片内存储器空间访问,4KB以上经过EMIF访问)三种方式。对于后两种存储器工作模式,需通过外部存储器接口使用MOVX和DPTR或MOVX和R0(R1)指令访问外部数据存储器和存储器映像的I/O设备。但是对于高8位地址,必须由外部存储器接口寄存器(EMI0CN)提供;而EMIF可将外部数据存储器接口映射到低端口(P0~P3)(F020/2/3系列)或高端口(P4~P7)(F020/2系列),以及配置为复用模式或非复用模式等。配置外部存储器接口的步骤下: *设置EMIF为低端口或高端口; *设置EMIF为复用模式或非复用模式; *选择存储器模式(片内方式、无块选择分片方式、带块选择分片方式、片外方式); *设置片外存储器或片外设备时基; *选择相关I/O端口(寄存器PnMOUT、P74OUT)的输出模式。 外部存储器接口(EMI)映射为低端口(P0~P3)即PRTSEL位(EMIOCH.5)置为0,如PRTSEL位置为1,EMI映射为高端口(P4~P7)(适用于P020/2系列)。此时如果EMIFLE位(XBR2.5)被设置为逻辑1,那么,数字交叉开关将不分配外部设备给P0.7(WR)、P0.6(RD)、P0.5(ALE)引脚(如果EMI设置为多中模式);如果EMIFLE位设为0,那么P0.7、P0.6、P0.5引脚的功能将由交叉开关寄存器或端口锁存器来决定。外部存储器接口只有执行片外MOVX指令期间使用相关的端口引脚,一旦MOVX指令执行完毕,端口锁存器或交叉开关寄存器又重新恢复对端口引脚的控制。 1.2 I/O端口配置 数字交叉开关译码器按照被使用设备的优先权顺序将端口P0~P7的引脚分配给外部数字外设。端口引脚的分配是从P0.0开始,没有被使用的引脚可作为一般通用的I/O引脚,通过读写相应的端口数据寄存器访问。在数字交叉开关寄存器XBR0、XBR1、XBR2中将相应的内部数字资源使能位置1,数字资源就映射到I/O端口引脚。例如:将UART0EN位(XBR0.2)置为1,那么,TX0和RX0引脚被分别映射到P0.0和P0.1。因为UART0具有最高的优先权,故在它的使能位置1时,TX0和RX0引脚总是被映射到P0.0和P0.1。如果一个数字外设的使能位没有置1,它的端口的I/O引脚上是不能被访问的。数字交叉开关寄存器被正确配置以后,通过置XBARE(XBR2.4)位1来使能交叉开关。在交叉开关使能后。P0~P3(F020/1/2/3系列)或P0~P7(F020/2系列)输出驱动自动被禁止,从而避免了交叉开关寄存器和其它寄存器写入时在端口引脚上产生的冲突。注意:对于由交叉开关分配的输入引脚(如T0、INT0、RX0等),其输出驱动自动被禁止,因此,端口数据寄存器和PnMDOUT寄存器的值对这些引脚的状态没有影响。 在给单片机内部数字资源分配了相应的I/O引脚后,还应设置其输出方式:推挽和漏极开路。PnMDOUT寄存器各位决定P0~P7端口引脚的输出方式,某一位置1,则该位为推挽输出方式;置0,为漏极开路输出方式。PnMDOUT寄存器控制端口引脚的输出方式,而与交叉开关是否把端口引脚分配给数字外设无关。注意:对于由交叉开关分配的输入引脚(如:SDA、SCL、RX0、RX1等)自动配置为漏极开路方式,而与相应的端口配置寄存器的设置无关。但对于一般的I/O引脚配置为输入时,与这一引脚相关的PnMDOUT设置为漏极开路,同时端口配置寄存器位必须清0。 尽管在C8051F021/3中P4、P5、P6和P7没有对应的引脚,但端口数据寄存器仍然存在,并可为软件所用。由于数字输入通路保持活动状态,所以建议不要将这些引脚处于“悬空”状态,避免因输入浮空为无效逻辑电平而导致不必要的功率消耗。下面的三种方法可以防止这种情况的发生: ①通过将WEAKPUD(XBR2.7)设置为逻辑0来使能弱上拉部件; ②通过写P74OUT=0xFF,将P4、P5、P6和P7的输出方式配置为推挽方式; ③通过向端口数据寄存器写0,将P4、P5、P6和P7的输出状态强制为逻辑0,即P4=0x00、P5=0x00、P6=0x00、P7=0x00。 2 EMIF和I/O端口配置应用 下面应用基于C8051F021/3单片机,也适应于C8051F020/2单片机。 *假设有一应用需要配置UART0、SMBus、UART1、INT0和INT1(8位),存储器的工作模式为片内方式;另外,P1端口作为4×4键盘的接口,P2、P3口作为通用的I/O端口。该应用的EMIF和I/O端口配置如下: ①设EMI的配置寄存器FMI0CF=0x00,因为本应用无扩展存储器和存储器映像的I/O设备,即存储器工作模式为片内方式;同时,将EMIFLE(XBR2.5)设置为0,这样P0.7、P0.5的引脚将由交叉开关寄存器或端口锁存器来决定,不被交叉开关跳过。 ②按UART0EN=1、UART1EN=1、SMB0EN=1、INT0E=1、INT1E=1和EMIFLE=0,设置XBR0、XBR1、XBR2为XBR0=0x05、XBR1=0x14、XBR2=0x04。 ③配置P1端口为数字输入模式,即P1MDIN=0xFF;P1端口低四位为键盘输出,高四位为输入,即P1MDOUT=0x0FH(P1.0~P1.3为推挽方式,P1.4~P1.7为漏极开路方式),P1|=0xF0。 ④使能交叉开关,即XBARE=1、XBR2=0x44。 因为EMIFLE=0,交叉开关译码器将不跳过P0.7、P0.6、P0.5引脚,所以按优先极交叉开关译码表进行分配。UART0具有最高优先极,故P0.0分配给TX0,P0.1分配给RX0;SMBus的SDA、SCL分别分配在P0.2、P0.3引脚;UART1的TX1、RX1分别分配在P0.4、P0.5引脚;INT0分配在P0.6引脚;INT1分配在P0.7引脚。 ⑤设置UART0的TX0引脚(TX0、P0.0)、UART1的TX1引脚(TX1,P0.4)为推挽输出方式,即P0MDOUT=0x11。RX0、SDA、SCL、RX1、INT0和INT1是由交叉开关分配输入的,因此与其端口配置寄存器的值无关。 ⑥P2、P3作为一般I/O端口初始化为输入状态,即P2MDOUT=0x00、P2=0xFF和P3MDOUT=0x00、P3=0xFF。 引脚功能如表1所列。表1 引脚 P0.0 P0.1 P0.2 P0.3 P0.4 P0.5 P0.6 P0.7 P1 P2 P3 功能 TX0 RX0 SDA CL TX1 RX1 INT0 INT1 键盘 通用 通用 *设现有一应用需要UART0、SMBus、UART1、INT0和INT1共8位。另外,存储器工作方式为带块选择的分片方式,EMIF为复用模式、低端口,并配置P1.2、P1.3、P1.4为模拟输入模式,通过这三个引脚利用ADC1来测量输入电压。具体配置步骤如下: ①配置EMI为复用模式和工作在低端口,即PRTSEL=0,EMD2=0;存储器模式为带块选择的分片方式,即EMD1~0=10;ALE时基设为2个SYSCLK周期,即EALE1~0=01。 ②按UART0EN=1、UART1EN=1、SYB0EN=1、INT0E=1、INT1E和EMIFLE=1,设置XBR0、XBR1、XBR2为XBR0=0x05、XBR1=0x14、XBR2=0x42。 ③配置P1端口的P1.2、P1.3、P1.4为模拟输入模式,这些引脚对应的位在P1MDIN寄存器中置为0,即P1MDIN=0xE3。 ④使能交叉开关,即XBARE=1、XBR2=0x46。 UART0具有最高优先权,故P0.0分配给TX0,P0.1分配给RX0;依次按照优先极分配表,SMBus的SDA、SCL分配在P0.2、P0.3引脚;UART1的TX1、RX1分配在P0.4、P1.0引脚。因为EMI工作在低端口且为复用模式,交叉开关译码器将不分配内部数字资源给P0.7(WR)、P0.6(RD)、P0.5(ALE),所以,RX1按次序分配在P1.0引脚,INT0分配在P1.1引脚。由于P1.2、P1.3、P1.4被配置为模拟输入,交叉开关跳过这些引脚,故INT1分配在P1.5引脚。在执行片外MOVX指令时,EMI将驱动P2和P3端口。 ⑤配置UART0的TX0引脚(TX0,P0.0)、UART1的TX1引脚(TX1,P0.4)、P0.7(WR)、P03.6(RD)、P0.5(ALE)为推挽输出方式,即P0MDOUT=0xF1。 ⑥配置EMIF的端口(P2、P3)输出为推挽方式,即P2MDOUT=0xFF和P3MDOUT=0xFF。 ⑦通过设置P1MDOUT=0x00(输出为开漏极)和P1=0xFF(P1为高阻状态)来禁止P1.2、P1.3、P1.4三个模拟输入引脚的输出驱动器。 引脚功能如表2所列。表2 引脚 P0 P1 P2 P3 0 1 2 3 4 5 6 7 0 1 2~4 5 6~7 功能 TX0 RX0 SDA SCL TX1 ALE RD WR RX1 INT0 模拟输入 INT1 通用 复用高地址 复用低地址/数据 3 总结 C8051F02X具有低功耗(3V工作电压)、大容量存储器、高速度、高集成度等特点,广泛应用于工业控制、测量系统、报警系统。该单片机具有双串行口,更适合于定位和报警系统的前端,从而提高移动终端集成度和降低功耗。

    智能硬件 接口 端口 c8051f02x 外部存储器

  • WindowsCE.Net下CAN卡的驱动程序设计

       摘要:主要讨论在WinCE设计和开发CAN卡通信程序的方法;详细介绍CAN卡底层驱动函数的设计和实现,同时将驱动进行封装,用动态库的方式提供给用户CAN卡通信用的驱动,使用启可以方便地在自己的程序中调用,实现WinCE下的CAN卡通信。     关键词:WinCE.NET CAN 驱动 引言 近年来电力行业为了快速部署变电站,采用了建造整体变电所的方法:在生产基地将变电站的内部设备安装、调试完成,只留下与外界的接口,整体运到变电站所在地后进行安装和简单调试即可投入运行。其内部设备通过CAN总线进行通信,系统原有的监控软件基于DOS系统,维护调试比较困难,因此想要寻求更方便、友好的系统支持。经过比较,嵌入式操作系统市场上风头正劲的Windows CE .NET成为最终选择。微软的最新产品Windows CE.NET提供了端对端的开发、调试手段,可以不拆卸设备的情况下通过Telnet登录到WindowsCE上进行调试和维护,其系统本身为嵌入式市场进行重新设计,包括创建一个基于WindowsCE的定制设备所需的一切。这样就需要将原来DOS下的程序移植到WindowsCE.NET下,但是各个硬件厂商目前还没有提供CAN通信卡在Windows CE.NET下的驱动,所以开发Windows CE.NET下的CAN卡驱动成为项目推行中的关键一环。 本文主要针对研华的双口CAN卡PCM3680进行分析,介绍在WindowsCE.ENT系统下进行底层设备驱动开发的方法并提供CAN通信的实例。1 CAN总线通信协议及CAN通信卡介绍 CAN总线是德国Bosch公司20世纪80年代初为解决现代汽车中众多的控制与测试仪器之间的数据交换而开的一种串行数据通信协议。它是一种多主总线,废除了传统的站地址编码,而代之以对通信数据块进行编码。这种方法使网络内节点个数在理论上不受限制,扩展格式中的29位的标识码便可以定义2 29个不同的数据块。 在本项目中使用的是研华的PCM3680,这是一块嵌入式PC104的双口CAN总线通信卡;CAN控制器采用Philips的独立CAN控制器SJA1000芯片;CAN收发器采用Philips的P82C250,可以同时操作两个CAN网络,提供高达1Mb/s的传输速度。PCM3680支持很宽的中断范围:中断3、4、5、6、7、9、10、11、12、15,同时1000V的光电隔离提供系统高可靠性。在CAN卡通信中,要用到CAN控制器中的很多寄存器,各个寄存器的含义和作用可以参考控制芯片的说明书。图1列出驱动程序设计中用到最主要的寄存器结构。 2 CAN卡驱动底层函数设计 本方案设计CAN驱动是放在Windows CE操作系统的内核下层,位于OEM adaptation layer(OAL)层的一个真正的驱动,而不是在主程序中的串口操作。在Windows CE的设备管理器可以看到CAN1和CAN2两个端口,并且可以查看其工作的正常与否和对其进行配置。如:中断号和I/O地址。 2.1 CAN卡寄存器读写函数 CAN卡的通信是通过操作CAN卡上的CAN控制器进行的。在CAN控制器中有很多寄存器,如控制寄存器、命令寄存器、状态寄存器、中断寄存器等,通过读写这些寄存器中的命令状态字可以检测和控制CAN卡的行为。在Windows CE.NET下,通过调用DOK中的API函数HalTranslateBusAddress,将CAN卡分配的物理地址映射为逻辑地址。这样各个寄存器对应的就是CAN卡基地址的偏移地址,因此,对寄存器的读写就转化为对内存地址的读写。下面是CAN卡寄存器的读写函数: *在偏移量为off的地址读取一个字节的数据inline BYTE CANR(LPCAN_HW_OPEN_INFO hCan,DWORD off) { return hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr[off]; *将一个字节数据写到偏移量为off的地址中inline VOID CANW(LPCAN_HW_OPEN_INFO hCan,DWORD off,BYTE val) { hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr[off]=val; } 参数LPCAN_HW_OPEN_INFO定义的是CAN卡的数据结构,其中成员lpMappeBaseAddr[0]表示的是映射后基地址,lpMappedBaseAddr[1]就是基地址+1的地址,对应CAN卡的寄存器是命令寄存器。通过上述两个函数可操作CAN卡上的所有寄存器。 2.2 CAN卡初始化 CAN卡的控制器比较复杂,在通信前必须确认硬件信息正确性、初始化各寄存器。初始化函数的基本流程如图3所示。 第一步,检查端口号和硬件信息的正确性,主要是CAN卡中断号是否有效。 第二卡,设置CAN卡默认参数: CanCardConfigInfo CAN_DEFAULT_SETTING= {0X00,0XFF,0X03,0X1C};/*设置默认波特率为125Kbps*/ DWORD dwThreadID =0; PHYSICAL_ADDRESS phyAddr={hwInfo->dwIOBaseAddr *16,0 }; 第三卡,用WinCE API函数LocalAlloc为CAN卡驱动中用到的数据结构分配缓冲区;通过HalTranslateBusAddress和MmMapIoSpace函数映射I/O地址,提供直接访问设备的虚拟地址: if(!HalTranslateBusAddress(Isa,0,phyAddr,0,&phyAddr)) goto _ExitInit; hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr= (LPBYTE)MmMapIoSpace(phyAddr,CANCARDADDRLEN,FALSE); if(!hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr) goto _ExitInit; 如果分配内存或映射逻辑地址失败,则退出初始化程序,CAN卡初始化失败。 第四步,初始化读写属性、共享模式、读超时时间和第二个CAN口的基地址。 第五步,创建CAN卡事件和数据接收事件:hCan->lpCanHWInfo->hCanEvent=CreateEvent(NULL,FALSE,FALSE,NULL); hCan->lpCanHWInfo->hRecvMsgEvent=CreateEvent(NULL,FALSE,FALSE,NULL); 第六步,初始化中断,如果CAN卡有复位请求就退出初始化程序。设置好中断后启动数据接收线程,设置线程优先级继续线程处理;最后配置CAN卡参数,进入正常运行状态。 2.3 CAN卡信息发送 CAN卡的信息发送分为两个步骤。在对CAN卡基本信息进行检查后,首先设置发送缓冲的ID号。CAN标准模式的ID号为11位,偏移地址10中存放的是ID号的高8位,偏移地址11的高3位存放的是ID号的低3位,剩下5位分别是RTR位(远程传送请求位)和数据长度。通过CANW函数将处理后的数据写入到相应的偏移地址,设置完相应的地址数据后,通过循环将偏移地址12~19的数据采集回来存到数组中。然后,设置CAN卡的传输请求为允许并不断侦测状态寄存器的变化,当传输缓冲满标志或传输结束标志为1时通出程序,完成一次数据采集。传输缓冲区的寄存器如表1所列。表1 ID号 10 ID.10 ID.9 ID.8 ID.7 ID.6 ID.5 ID.4 ID.3 RTR,数据长度码 11 ID.2 ID.1 ID.0 RTR DLC.3 DLC.2 DLC.1 DLC.0 数据1~8 12~19 数据 数据 数据 数据 数据 数据 数据 数据 表2 ID号 20 ID.10 ID.9 ID.8 ID.7 ID.6 ID.5 ID.4 ID.3 RTR,数据长度码 21 ID.2 ID.1 ID.0 RTR DLC.3 DLC.2 DLC.1 DLC.0 数据1~8 22~29 数据 数据 数据 数据 数据 数据 数据 数据 CAN消息发送函数的实现如下: BOOL CAN_SendMessage(LPCAN_HW_OPEN_INFO hCan,LPCanCardMessageBuflpMsg) { BOOL bSuc=FALSE; ASSERT(hCan && lpMsg && lpMsg->dwMessageLen <=8); /*防错处理*/ if(0= =(hCan->dwAccessCode & GENERIC_WRITE)) return FALSE; :: EnterCriticalSection(&hCan->lpCanHWInfo-> TransmitCritSec); /*进入临界区*/ BYTE byV=static_cast<BYTE>(1pMsg->dwMsgID>>3); CANW(hCan,10,byV); /*设置ID值高8位*/ byV=static_cast<BYTE>=((lpMsg->dwMsgID & 7)<<5); if(lpMsg->bRTR) byV|=0x10; byV+=static_cast<BYTE>(lpMsg->dwMessageLen); CANW(hCan,11,byV);/*设置ID值低3位、RTR及数据长度*/ for(UINT i=0;<lpMsg->dwMessageLen;++i) { CANW(hCan,12+i,lpMsg->byMsg[i]); } /*采集数据*/ CANW(hCan,1,1);/*重置传输请求*/ while(TRUE) {byV=CANR(hCan,2); if(byV & 0X40) /*传输缓冲区满,退出*/ {break;} if(byV & 0X8){ /*传输结束,正确返回退出*/ bSuc = TRUE; break;} } ::LeaveCriticalSection(&hCan->lpCanHWInfo->TransmitCritSec); /*离开临界区*/ return bSuc; } 2.4 CAN卡信息接收 CAN卡的信息接收是发送的逆过程,当接收缓冲区标志为1时,表示缓冲区已满可以接收数据,将数据接收到数组后释放接收缓冲区,然后对接收到的数据进行分解并存储到CAN卡信息缓冲区的结构体。接收缓冲区的寄存器结构如表2所列。 CAN消息接收函数的实现如下: BOOL CAN_RecvRecvMessage(LPCAN_HW_OPEN_INFO HCan,OUT LPCanCardMessageBuflpMsg) {…… if(CANR(hCan,2)&1){ /*判断接收缓冲区是否已满*/ for(UINT i=0;i<10;++i) recvBuf[i]=CANR(hCan,20+i);/*将数据暂存到临时缓冲区*/ CANW(hCan,1,4); /*释放接收缓冲区*/ LpMsg->dwMsgID=recvBuf[0]<<3; /*取出ID的高8位*/ BYTE byV =recvBuf[1]; LpMsg->dwMsgID+=byV >>5;/*取出ID低3位,然后和高8位合并*/ LpMsg->bRTR =byV &0x10?TRUE:/*返回RTR状态*/ LpMsg->dwMessageLen = byV &0XF; /*返回数据长度*/ …… } else {++hCan->lpCanHWInfo->dwErrorMsgCount;}/*没有收到数据,错误计数加1*/ ::LeaveCriticalSection(&hCan->lpCanHWInfo-> ReceiveCritSec); /*离开临界区*/ Return bSuc; } 2.5 CAN卡事件处理 CAN卡事件处理函数是CAN卡驱动程序中很重要的部分。驱动设计要求具有消息通知的功能,当事件发生时及时捕获事件并进行消息处理。 下面是事件处理函数的实现: staric DWORD WINAPI CAN_EventHanle(LPVOID lpParam) { ASSERT(lpParam); LPCAN_HW_OPEN_INFO hCan=(LPCAN_HW_OPEN_INFO)lpParam; CanCardMessageBuf bufMsg; while(TEUE) { /*循环等待CAN卡消息产生,然后进行处理*/ ::WaitForSingleObject(hCan->lpCanHWInfo->hCanEvent,0XFFFFFFFF); if(hCan->lpCanHWInfo->bKillCanThread) break; /*若CAN线程已关闭则中断*/ if(CAN_RecvMessage(hCan,&hufMsg)){ /*正确接收数据后*/ CAN_RecvBufPush(hCan,&bufMsg);} /*将数据压入缓冲*/ BYTE byV=CANR(hCan,3); /*将3号寄存器读出然后立即写入*/ CANW(hCan,3,byV);/*能够获取每次中断*/ InterruptDone(hCan->lpCanHWInfo->lpCanObj->dwSysIrqt); } /*本次中断结束,等待下次中断*/ return 0; } 2.6 其它函数 为了提供更多的功能和更方便地使用CAN卡进行通信,在CAN卡驱动程序中还设计了一些函数如CAN_Config用CAN卡信息配置、CAN_RecvBufPop用于处理接收缓冲区、CAN_Reset用于复位CAN卡、CheckHWInfo用于硬件信息检查等。这些函数提供了对CAN通信卡的设置、检查等功能,在这里不再详述了。 3 CAN卡驱动封装设计 CAN卡底层驱动函数虽然功能完整,但是对于用户使用比较复杂并且一般用户不需要了解底层实现的机制。为了便于使用,最后对CAN卡的驱动进行了封装,提供CanOpenFile、CanSendMsg等五个函数用于CAN总线的通信,以动态连接库(DLL)的形式提供给用户调用。封装函数及功能如下: *CanOpenFile;初始化并打开CAN卡的一个端口。 *CanCloseFile;关闭由CanOpenFile打开的CAN卡端口。 *CanRecvMsg;接收CAN卡数据,打开CAN卡时必须具有GENERIC_READ权限。 *CanSendMsg;通过CAN卡发送数据。打开CAN卡时必须具有GENERIC_WRITE权限。 *CanIOControl;设置或获取CAN卡I/O参数支持的I/O控制包括:IOCTL_CAN_CONFIG,IOCTL_CAN_RESET,IOCTL_CAN_TIMEOUT,IOCTL_CAN_SENDREADY,IOCTL_CAN_RECVREADY。 下面是CanSendMsg函数实现的代码: BOOL CanSendMSg( HANDLE hCan, LPCanCardMessageBuflpMsg) { if(!hCan||INVALID_HANDLE_VALUE= =hCan|| !lpMsg||lpMsg->dwMessageLen>8)return FALSE; return CAN_SendMessage(LPCAN_HW_OPEN_INFO) hCan,lpMsg); 该函数就是通过封装CAN卡的底层驱动函数SendMessage来实现的,这样将功能集中的五个函数更方便了用户使用。 结语 程序开发的上位机是普通的PC机,软件环境是:Windows2000 Professional、Embedded Visual C++4.0、与下位机中WinCE.NET对应的SDK,该SDK是在用Platform Builder 4.0定制WinCE时编译生成的。下位机使用的硬件是研华的嵌入式PC104主板PCM3346N,操作系统为WinCE.ENT。 本文设计开发的驱动已经在北京怀柔的变电站项目中得到成功的应用,CAN卡通信稳定,系统在WINCE.NET下运行可靠,保证了项目的顺利实施。

    智能硬件 驱动 can windowsce net

发布文章