基于FPGA的任意波形发生器设计与实现 下载本文

内容发布更新时间 : 2024/11/2 17:38:32星期一 下面是文章的全部内容请认真阅读。

60

基于FPGA的任意波形发生器的设计与实现

号来控制数据选择器的选择端就可以改变DDS的输出信号频率。如当选择端信号为“0”时,输出频率控制字1对应的频率,当选择信号为“0”时,输出频率控制字2对应的频率,从而实现了FSK。要实现PSK,需要在相位累加器的输出端添加一个加法器,加法器的输入值为PSK信号的两个初始相位之一,通过二进制信号来控制数据选择器的选择端就可以改变DDS输出信号的初始相位,从而实现PSK。FSK、PSK调制信号在FPGA中的实现框图如图4.16所示。

4.4 相位抖动注入技术的研究

在第二章讨论降低DDS输出信号的杂散谱时曾经提到几种方法:加大波形存储器存储深度、对存储器中的数据进行压缩、增加DAC的分辨率等。这些方法能在一定程度改善杂散,但应该看到这些方法有一定的局限性。

从第二章的分析可知,相位截断时,DDS的杂散根本原因在于相位截断误差 ? p ( 如果能打破这种周期性就会在一定程度改善杂散。在这里n )是一个周期序列,采用加扰码的方法,具体实现如图4.17。

频率字相位累加器加法器扰码产生器图4.17 相位抖动注入框图

波形存储器

它的主要思想是把确定性的、有规律的杂散转化成随机的、无规律的相位噪声。这里的扰码产生器又叫M序列发生器[31],是多级移位寄存器级联而成,目的是产生一些随机数加在相位累加器的后面,使相位累加器的溢出不总是比理想的推后,而是随机地提前,从而打破相位截断误差的周期性。

从式(2-38)可知,相位截断引起的相位误差序列为 e p ( n ) ? nK mod2 B ,它的周

'期为mk?2B/GCD(2B,Kmod2B),加上扰码之后:

e'p(n)??(nKmod2N)?Random(2B)?mod2B 式(4-9)

其中,Random(2B)表示在[0,2B]范围内均匀分布的随机数。可见 ? 'p ( n ) 为一随即序列,相应此时的DDS输出序列为:

2??2??Sp(n)?sin?NK?n?Ne'p(n)? 式(4-10)

2?2? 可以看出,由于 e 'p 的调相作用, S p ( n )也没了规律。这样就把有规律的杂散转化成随机的相位噪声。

第五章 任意波形发生器的软件设计

61

第五章 任意波形发生器的软件设计

5.1 系统软件结构

基于FPGA的任意波形发生器的软件按层次可以划分为固件程序、USB驱动程序和用户应用程序三个部分,如图5.1所示。

应用程序驱动程序固件代码

图5.1 系统软件结构

固件程序(firmware)是运行在USB接口芯片中8051微控制器内的程序,它是用户命令转换为电路中电信号的解释器,也是数据传输的中转器,必须和USB驱动程序、用户应用程序在时序上非常准确的配合。固件程序接收到用户应用程序下发的数据包后,通过分析数据包中的数据,解释命令然后执行相应的操作;

驱动程序的作用是为系统和硬件设备提供一个接口,它支持用户应用程序所要求的信息流。由于Windows对系统底层操作采取了屏蔽的策略,所以由用户应用软件发出的数据包必须经过USB设备传递给USB总线驱动程序,再由USB总线驱动程序将数据包送外设的USB控制器;

用户应用程序实现用户和任意波形发生器的交互操作,用户通过用户应用程序控制着输出波形的种类、频率、幅度等参数。

5.2 固件程序设计

所有基于微控制器及其外围电路的功能设备要正常工作都离不开固件的参与,固件的作用就是辅助硬件或者说是控制硬件来完成预期的设备功能。尽管EZ-USB FX2系列接口控制芯片已经相当智能了,但是其仍不可能完成所有的工作,固件程序的目的就是要辅助FX2接口控制芯片完成USB的通信任务。设计中使用了德国Keil软件公司的集成开发环境Keil uVision2来开发FX2的固件程序,程序语言为C51语言。

62

基于FPGA的任意波形发生器的设计与实现

5.2.1 功能分析

在本设计中,微控制器固件程要实现的功能[32]主要包括以下三点: (1)初始化工作,包括设置一些特殊功能寄存器的初值以实现所需的设备属性或者功能,如开中断、使能端点、配置端口等;

(2)辅助硬件完成设备的列举过程,对主机的设备请求作出相应的响应,完成主机对设备的配置;

(3)从主机接收数据包,并根据事先定义的协议进行相应的操作,如向FPGA内部的寄存器和波形RAM发送数据。

5.2.2 固件程序结构

要编写一个优秀的固件程序,固件的开发这必须对芯片的硬件资源及工作原理有比较深入的了解,值得高兴的是,Cypress公司为其FX2系列的USB芯片提供了一个固件程序结构[34],固件的开发者只需要提供设备描述符表和外设的功能程序代码就可以完成整个固件的开发。下面结合固件程序流程图,分析固件代码中比较重要的几个部分。

上电复位初始化状态变量调用TD_Init()使能中断收到Setup包?N延迟1s并重列举Y调用TD_Poll()收到Setup包?YYY解析并执行设备请求NNNUSB总线空闲?调用TD_Suspend()成功调用?调用TD_Resume()挂起处理器 图5.2 固件程序流程图

第五章 任意波形发生器的软件设计

63

图5.2所示固件程序流程图中,有几个比较重要的函数:

(1)TD_Init( ):此函数主要根据用户的要求完成特殊寄存器初始化; (2)TD_Poll( ):任务调度函数,被固件主程序循环调用的,用于监视用户的请求,通过执行该函数中具体程序功能代码来实现对用户接口的控制的;

(3)TD_Suspend( ):此函数的作用是在USB内核没有操作时进入低功耗状态;

(4)TD_Resume( ):此函数用于对外部恢复事件作出响应,恢复芯片的正常供电和微控制器的正常工作状态。

对FX2芯片的固件程序开发大多数情况只需要在TD_Init( )和TD_Poll( )两个函数中编写功能代码即可。

5.2.3 固件程序开发

在设计中,CY7C68013芯片的固件程序共包含了8个程序文件:

(1)testregs.h:这个文件对CY7C68013的各个寄存器及寄存器相应的位进行了定义。

(2)testheader.h:定义了通用的EZ-USB FX2常量、数据类型和宏,如USB描述符的数据结构、FX2所含的中断向量等。

(3)testdly.h:定义了同步延时宏SYNCDELAY。在读写EZ-USB FX2的某些特殊寄存器时,必须使用该宏进行隔离。

(4)dscrptr.a51:定义了系统所使用的各种USB描述符。

(5)delayms.a51:包含延时1ms的子程序和芯片挂起处理子程序。 (6)jmptable.a51:定义了CY7C68013芯片的INT2和INT4跳转表。 (7)main.c:固件的主程序文件,负责处理主机发出的各种USB设备请求。 (8)function.c:包含各种用户功能函数(如TD_Init( )、TD_Poll( )等)和IN2、INT4中断服务程序的定义,它负责实现系统的主要功能。用户需要在该文件中添加相应代码来实现硬件功能。

在开发CY7C68013芯片的固件程序时,我们只用到了其两种接口方式:端口方式和从属FIFO方式。在TD_Init( )初始化函数中,我们将接口设置为从属FIFO方式,采用同步传输机制,使能端点2,同时禁止端点4、端点6、端点8(因为我们只使用了端点2作为数据传输通道),端点2配置为4重缓冲,每重缓冲区为1K字节;在TD_Poll( )函数中,实现了在端口方式和从属FIFO方式两种接口方式之间的切换,同时,在端口方式下,根据用户请求控制I/O口输出数据、地址和控制信号(在从属FIFO方式下,数据的传输是自动完成的,因此不需要固件的参与)。

64

基于FPGA的任意波形发生器的设计与实现

代码添加完毕之后就可以生成固件程序了,具体步骤如下:

(1)项目生成:打开Keil uVision2集成开发环境,选择Project->New project新建工程,在弹出的对话框中选择所用芯片为EZ-USB FX2;

(2)项目设置:在工作区右键点击Target,在弹出的属性设置对话框中设置晶震频率、输出文件的命名等参数;

(3)添加源文件:在Source Group中添加源文件,另外,在项目的自动映射的库文件中没有包含的头文件,一定要存放在该目录下面,否则编译时将会出错。

(4)编译链接:C51编译器在检查程序代码无语法错误之后就会生成.hex文件,这个文件将在后面的CY7C68013下载驱动程序开发时用到。

5.3 USB设备驱动程序

设备驱动程序是一个软件组件,在装入后就成为操作系统内核的一部分。这些驱动程序介于硬件和用户应用软件之间,为他们之间的通信提供桥梁。应用程序可以不必知道将要或者正在与之通信的硬件设备的属性,这些工作全部交由各个层次的驱动程序来完成的,应用程序只需要知道设备的名称和设备的功能就可以了。在Windows操作系统下,应用程序可以通过驱动程序像操作一般文件一样来访问硬件设备,以实现应用层和设备的交互。USB驱动程序属于标准的WDM(Windows Driver Mode)驱动程序。一个基本的WDM驱动程序包含以下5个例程:

(1)驱动程序入口例程:处理驱动程序的初始化; (2)即插即用例程:处理PnP设备的添加、删除和停止; (3)分发例程:处理用户应用程序发出的各种I/O请求; (4)电源管理例程:处理电源管理请求; (5)卸载例程:处理驱动程序的卸载。

5.3.1 驱动程序的实现

在设计中,由于CY7C68013采用了软配置方式,即其固件代码存放在主机上,当它连接到主机时,才将固件自动下载至其RAM中并由8051执行。因此需要两个驱动程序:一个是用来下载芯片固件程序的loaddriver.sys,另一个是用于实现系统功能的usbdriver.sys。其中loaddriver.sys由我们自行设计,usbdriver.sys由Cypress公司提供。

需要参加loaddriver.sys驱动程序编译的总共有四个文件:TestInit.c、TestPnp.c、Loader.c和Tagtest.c。其中TestInit.c负责处理驱动程序的入口例程和卸载例程;