网站首页 > 资源文章 正文
1)实验平台:正点原子开拓者FPGA 开发板
2)摘自《开拓者 Nios II开发指南》关注官方微信号公众号,获取更多资料:正点原子
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/index.html
第二十七章开拓者FPGA开发板GUI综合实验
本章将通过一个综合实例,向大家展示FPGA强大的并行处理能力以及与Nios II的协同处
理,并且可以测试开发板的大部分功能。该实验代码非常多,涉及uC/GUI、图像缩放处理、
音频播放、OV5640摄像头图像显示、手写画笔等非常多的内容,其中大部分功能在前面的实
验中都有实现过,故本章不对代码进行讲解,只介绍程序的设计思路与实现的功能。
本章包括以下几个部分:
27.1 开拓者开发板 GUI 综合实验简介
27.2 实验任务
27.3 硬件设计
27.4 软件设计
27.5 下载验证
开拓者开发板GUI综合实验简介
大家收到的开发板,默认固化的就是本次GUI综合测试实验的程序,开发板必须连接LCD
屏,才能显示UI界面以及测试开发板的外设,本次实验支持正点原子推出的所有的LCD屏。
开拓者FPGA开发板综合实验除上电自检外,总共有14大功能,分别是:按键测试、LED测
试、蜂鸣器、数码管、串口、红外遥控、EEPROM、环境光、RTC实时时钟、音乐播放、ADDA、
手写画笔、摄像头和网络通信。
按键测试:一个按键测试应用,可以测试板载的4个按键的好坏。
LED测试:一个LED测试应用,可以测试板载的4个LED的好坏。
蜂鸣器:一个蜂鸣器测试应用,可以测试蜂鸣器的好坏。
数码管:一个数码管测试应用,可以测试数码管的好坏。
串口:一个串口通信数据环回应用,通过串口助手完成和开发板的串口通信的功能。
红外遥控:一个红外遥控测试应用,可以测试板载的红外遥控的好坏。
EEPROM:向EEPROM中写入数据,写入完成后读出数据,通过比较写入的数据和读出的数
据是否一致,来判断EEPROM读写是否正确。
环境光:一个环境光传感器测试应用,读出并显示环境光传感器的光强度和距离值。
RTC实时时钟:一个RTC实时时钟测试应用,读出并显示当前的日期与时间。
音乐播放:音频信号从板载的LINE_IN接口输入,通过喇叭和PHONE接口(连接耳机)进
行播放,可以测试板载的音频芯片和喇叭的好坏。
ADDA:一个ADDA测试应用,通过DA和AD转换,测试板载ADDA的好坏。
手写画笔:在LCD屏上留下触摸后的轨迹,可以用来绘画和写字。
摄像头:通过连接OV5640摄像头,进行视频图像的实时显示。
网络通信:通过以太网的SMI接口(Serial Management Interface,串行管理接口),
读取当前网口和其它网络设备的连接状态。
以上是综合实验的14个功能简介,其中大部分功能在前面的实验中都有实现过,如果大
家有不明白的地方,可以参考前面的内容。在简介部分中,我们仅介绍新增的Qsys IP核和接
口,即缩放IP核(Scaler II – Edge Adaptive)和SMI接口。
缩放IP核(Scaler II – Edge Adaptive)
缩放IP核是Qsys系统提供的用于视频图像处理的IP核,该IP核支持输入视频流分辨率到
输出视频流分辨率的放大和缩小。我们知道,不同尺寸的LCD屏,它们的分辨率是不同的,即
使是相同尺寸的LCD屏,分辨率也可能不同,为了使综合实验能够兼容不同分辨率的LCD屏,
我们在综合实验中,添加了缩放IP核,便于兼容不同分辨率的LCD屏。
缩放IP核可选的算法有临近算法、双线性算法、双三次算法、多项式算法和边缘自适应
算法。临近算法相比于其它几种算法,其缩放效果较差,但是消耗的逻辑资源是最少的;而
其它几种算法虽然缩放效果更好,但是所消耗的逻辑资源也是相对较多的。考虑到综合实验
驱动的外设比较多,功能复杂,并且开拓者FPGA开发板上的逻辑资源有限,因此本次实验使
用的缩放算法是逻辑资源消耗最少的临近算法,同时其显示效果也能够满足我们的要求。
缩放IP核的配置界面如下图所示:
图 27.1.1 缩放IP核配置界面
? Bits per symbol:选择symbol的位数,通常是一个字节
? Symbols in parallel:选择并行发送的symbol个数
? Symbols in sequence:选择按顺序发送数据的个数,通常为1
? Enable runtime control of output frame size and edge/blur thresholds:使能运行时控制
帧输出大小和边缘/模糊阈值。
? Maximum input frame width:选择输入最大帧的宽度
? Maximum input frame height:选择输入最大帧的高度
? Maximum output frame width:选择输出最大帧的宽度
? Maximum output frame height:选择输出最大帧的高度
? 4:2:2 video data:选择帧格式是否为4:2:2格式
? No blanking in video:如果输入视频在转换到 Avalon-ST 视频协议时不包含垂直消隐,
则打开使能
? Scaling algorithm:选择缩放算法。Nearest Neighbor(临近算法)、Bilinear(双线性算
法)、Bicubic(双三次算法)、Polyphase(多项式算法)和 Edge Adaptive(边缘自适
应算法)。
其它一些不常用的参数保持默认即可,这里不作过多的介绍。
下表是缩放IP核常用的寄存器描述。
表 27.1.1 缩放IP核寄存器描述
由上表可知,地址0控制着缩放IP核是否使能;地址3和地址4控制输出视频的分辨率(宽
度和高度)。在获取到LCD屏的ID后,也就知道了LCD屏的分辨率,我们只需要将缩放IP核输
出的分辨率设置成LCD屏的分辨率即可,从而实现兼容不同分辨率的LCD屏。
Qsys系统中提供了很多VIP(Video and Image Processing,视频图像处理)的IP核,比
如:图像缩放、图像灰度校正等IP核。这些IP核在发送和接收视频数据时,都要按照Avalon
ST的视频标准进行传输,Avalon-ST的视频标准定义了传输的信号线,如图 27.1.2所示:
图 27.1.2 Avalon-ST视频格式信号线
图中为两个VIP IP核通过Avalon-ST的视频标准传输数据的示意图,从图中可以看到
Avalon-ST视频标准的端口信号,接下来我们介绍下这些端口信号分别代表什么含义。
startofpacket:开始包,用于表示一帧视频传输的开始,高电平有效。
endofpacket:结束包,用于表示一帧视频传输的结束,高电平有效。
data:视频流数据。
empty:可选的空标志信号,当单次传输超过一个像素点的时候,会增加一个空标志信
号,用于表示哪些数据是无效的。
valid:有效信号,用于表示data是否有效。
ready:准备完成信号,当ready信号拉高时,此时发送端开始发送数据。
Avalon-ST视频包传输时序图如所示:
图 27.1.3 Avalon-ST视频包传输时序图
由上图可知,在时钟(clock)的驱动下,当发送端检测到ready信号为高电平时,此时
开始传输数据,发送端拉高开始包信号(startofpacket)和数据有效信号(valid),此时
第一次传输数据。需要注意的是,图中一个时钟周期传输的数据量为24位,分3个通道传输,
对应缩放IP的设置为:Bits per symbol设置为8,Symbols in parallel设置为3。当单帧数
据传输结束后,此时拉高结束包信号(endofpacket)。
VIP IP核传输数据遵循Avalon-ST的视频标准,同时为了适配不同的视频流传输,这个标
准也是一个可配置的协议,包含视频包、控制包和用户包,我们称之为VIP视频协议。VIP视
频协议规定,在传输视频包之前,必须先传输控制包,而用户包是可选的,一般用来传输和
用户相关的内容,如帧ID信息、音频等。
包的类型是由包的ID来指定的,包起始传输的D0[3:0]即为包的类型,用于表示后面传输
的类型为视频包、控制包或者用户包。包传输ID与包传输类型的对应关系由下表所示:
表 27.1.2 包类型定义
在包传输的类型中,常用的就是控制包和视频包,从名字中我们就可以看出,控制包主
要用来传输一些配置信息的,而视频包用来传输视频数据,控制包数据的详细定义如下表所
示:
表 27.1.3 控制包数据定义
下图为扫描方式与具体值的对应关系。
图 27.1.4 扫描方式定义
图中Interlacing表示隔行扫描,Progressive为逐行扫描,本次实验所使用的为逐行扫
描,所以参数要设置为4’b0010。
由此可知,我们在使用缩放IP核时,必须按照VIP视频协议来传输数据,协议规定了传输
数据时包括控制包和视频包,同时在传输控制包和视频包之前,要先传输包类型ID,作为包
类型的标志。而在传输控制包和视频包时,要符合Aavlon-ST的视频流标准,最终我们缩放IP
核才能实现输入视频流分辨率到输出视频流分辨率的调整。
在介绍完缩放IP核后,接下来我们再来学习下SMI管理接口。
SMI管理接口
SMI串行管理接口,也被称作MDC/MDIO接口,可以用来读写PHY的寄存器。在“以太网通
信实验”章节中,实际上我们只用到了以太网的MII接口,并没有使用MDC/MDIO接口。
RTL8201CP芯片的参数可以通过MDC/MDIO接口来配置,由于其默认的参数就可以实现MII接口
的自适应10M/100M收发数据,因此可不必对芯片做配置。我们本次网络通信实验完成的功能
是读取网口和其它网络设备的连接状态,这个就需要通过MDC/MDIO接口来完成。
SMI串行管理接口包括MDC和MDIO两条信号线,MDC是时钟信号,由主机(FPGA)发送给从
机(PHY芯片),最大不超过2.5MHz;MDIO是双向数据信号,和IIC接口有些类似,但是其传
输的时序有些区别。SMI接口的写时序图和读时序图分别如图 27.1.5和图 27.1.6所示:
图 27.1.5 SMI接口写时序
图 27.1.6 SMI接口读时序
Preamble:前导码,DMIO至少保持32个时钟周期的高电平,用于同步PHY芯片。
ST(Start of Frame):2位帧开始信号,使用“01”作为帧开始信号。
OP(Operation Code):2位操作码,即读写控制信号,10:读;01:写。
PHYAD(PHY Address):5位物理地址,由PHY芯片引脚的9、10、12、13、15决定。
REGAD(Register Address):5位寄存器地址。
TA(Turnaround):2位的TA,在读命令中,MDIO在此时由MAC驱动改为PHY驱动,并等待
一个时钟周期准备发送数据;在写命令中,不需要MDIO方向发生变化,则只是等待两个时钟
周期准备写入数据。
DATA:16位数据,在读命令中,PHY芯片将读到的寄存器的数据写到Data中;在写命令
中,MAC将要写入寄存器的值写入Data中。
IDLE:空闲状态,此时MDIO处高阻状态。
PHY芯片是在MDC时钟的上升沿采集和输出MDIO数据的,为了保证数据的可靠传输,FPGA
在MDC的下降沿更新和采集MDIO的数据。
需要注意的是,PHY Address由PHY芯片引脚的9、10、12、13、15决定,这几个引脚一方
面表示PHY芯片的物理地址,另一方面也用于指示连接状态的LED灯,如果通过RJ45接口,连
接其它网络设备的话,虽然硬件上引脚接地,也可能出现高电平的情况。开拓者FPGA开发板
连接其它网络设备后,PHY地址为9。
PHY芯片的寄存器比较多,表 27.1.4和表 27.1.5列出了程序中用到的两个寄存器,至于
其它寄存器的详细信息可以参考RTL8201CP的数据手册。
表 27.1.4 寄存器地址1详细信息
这里我们主要读取寄存器地址1的Bit[2],来获取当前PHY芯片有没有和其它网络设备进
行连接。
表 27.1.5 寄存器地址3详细信息
寄存器地址3可以用来读取当前PHY芯片是否为RTL8201。
实验任务
本章我们要在开拓者FPGA开发板上,搭配LCD屏,完成一个综合测试实验,包括上电自检
以及14个应用功能,应用功能分别是:按键测试、LED测试、蜂鸣器、数码管、串口、红外遥
控、EEPROM、环境光、RTC实时时钟、音乐播放、ADDA、手写画笔、摄像头和网络通信,该实
验可以测试开发板的大部分功能。
硬件设计
首先,我们把综合实验的功能实现划分为两部分,“外设的驱动”和“用户界面的绘
制”。其中用户界面的绘制比较复杂,适合用软件来实现,即在嵌入式处理器Nios II中采用
C语言来设计。而驱动外设的选择性比较灵活,对于通信速率或者处理速度要求较高的外设来
说,必须使用硬件来实现,即采用Verilog HDL来设计,如OV5640摄像头图像的采集以及LCD
屏的显示;对于其它通信速率或者处理速度要求较低的外设来说,既可以使用硬件来实现,
也可以使用软件来实现。
使用硬件来驱动外设的话,会消耗比较多的逻辑资源,而采用软件驱动外设只需消耗很
少的逻辑资源,只在固化程序时,受限于EPCS Flash存储器的存储资源。Qsys系统搭建Nios
II处理器以及缩放IP核,会消耗比较多的逻辑资源,受限于FPGA逻辑资源的大小,本次实验
将部分通信速率较低的外设使用Nios II处理器来驱动,而其余的外设驱动使用硬件来实现。
在软硬件划分之后,我们来看一下整个系统的实现方案,如图 27.3.1所示。OV5640摄像
头图像采集及LCD显示对处理速度的要求较高,因此和图像显示相关的功能使用硬件来实现。
OV5640摄像头的数据先写入FIFO,然后SDRAM桥控制模块通过Qsys系统生成的SDRAM控制器,
写入显存SDRAM中。需要注意的是,OV5640摄像头的图像数据无法直接通过SDRAM控制器写入
SDRAM中,因此本次实验通过SDRAM桥控制模块和SDRAM控制器实现SDRAM的读写操作。
用户界面的绘制由Nios II处理器来完成,为了提高UI界面的开发效率,UI界面的绘制我
们将在Nios II中采用uC/GUI来实现,这样将会大大提高UI界面的开发效率以及降低UI 界面
绘制的复杂度。与此同时,显存SDRAM也用作UI绘制过程中的显存,SDRAM桥控制模块会根据
Nios II处理器的控制,从SDRAM中读出UI界面或者摄像头的图像数据,并最终转换成VIP协议
的视频流,连接至Qsys系统中的缩放IP核;图像数据经缩放IP核后,输出调整分辨率之后的
图像,然后转换成FIFO接口的数据以便于LCD驱动模块来读取,最终将图像数据显示在LCD液
晶屏上。
由系统框图可知,红外接收驱动模块、数码管驱动模块、ADDA驱动模块以及触摸驱动模
块是由硬件来实现的,Nios II处理器通过Avalon-MM端口来写入和读出模块中的数据,比如
红外接收到的数据、数码管显示的数值等。
图 27.3.1 GUI综合实验系统框图
整个系统的设计方案确定之后,我们还需要完成用户界面的设计。根据实验任务的要
求,用户界面应该包含上电自检界面、主界面以及14个应用功能的子界面。这里只列出LCD主
界面的显示图,如图 27.3.2所示:
图 27.3.2 LCD显示主界面
上面的UI设计我们将在Nios II中采用uC/GUI来实现,这部分内容会在接下来的软件设计
中讨论,我们先对照着图 27.3.1来看一下底层硬件中各个模块的设计思路。
OV5640驱动模块
OV5640驱动模块(ov5640_dri)主要负责摄像头的配置、图像采集,并输出图像数据,
其模块接口定义如下图所示:
图 27.3.3 OV5640驱动模块及其接口定义
模块的输入端为8位的图像数据(cam_data),输出端为写使能信号(wr_en)和写16位
图像数据信号(wr_data),图像数据为RGB565格式,写使能和写数据信号连接到FIFO模块
(ov5640_fifo)。除此之外,模块还输出了摄像头初始化完成信号(cam_init_done)和摄
像头的ID标志(ID_flag),这个标志可以用来判断当前连接的摄像头是否为OV5640,如果不
是的话,即没有检测到OV5640摄像头,ID_flag为低电平。
OV5640驱动模块内部例化了3个子模块,分别为OV5640配置模块
(i2c_ov5640_rgb565_cfg)、OV5640 I2C驱动模块(i2c_dri_ov5640)和图像采集模块
(cmos_capture_data),如下图所示:
图 27.3.4 OV5640驱动模块框图
图像采集模块负责将输入的8位数据转成16位的RGB565数据;OV5640配置模块寄存了
OV5640需要配置的寄存器地址和数据,在开始配置之前,先对摄像头的ID进行读取,从而判
断出开发板是否连接OV5640摄像头;OV5640 I2C驱动模块(i2c_dri_ov5640)负责驱动摄像
头的配置总线,即SCCB总线,由于本次实验增加了读取摄像头ID的功能,而SCCB接口的读操
作和IIC接口的读操作有些许差别,因此OV5640 I2C驱动模块在IIC驱动模块上做了一些修
改,即将读操作的重新开始(restart),改为先停止后开始。
需要注意的是,通过SCCB接口读取摄像头的ID时,由于配置接口的SCL和SDA信号线没有
接上拉电阻,因此在Quartus II软件中,需要将这两根信号线连接上拉电阻。
管脚设置成弱上拉的步骤如下:打开工程的管脚分配界面,在界面端口设置信息的空白处
右击,选择Customize Columns,如图 27.3.5所示:
图 27.3.5 管脚分配界面
双击左侧的Weak Pull-Up Resistor,将其添加至右侧的列表中(如果已经出现在右侧列
表中,可忽略此步骤),并点击【OK】按钮,如下图所示:
图 27.3.6 添加弱上拉的选项
此时在管脚分配界面可以看到Weak Pull-Up Resistor的选项,在对应cam_scl端口和
cam_sda端口,设置成On即可。如下图所示:
图 27.3.7 设置成弱上拉
为了适配不同LCD屏的显示,本次实验添加了缩放IP核,缩放之前的分辨率固定为
800x480,因此,摄像头输出的图像分辨率设置为800x480。
SDRAM桥控制模块
SDRAM桥控制模块(sdram_bridge_control)一方面负责从FIFO模块(ov5640_fifo)中
读出OV5640的图像数据,写入SDRAM中,写入的频率由OV5640 FIFO模块缓存的数据个数决
定;另一方面也负责从SDRAM中读出数据,读出数据的频率由fifo_2_st模块(FIFO数据转
Avalon-ST数据流模块)输出的fifo缓存个数决定。其模块接口定义如下图所示:
图 27.3.8 SDRAM桥控制模块及其接口定义
我们在前面说过,SDRAM既作为OV5640摄像头图像的显存,也作为UI界面的显存,实际上
图像显存和UI界面的显存,占用的地址空间是不一样的。当Nios II处理器发送控制信号显示
OV5640摄像头数据时,SDRAM桥控制模块读取图像的显存地址;而当Nios II处理器发送控制
信号显示UI界面时,SDRAM桥控制模块读取UI界面的显存地址,因此,当UI界面和摄像头图像
需要切换显示时,只需要修改读取SDRAM的地址,就可以实现快速的切换显示。
SDRAM桥控制模块无论读取的是摄像头图像数据的显存地址,还是UI界面的显存地址,最
终都是要经过缩放IP核改变像素的分辨率。为了方便下一级模块将16位数据转成Avalon-ST的
数据流,我们在SDRAM桥控制模块对读出的16位像素数据做了一层封装,将16位数据封装成19
位数据,这19位数据从高位到低位依次为开始包信号(source_sop)、结束包信号
(source_eop)、数据有效信号(source_valid)和16位数据(source_data)。
FIFO数据转Avalon-ST数据流模块(fifo_2_st)
FIFO数据转Avalon-ST数据流模块主要负责的是,将SDRAM桥控制模块输出的数据先写入
FIFO,然后从FIFO中读出数据时,并转成Avalon-ST格式的数据流。其模块接口定义如下图所
示:
图 27.3.9 FIFO转ST数据流模块接口及定义
该模块内部例化了FIFO模块,输入的数据之所以先经过FIFO缓存,是因为要先等待下一
级模块输出ready(准备完成)信号,才能给下一级模块输出数据,同时该模块将输入的19位
数据转成Avalon-ST的数据流格式,即开始包信号(st_source_sop)、结束包信号
(st_source_eop)、数据有效信号(st_source_valid)和16位数据(st_source_data)。
Avalon-ST数据流转VIP格式数据流
由于缩放IP模块输入的数据必须为VIP格式数据流,因此该模块主要对Avalon-ST格式的
数据流进行封装,即添加包类型以及控制包。其模块接口定义如下图所示:
图 27.3.10 ST转VIP格式模块接口及定义
我们在简介部分中有向大家介绍,VIP视频协议规定,在传输视频包之前,必须先传输控
制包,包的类型是由包的ID来指定的,包起始传输的D0[3:0]即为包的类型,用于表示后面传
输的类型为视频包、控制包或者用户包。
ST格式转VIP格式模块在传输视频包之前,先发送控制包类型(ID),ID=4’hF;然后发
送控制包的内容,即输入视频的宽度为800,高度为480,图像扫描方式为逐行扫描;接下来
发送视频包的类型(ID),ID=4’h0;最后发送视频包,即有效的图像数据。在发送包类型
(ID)的时候要拉高包开始信号(dout_startofpacket),控制包和视频包最后一位数据发
送完成后,拉高包结束信号(dout_endofpacket)。
需要注意的是,在缩放IP核的配置界面(软件设计部分会介绍)中,设置的数据位宽为
24位,即RGB888的数据格式,而输入的数据为RGB565格式,因此在输出数据的时候,各个颜
色分量的低位补1,以满足缩放IP核的格式要求,最终该模块输出的信号连接至Qsys系统的缩
放IP核模块。
VIP数据流转Avalon-ST格式数据流
缩放IP核模块输入的数据为VIP数据流格式,那么输出调整分辨率之后的数据同样也为
VIP数据流格式,因此VIP数据流转ST数据流模块实际上是对数据进行解包,其模块接口定义
如下图所示:
图 27.3.11 VIP转ST数据流模块及定义
该模块可以看成是ST格式转VIP格式模块的逆过程,将输出的Avalon-ST格式数据连接至
下一级模块。
Avalon-ST数据流转FIFO模块(fifo_2_st)
Avalon-ST数据流转FIFO模块主要将输入的ST数据流存入FIFO,根据FIFO中的数据个数来
控制读取ST数据流的速度,FIFO中的读操作接口连接至LCD驱动模块,其模块接口定义如下图
所示:
图 27.3.12 ST数据流转FIFO模块接口及定义
LCD顶层驱动模块
LCD驱动模块负责驱动LCD屏,包括MCU屏和LCD屏,其模块接口定义如下图所示:
图 27.3.13 LCD顶层驱动模块
图中有两组LCD端口信号,一组连接至顶层模块的端口信号,另一组连接至Qsys模块的端
口信号,其中Qsys模块的LCD端口信号主要用于读取LCD屏的ID,以及对MCU LCD屏进行初始
化。由于MCU LCD屏的初始化比较复杂,需要配置的寄存器非常多,所以这部分内容非常适合
软件来实现,而LCD屏的显示对处理速度要求较高,因此使用硬件来实现。
LCD顶层模块例化了以下四个模块,分别是LCD信号选择模块(lcd_signal_sel)、RGB
LCD屏驱动模块(rlcd_driver)、MCU LCD屏驱动(mlcd_driver)和时钟分频模块
(clk_div)。如下图所示:
图 27.3.14 LCD顶层模块框图
LCD信号选择模块主要对顶层模块的LCD端口信号进行连接的选择,当LCD初始化未完成
时,将顶层模块的LCD端口信号连接至Qsys模块;当LCD初始化完成,并且读到的ID为RGB LCD
屏的ID时,将顶层模块的LCD端口信号连接至RGB LCD屏驱动模块;否则连接至MCU LCD屏驱动
模块。
时钟分频模块根据输入的LCD屏的ID,选择输出不同的时钟频率,这是由于不同分辨率的
RGB LCD屏和MCU LCD屏,对应LCD的时钟频率不同。
RGB LCD驱动模块负责驱动RGB LCD屏,同时根据输入的RGB LCD屏的ID,来选择使用不同
的参数,如行同步像素数、行同步后沿像素数等。
MCU LCD驱动模块负责驱动MCU LCD屏,同样也需要根据输入的MCU LCD屏的ID,来选择使
用不同的寄存器地址与寄存器参数。
触摸屏驱动模块
触摸屏驱动模块完成对触摸屏按键的检测与触摸点坐标的获取,其模块接口定义如下图
所示:
图 27.3.15 触摸屏驱动模块接口及定义
触摸屏驱动模块支持正点原子推出的所有电阻屏和电容屏,该模块根据输入的LCD屏的
ID,来对触摸屏执行不同的配置和获取触摸点坐标。当检测到屏幕被按下后,会拉高
touch_done信号,如果touch_valid一直为高电平,则表示触摸屏一直被按下,Nios II通过
Avalon-MM接口来获取坐标值。图中page_paint_flag为Nios II输出的手写画笔界面的标志,
便于电阻屏连续检测触摸点坐标。
触摸屏驱动模块例化了三个子模块,如图 27.3.16所示。其中GT系列芯片配置模块
(touch_gt_cfg)用于初始化触摸屏(GT系列芯片包括4.3寸屏幕和10.1寸屏幕芯片),即通
过IIC接口对GT芯片进行配置,并在配置完成后拉高配置完成信号(cfg_done)。而电容触摸
驱动模块(touch_ctrl)负责控制所有电容触摸屏驱动的整个流程,包括控制触摸屏初始化
的开始、检测触摸屏是否被按下以及读取触摸点的坐标。电阻触摸驱动模块(xpt2046)负责
驱动电阻触摸屏,需要注意的是,电容触摸屏的驱动采用的是IIC协议,而电阻触摸屏采用的
是SPI协议。
图 27.3.16 触摸屏模块框图
GT系列芯片配置模块例化了以下三个模块,分别是信号切换模块(signal_switch)、
IIC驱动模块(i2c_dri_m)和i2c参数配置模块(i2c_reg_cfg),如图 27.3.17所示。
图 27.3.17 GT系列芯片配置模块框图
这里的IIC驱动模块和“EEPROM读写实验”中所使用的IIC驱动模块有些区别,在
“EEPROM读写实验”中,IIC驱动模块只支持单次读写,并不支持连续的读写。由于触摸屏的
初始化参数比较多,并且在读取触摸点坐标时也会对IIC接口进行连续的读操作,因此本次实
验在此基础上,增加了对IIC接口连续读写的功能,单次操作连续读写的次数由reg_num进行
设置,这样将会大大提高IIC读写的速度。当IIC单个地址读写完成后,IIC驱动模块会输出一
个单次完成的脉冲信号(once_done);当IIC单次操作完成后(连续地址读写完成),会输
出一个IIC操作完成的脉冲信号(i2c_done)。
IIC参数配置模块寄存了触摸屏初始化参数,由于本次试验FPGA的逻辑资源消耗很多,而
RAM资源消耗的较少,因此本次试验将GT系列的配置参数全部放在mif文件里,即存储在ROM
中。
由于电容屏驱动模块的读写操作和IIC参数配置模块的初始化操作都会用到IIC接口,因此这两个模块输出的端口信号需要先做一个选择,再连接到IIC的驱动模块中,信号选择的功
能是由信号切换模块实现的。这个模块实现的方法也比较简单,根据输入的cfg_switch信号
的高低电平进行选择。当cfg_switch为高电平时,将IIC参数配置模块的IIC操作端口信号连
接至IIC驱动模块;当cfg_switch为低电平时,将电容屏驱动模块的IIC操作端口信号连接至
IIC驱动模块。
在硬件设计部分中,主要向大家介绍了SDRAM桥控制模块的读写、缩放IP核输入数据的格
式转换与输出数据的格式转换、LCD屏幕显示驱动以及触摸驱动,而其它外设的驱动模块在前
面的实验中都有详细的讲解,这里不再重复赘述。需要说明的是,Nios II处理器通过
Avalon-MM端口来写入和读出模块中的数据,比如红外接收到的数据、数码管显示的数值等。
在介绍完各功能模块后,接下来我们在软件设计部分介绍一下如何实现UI界面的绘制,
以及如何利用触摸屏来实现与用户的交互。
软件设计
综合实验的UI界面比较复杂,包括上电自检界面、主界面以及14个应用功能子界面。为
了提高UI界面的开发效率,UI界面的绘制我们将在Nios II中采用uC/GUI来实现。Nios II除
了负责完成用户界面的绘制外,还根据触摸屏输入的触摸点坐标来实现相应的功能,为了做
到触摸点坐标的实时响应,本次实验触摸屏的驱动是在硬件中使用Verilog语言实现,Nios
II通过Avalon-MM端口来获取触摸驱动模块输出的触摸点的坐标。由于FPGA的逻辑资源有限,
Nios II处理器也负责驱动部分外设。
Qsys系统搭建
在介绍完触摸驱动模块和SDRAM桥控制模块之后,接下来我们来介绍下Qsys系统环境的搭
建,如图 27.4.1所示:
图 27.4.1 Qsys系统的搭建
Qsys系统使用的IP核,绝大多数在我们前面的实验中都有涉及,其中avalon_mm_bridge
为自定义的IP核,Nios II处理器通过Avalon-MM端口来写入和读出硬件模块中的数据;
sdram_bridge为Avalon-MM Pipeline Bridge IP核,通过SDRAM控制器来突发读写SDRAM;
pio_mdc和pio_mdio为以太网的MDC/MDIO管理接口,用于读取以太网的和其它网络设备的连接
状态;pio_cs、pio_clk、pio_mosi、pio_miso为SD卡的端口信号,用于对SD卡进行读写测
试;pio_page_paint_flag为手写画笔界面的标志,方便触摸驱动模块对连续触摸进行检测;
缩放IP核(alt_vip_cl_scl_0)用于放大和缩小图像的分辨率,以兼容不同分辨率的屏幕。
这里我们主要介绍下缩放IP核(alt_vip_cl_scl_0),其配置界面如图 27.4.3所示:
图 27.4.3 缩放IP核配置页面
Bits per symbol(symbol的位数)设置为8,Symbols in parallel(并行发送的symbol
个数)设置为3,Symbols in sequence(按顺序发送数据的个数)设置为1,则发送数据的位
宽为24(8*3)位。
由于本次实验需要根据LCD屏ID来调整缩放比,因此使能运行时控制帧输出大小。
缩放IP核固定输入分辨率为800x480,最大输出分辨率为1280x800(10.1寸RGB LCD
屏)。
输入视频在转换到Avalon-ST视频协议时不包含垂直消隐,因此勾选No Blanking invideo。
由于FPGA的逻辑资源有限,因此缩放算法这里选择对逻辑资源消耗最少的临近算法
(Nearest Neighbor),其余配置保持默认即可。
Nios II软件设计
在介绍完Qsys系统的搭建之后,最后我们再来介绍一下Nios II软件设计部分。
Nios II主要负责绘制上电自检界面、主界面以及14个应用功能子界面,除此之外,还需
要判断用户的触摸操作和部分外设的驱动。上电自检界面如图 27.4.4所示:
图 27.4.4 上电自检界面
在前面学习了uC/GUI相关的章节之后,相信对大家来说,绘制上图中的用户界面是比较
容易的。图中主要使用GUI_DispStringAt()函数绘制字符串,而对外设的测试方法,如
EEPROM、SD卡、AP3216C,则是向某个或某段地址写入固定值,然后读出数据,比较读出的值
和写入的值是否一致,如果一致则外设测试正确,否则外设测试出错。RTC实时时钟的测试方
法和其它外设有些区别,这里是通过读取RTC实时时钟的秒寄存器,如果在一秒时间内,秒寄
存器数值加1,则测试正确(如果数值为59,则加1后为0),否则测试错误。
在开发板上电自检完成后,接下来会进入主界面,主界面如图 27.4.5所示:
图 27.4.5 LCD显示主界面
这里需要强调的是,主界面的绘制并不是先绘制背景图片,再绘制应用图标和文字,而
是整个主界面是一幅图片,直接把图片绘制出来,就是上图中LCD显示的主界面。这里主要是
考虑到过多的字体和图片在最终固化程序时,会占用大量EPCS Flash的存储资源,而开发板
的片外存储资源是有限的,因此将主界面作为一副图片显示在主界面上。
接下来我们看下main函数的代码,了解下Nios II执行的过程,由于main函数的代码较
长,这里只贴上部分代码。
170 int main()
171 {
172 alt_u8 key,key_pre;
173 alt_u8 i;
174
175 alt_u8 led_button;
176 alt_u8 led_num;
177
178 alt_u8 grade=vol/8; //音频的音量级别
179 alt_u8 page_5640_done = 0; //ov5640子页面绘制完成页面
180
181 MY_LCD_Init(); //LCD初始化
182
183 IOWR_ALTERA_AVALON_PIO_DATA(PIO_OV5640_EN_BASE, 0); //显示GUI界面
184 GUI_Init(); //uC/GUI初始化
185 GUI_UC_SetEncodeUTF8(); //设置汉字编码格式
186 GUI_SetFont(&GUI_FontChinese_WRYH32);
187
188 lcdgui.width = lcddev.height;
189 lcdgui.height = lcddev.width;
190 height_ave32 = lcdgui.height/32;
191 width_ave8 = lcdgui.width/8;
192
193 switch(lcddev.id){
194 case 0x9341:{
195 IOWR(ALT_VIP_CL_SCL_0_BASE,3,320); //设置缩放后图像宽度
196 IOWR(ALT_VIP_CL_SCL_0_BASE,4,240); //设置缩放后图像高度
197 break;
198 }
199 case 0x5310:{
200 IOWR(ALT_VIP_CL_SCL_0_BASE,3,480); //设置缩放后图像宽度
201 IOWR(ALT_VIP_CL_SCL_0_BASE,4,320); //设置缩放后图像高度
202 break;
203 }
204 case 0x5510:{
205 IOWR(ALT_VIP_CL_SCL_0_BASE,3,800); //设置缩放后图像宽度
206 IOWR(ALT_VIP_CL_SCL_0_BASE,4,480); //设置缩放后图像高度
207 break;
208 }
209 case 0x1963:{
210 IOWR(ALT_VIP_CL_SCL_0_BASE,3,800); //设置缩放后图像宽度
211 IOWR(ALT_VIP_CL_SCL_0_BASE,4,480); //设置缩放后图像高度
212 break;
213 }
214 case 0x4342:{
215 IOWR(ALT_VIP_CL_SCL_0_BASE,3,480); //设置缩放后图像宽度
216 IOWR(ALT_VIP_CL_SCL_0_BASE,4,272); //设置缩放后图像高度
217 break;
218 }
219 case 0x7084:{
220 IOWR(ALT_VIP_CL_SCL_0_BASE,3,800); //设置缩放后图像宽度
221 IOWR(ALT_VIP_CL_SCL_0_BASE,4,480); //设置缩放后图像高度
222 break;
223 }
224 case 0x7016:{
225 IOWR(ALT_VIP_CL_SCL_0_BASE,3,1024); //设置缩放后图像宽度
226 IOWR(ALT_VIP_CL_SCL_0_BASE,4,600); //设置缩放后图像高度
227 break;
228 }
229 case 0x1018:{
230 IOWR(ALT_VIP_CL_SCL_0_BASE,3,1280); //设置缩放后图像宽度
231 IOWR(ALT_VIP_CL_SCL_0_BASE,4,800); //设置缩放后图像高度
232 break;
233 }
234 default: ;
235 }
236
237 IOWR(ALT_VIP_CL_SCL_0_BASE,0,1); //启动缩放模块
238 IOWR_ALTERA_AVALON_PIO_DATA(PIO_LCD_INIT_DONE_BASE,1); //初始化完成
239
240 init_tp_interrupt(); //触摸屏中断初始化
241 init_touch_key_interrupt(); //触摸按键中断初始化
242 init_uart_interrupt(); //串口中断初始化
243 init_paint_interrupt(); //手写画笔中断初始化
244 disable_paint_interrupt(); //初始化关闭画笔结束中断
245
246 gui_draw_sys_test_page(); //画系统测试界面
247 gui_draw_home_page(); //画主界面
248
249 while(1)
……
在LCD屏初始化完成后,获取到LCD屏的ID,此时根据LCD屏的ID,来设置缩放IP核输出分
辨率,使能缩放IP核并拉高LCD初始化完成信号,如代码中第193至第238行所示。接下来绘制
开发板的上电自检界面,自检界面完成后,进入主界面,如代码中第246行和第247行代码所
示。进入主界面后,接下来开始根据用户的触摸操作,来切换显示各个应用子界面,这部分
内容由while循环来完成。
我们这里只简单介绍下main函数的程序,了解下Nios程序的执行过程,还需要注意的是
当触摸屏被按下后,触摸屏驱动模块有可能检测到单个触摸点坐标触发多次,此时程序会多
次进入触摸中断函数tp_interrupt(),导致功能错误的情况。为了避免这一情况,在触摸屏
驱动模块中加入了对触摸点坐标的判断,如果触摸屏一直被按下没有松开,并且当前触摸点
坐标和上一次触摸点坐标一致的话,则忽略当前触摸点的坐标。
除此之外,新起点开发板的GUI综合程序只是在开拓者开发板GUI综合程序做了简单的修
改,因为两块FPGA开发板上的外设有所区别,因此我们在draw_page.h文件中定义了开发板的
类型,如下所示:
#define BOARD_TYPE 1 //0:新起点 1:开拓者
当BOARD_TYPE = 1时,表示执行开拓者的程序;当BOARD_TYPE = 0时,表示执行新起点
的程序。另外开拓者GUI程序改成适配新起点开发板,也不仅仅修改这一个参数,同时还需要
修改主界面的显示图片。
下载验证
接下来我们把程序下载至开拓者开发板上,验证我们所完成的GUI综合实验的功能。
要测试开拓者FPGA开发板综合实验的全部功能,大家得自备1张SD卡、1根网线、OV5640
摄像头。不过,就算没有外接这些模块,综合实验还是可以正常运行的,只是有些限制而
已。
针对LCD屏这里再补充一点,GUI综合实验必须连接LCD屏才能看到显示效果,该实验基于
图像缩放算法来适配不同分辨率的LCD屏幕,图像缩放之前的原始分辨率大小为800*480,而
2.8寸屏幕和3.5寸屏幕分辨率较低,所以缩放之后,字体的显示效果会比高分辨率屏幕的显
示效果差,为了获得更好的显示效果,建议大家连接4.3寸及以上的屏幕。
这里以4.3寸RGB LCD屏为例,大家拿出开发板,先接上12V1A电源适配器给开发板供
电,RGB LCD屏和开发板是通过40P的FPC排线相连接,如下图所示:
图 27.5.1开拓者FPGA开发板与4.3寸RGB屏连接示意图
最后,按下电源开关,给开发板上电,此时开发板右下角的蓝色电源灯会亮,同时开发
板会对EEPROM、SD卡、AP3216C和RTC做读写测试,如下图所示:
图 27.5.2 开拓者FPGA开发板开机自检界面
如果开发板在上电前连接了SD卡(SD卡槽在开发板背面),在测试成功后显示OK;如果
没有连接SD卡的话,会提示Error。
接下来进入到主界面之后,就可以通过点击屏幕的图标进行各项功能测试了。主界面如
下图所示:
图 27.5.3 RGB LCD液晶屏主界面
主界面有1个页面,总共是14个图标。每个图标代表一大功能,主界面顶部是状态栏,
用于显示“正点原子”四个字和当前时间。在任何界面下,都可以通过按下TPAD触摸按键返
回上一级,直至返回主界面。PS:TPAD就是开拓者FPGA开发板上的一个触摸按键,即右下角
的白色骷髅头。
如果大家的开发板连接了VGA显示器的话,在开发板上电之后,VGA显示器会显示出彩
条。需要说明的是,LCD屏处于任何GUI界面,VGA显示器都会一直显示彩条的,如下图所示。
图 27.5.4 开拓者开发板VGA显示画面
在介绍完主界面后,接下来我们开始介绍各个功能。
1、按键测试
点击主界面的按键测试图标,进入如图 27.5.5所示的界面:
图 27.5.5 按键测试界面
上图中,左侧的图片是我们点击按键测试后进入的子界面,可以看到,图中共四个按键
图标,分别对应开拓者开发板上的KEY0~KEY3按键。当我们按下开发板上其中的一个按键后,
界面上对应的按键图标会变成红色背景,如上图中右侧图片所示;松开按键后,按键图标又
会恢复成黄色背景。
当我们想退出按键测试界面时,只需要按下开发板上的TPAD触摸按钮即可。
2、LED测试
点击主界面的LED测试图标,进入如图图 27.5.6所示的界面:
图 27.5.6 LED测试界面
上图中,左侧的图片是我们点击LED测试后进入的子界面,图中从左往右共4个LED图标,
分别对应开发板上的DS0~DS3,图标下方的按钮用来控制开发板上的LED灯的亮灭。当我们点
击界面上的其中一个按钮后,界面上对应的LED图标会变成蓝色(如上图中右侧图片所示),
同时开发板上的LED灯会点亮;再次点击按钮后,界面上对应的LED图标恢复成白色,同时开
发板上的LED灯会熄灭。
3、蜂鸣器
点击主界面的蜂鸣器图标,进入如图 27.5.7所示的界面:
图 27.5.7 蜂鸣器测试界面
上图中,左侧的图片是我们点击蜂鸣器后进入的子界面,点击界面上的“打开”按钮,
此时可以听到开发板上的蜂鸣器在鸣叫,并且按钮会显示成“关闭”(如上图中右侧图片所
示);点击界面上的“关闭”按钮,蜂鸣器即可停止鸣叫。
4、数码管
点击主界面的数码管图标,进入如图 27.5.8所示的界面:
图 27.5.8 数码管测试界面
上图中,左侧的图片是我们点击数码管后进入的子界面,图中有三个按钮,分别是
“-”、“打开”和“+”按钮。我们点击界面上的“打开”按钮,此时可以看到开发板上的
数码管显示数字,并且界面上同样也会显示数码管显示的数字(如上图中右侧图片所示),
点击界面上的“+”和“-”按钮可以对数字进行加减,点击“关闭”按钮即可关闭数码管的
显示。
5、串口
我们开拓者FPGA开发板板载两个串口,一个是USB串口,另一个是RS232串口,我们这里
测试的是USB串口。在开始测试之前,我们需要将USB线一端连接电脑,另一端与开发板上的
USB_232口相连接,需要注意的是,大家在第一次做串口实验时,需要安装USB的串口驱动程
序,该程序位于资料盘的“6_软件资料\1_软件\CH340驱动(USB串口驱动)_XP_WIN7共用”文
件夹下。串口测试需要在电脑中打开串口调试助手才能完成通信,我们资料盘中提供了几种
调试助手,本次测试使用的是“XCOM”调试助手,该软件位于“6_软件资料\1_软件\串口调
试助手\XCOM(ALIENTEK官方推荐)”文件夹下。我们本次串口通信的波特率为115200,串口
打开和设置完成后的界面如图 27.5.9所示。
图 27.5.9 串口打开界面
不同电脑的不同USB口串口号可能会不一样,大家可以根据自己的电脑进行选择,我们这
里选择的是COM5:USB-SERIAL CH340。
点击主界面的串口图标,进入如图 27.5.10所示的界面:
图 27.5.10 串口测试界面
上图是我们点击串口后进入的子界面,我们点击界面上的“发送”按钮,串口调试助手
即可接收到开发板发送的数据,如下图所示:
图 27.5.11 串口助手接收到数据
这个时候,我们点击串口调试助手的“发送”按钮,开发板界面上会显示接收到的数
据,如下图所示:
图 27.5.12 串口测试界面
6、红外遥控
点击主界面的串口图标,进入如图 27.5.13所示的界面:
图 27.5.13 红外遥控测试界面
上图中,左侧的图片是我们点击红外遥控后进入的子界面,图中第一栏是遥控器的键
值,第二栏是遥控器的符号。此时按下遥控器的按键(使用遥控器之前需要先将遥控器后部
的塑料绝缘片拔出),界面上会显示出遥控器的键值和符号(如上图中右侧图片所示)。
7、EEPROM
EEPROM是板载的电可擦除可编程只读存储器,是一种常用的非易失性存储器,点击主界
面的EEPROM图标,进入如图 27.5.14所示的界面:
图 27.5.14 EEPROM测试界面
上图中,左侧的图片是我们点击EEPROM后进入的子界面,点击“测试”按钮后,FPGA开
始向EEPROM的地址0写入数据0,数据写完后从地址0中读取数据,并将读取的数据显示在页面
中的读数据上;接着FPGA向EEPROM中的地址1中写入数据1,同样是写完后将数据读取出来,
并显示在界面上,直至写至EEPROM的地址99开始停止(如上图中右侧图片所示)。比较写入
的数据和读出的数据是相同的,说明本次EEPROM测试成功。
8、环境光
环境光传感器(AP3216C)是一个能够测量环境光强度和距离的整合型光感测距传感器。
点击主界面的环境光图标,进入如图 27.5.15所示的界面:
图 27.5.15 AP3216C测试界面
上图是我们点击环境光后进入的子界面,界面中第一栏是环境光的强度,第二栏是距离
值。环境光传感器(U7)位于开发板的左下角位置(靠近数码管),通过增加光照和接近环境
光传感器,可以在界面上看到光照值和距离值的实时变化。
9、时钟
点击主界面的时钟图标,进入如图 27.5.16所示的界面:
图 27.5.16 时钟测试界面
上图是我们点击时钟后进入的子界面,界面中显示了日期、时间、温度信息,并且在上
方区域,有一个指针式时钟显示。
同样,按下TPAD触摸按钮返回至主界面。
10、音乐播放
点击主界面的音乐播放图标,进入如图 27.5.17所示的界面:
图 27.5.17 音乐播放界面
上图是我们点击音乐播放后进入的子界面,界面中有三个按钮,分别是“-”、“打开”
和“-”按钮。首先点击“打开”按钮,启动音频播放的功能,然后使用音频线一端连接开发
板上的LINE_IN接口,另一端与播放设备相连接(电脑或者手机的耳机接口),此时开发板上
的喇叭会播放手机或者电脑播放的音乐,如果将耳机连接至开发板上的PHONE接口,在耳机中
同样可以听到音乐。
11、ADDA
点击主界面的ADDA(模数/数模转换)图标,进入如图 27.5.18所示的界面:
图 27.5.18 ADDA测试界面
上图中,左侧的图片是我们点击ADDA后进入的子界面,板载的ADDA芯片同时具有模数和
数模转换的功能,点击“测试”按钮后,DA输出的数字量从0累加至255(如上图中右侧图片
所示),此时AD采集到的模拟电压值从0累加至约3.3V说明测试成功。
12、手写画笔
点击主界面的手写画笔图标,进入手写画笔的界面。通过在白板界面滑动手指可以看到
留下的轨迹,如图 27.5.19所示。
图 27.5.19 手写画笔测试界面
同样,按下TPAD触摸按钮返回至主界面。
13、摄像头
此应用支持的摄像头模块为ALIENTEK OV5640-AF这款500W像素的CMOS摄像头模块,在进
入摄像头应用之前,需要先将OV5640插在开发板上的Camera扩展接口上(摄像头镜头方向朝
外),点击主界面的摄像头图标,进入图 27.5.20所示的界面:
图 27.5.20 摄像头采集画面
上图是我们点击摄像头后进入的子界面,接下来就可以从界面中看到摄像头采集到的画
面,按下TPAD触摸按钮返回至主界面。
14、网络通信
此应用可以读取开发板的网口是否连接网线,点击主界面的网络通信图标,进入图
27.5.21所示界面。
图 27.5.21 以太网测试界面
上图是我们点击网络通信后进入的子界面,如果此时未连接网线的话,界面中会提示
“请连接网线!”,如果已经连接了网线,界面中会提示“Check OK!”。
猜你喜欢
- 2024-09-16 手机“满血复活”时间从数小时到几分钟 技术进步让大众告别充电焦虑
- 2024-09-16 51单片机AD模数转换,使用SPI通信方式
- 2024-09-16 正点原子STM32F4/F7水星开发板资料连载第三十五章 触摸屏实验
- 2024-09-16 正点原子开拓者 Nios II资料连载第十二章MCU TFT-LCD画板实验
- 2024-09-16 「正点原子STM32Mini板资料连载」第二十六章 触摸屏实验
- 2024-09-16 串行交互程序设计基于STM32103VET6
- 2024-09-16 Labview实验二十:触摸屏实验(labview自动触发按键)
- 2024-09-16 探索者 STM32F407 开发板资料连载第三十三章 触摸屏实验
- 2024-09-16 基于STM32设计的数码相册(stm32电子相册毕业设计论文)
- 2024-09-16 基于STM32的 RTC实时时钟屏幕显示工程
你 发表评论:
欢迎- 05-21外贸人必备8个效率外贸工具合集
- 05-21Dify实战:解除Dify知识库上传文件15MB限制的
- 05-21腾讯云国际站:怎样优化TCP传输效率?
- 05-21电脑文件怎么压缩
- 05-21手机扩容新方案,搭配腾隐P2000移动固态硬盘,还可以在再战几年
- 05-21如何安全的传输文件(2)
- 05-21前端大文件秒传黑科技!程序员集体沸腾
- 05-21128GB内存8060S最强核显!极摩客EVO-X2 Max+ 395开箱
- 最近发表
- 标签列表
-
- 电脑显示器花屏 (79)
- 403 forbidden (65)
- linux怎么查看系统版本 (54)
- 补码运算 (63)
- 缓存服务器 (61)
- 定时重启 (59)
- plsql developer (73)
- 对话框打开时命令无法执行 (61)
- excel数据透视表 (72)
- oracle认证 (56)
- 网页不能复制 (84)
- photoshop外挂滤镜 (58)
- 网页无法复制粘贴 (55)
- vmware workstation 7 1 3 (78)
- jdk 64位下载 (65)
- phpstudy 2013 (66)
- 卡通形象生成 (55)
- psd模板免费下载 (67)
- shift (58)
- localhost打不开 (58)
- 检测代理服务器设置 (55)
- frequency (66)
- indesign教程 (55)
- 运行命令大全 (61)
- ping exe (64)
本文暂时没有评论,来添加一个吧(●'◡'●)