lxynjt.hnie.edu.cnlxynjt.hnie.edu.cn/__local/c/89/d0/ad03786f1472a7a741…  · web...

Click here to load reader

Upload: others

Post on 03-Nov-2020

17 views

Category:

Documents


0 download

TRANSCRIPT

前 言

南京润众科技有限公司是专业从事通信工程与电子信息专业实验教学设备研发、生产、销售和技术服务的高新技术企业。公司坐落在著名的历史文化名城--中国南京市,枕紫金、挽玄武,踞光华门之宝地、映秦淮河之碧波,依托地区教育,信息,产业优势,经过润众人不懈的努力,公司已经发展成为国内知名的通信教育综合服务厂商。

公司主要生产《通信原理系列》《高频电子系列》《移动通信系列》《程控交换系列》《信号与系统系列》《微波与射频通信系列》《数字电路系列》《软件无线电系列》《课题设计系列》《现代通信网络实验系统》《实验台系列》《物联网》《虚拟仪器系列》《DSP与通信应用系列》《通信仪表设备》等十六大系列四十多种型号的通信与电子教学设备,品种之多样,型号之齐全,堪称通信电子教仪生产公司之最。

近年经公司精心研发,又新推出了通信实训系统九大系列产品,分别为《RZ-NGN通信网络综合实训系统》、《基于4G的移动互联网实训系统》、《3G移动通信系统》、《NGN软交换实训系统》、《SDH光传输与EPON光接入系统》、《开放实验室管理系统》、《虚拟实验室系统》、《可视通信系统》。

专家教授领其衔,栋梁英才集于斯。公司拥有一支由一线资深教授、高级工程师、高级实验师和年轻硕士、博士组成的研发队伍,研发能力强,产品科技含量高。可为各类院校提供个性化服务,量身定做各种适用的通信电子教学实验设备。公司设有专业的焊接生产调试基地,生产设备良好,通过严格的生产调试工艺,保证产品质量稳定可靠。经过公司多年信誉积累,销售及服务网络遍及全国,产品已在超过200百所高校投入使用,为各高校的实验教学发挥了重大作用。

润众公司任重道远,公司非常感谢教育界同仁多年来对南京润众科技的关心和大力支持,热忱欢迎广大用户莅临公司参观、考察、指导。我们期待您的到来!

技术支持及联系方式: 电 话: 025-84585075

84585951 68550915

传 真: 025-84585075

E-Mail: [email protected]

Http:// www.njrzkj.com

润众教材编写组2017年01月版

目 录

目 录3

实验一 第一个SOPC实验—hello world!4

实验二 IO输出控制实验18

实验三 中断实验32

实验四 SPI接口以及SD卡编程37

实验五 数码管驱动CH45142

实验六 字符屏LCD1286445

实验七 基于W5500的SOPC网口通信49

实验一 第一个SOPC实验—hello world!

本实验带领同学们搭建一个最简单的SOPC环境,并在此环境(Nios II)上进行硬件配置和软件开发。我们通过用“hello world”来进行SOPC的第一个演示,通过这个演示我们可以对如何构建基于Qsys的SOPC有一个初步的认识。本教材中我们使用的开发软件是Quartus II 13.1 (64-bit),FPGA芯片型号是Altera Cyclone IV EP4CE22E22C8N。

1、 硬件设计

Nios II的设计分为两部分,硬件设计和软件设计。这里的硬件设计是指利用Quatus II和其集成的Qsys工具设计一个能满足应用要求的软核。

1. 设计目标

基于Qsys和Nios II系统设计完成FPGA平台上的“Hello world”功能。

2. FPGA项目搭建和引脚分配

打开Quartus II 13.0(64-bit),新建一个工程,File -> New Project Wizard…,忽略Introduction,之间单击 Next> 进入下一步。分别设置工程工作目录、工程名称。这里需要注意的是工程工作目录中请使用英文,不要含有空格等。设置好后如图1.1所示。然后进行下一步。

图 1.1 项目路径和项目名称

添加已经存在的文件,这里我们没有需要添加的文件,直接单击 Next> 进入下一步。进行器件设置。我们使用的Cyclone IV家族的EP4CE22E22C8N 芯片,选择好后直接进入下一步。进行EDA工具设置,由于我们工程中不进行仿真等,故不进行设置,如果需要进行ModelSim仿真,则在Simulation行中,选择Tool Name 为ModelSim-Altera(这里根据所安装的ModelSim版本进行选择),Format(s)选择为Verilog HDL(这里也是根据所掌握的硬件描述语言进行选择)。点击 Next> ,进入了Summary(摘要)页面,然后单击 Finish 完成即可。

图1.2芯片选择

新建一个Verilog HDL文件或者Schematic文件。单击 File -> New..,选择Design Files中的Verilog HDL FILE,单击OK即可。

仔细阅读原理图,然后根据原理图新建一个模块名和项目名一样的模块,使得该模块包含所有原理图中出现的引脚(包括FLASH芯片EPCS16的引脚),以便后面使用。然后保存该文件并重命名成和项目名一样。如图1.3所示。

图1.3顶层模块

如有需要,可以添加锁相环,将16.384Mhz基础时钟倍频至65.536Mhz。Tools->MegaWizard Plug-In Manager->Create a new custom megafunction variation ,选择ALTPLL,命名为pll4,inclk0 input 设置为16.384Mhz,然后一路next,直到设置c0-Core,按照图1.4所示设置,设置完后直接点Filish。

图1.4 锁相环设置

然后就可以在主模块中添加锁相环模块了。

再添加一些其他的功能信号,如开机复位等,参考工程中的按键模块可以不用添加。

编译后就可以使用Assignments/Pin Planner 工具进行引脚分配了。如图1.5所示。

图1.5 引脚分配

我们使用的FLASH芯片EPCS16的引脚分配需要稍作简单的配置。在后面实验里需要将EPCS的相关引脚引出,打开"Assignments/Device.../Device and Pin Options"选项, 在Dual-Purpose Pin选项中将所有相关EPCS管脚的信号设置成“Use as regular I/O"。

图1.6 Dual-Purpose Pin

我们将以上完成的部分备份一下,放在./history/save1文件夹中。同学们可以直接将这个文件夹中的项目拿出来使用,没必要浪费太多的时间在项目搭建和引脚分配上。接下来正式介绍软核的设计。

3. 使用Qsys工具进行软核设计

打开Tools->Qsys,弹出Qsys工具。如图1.7所示系统已经默认添加clk模块。为了完成最小NIOS系统,我们还需要添加Nios II Processor、On_ChipMemory(RAM or ROM)、JTAG UART、System ID Peripheral这4个模块。

图 1.7 Qsys设计工具界面

首先熟悉一下 Qsys 的界面。左面Component Library,是系统提供的元件库,里面有一些构成处理器的常用模块。右面是已经添加到系统的模块,也就是说,Nios II 软核处理器是可以定制的,根据具体需要来。我们在Component Library中搜索Nios II Processor,双击即可进行配置。首先需要选择的是Nios II 核心的类型。Nios II 软核的核心共分成三种,为e型、s型以及f型。如图1.8 所示。

图1.8 Nios II Processor设置一

这里简单介绍一下:e型核占用的资源最少,功能也最简单,速度最慢。s型核占用资源其次,功能和速度较前者都有所提升,f型核的功能最多,速度最快,相应的占用资源也最多,选择的时候根据需求和芯片资源来决定,我们选择s核。然后单击 Finish,结束当前配置。

下面添加片内存储器,在元件库中搜索 On Chip Memory。双击进行设置。我们主要设置Size中的Data width和Total memoy size。Data width设置的是数据位宽,这里我们设置成16位。Total memoy size设置的是片内资源的大小,需要根据芯片资源进行合理设置,这里我们设置为10240 bytes。单击 Finish,结束当前配置。

接着添加Jtag下载调试接口。在元件库中搜索 jtag uart。双击进行设置。由于我们的系统没有特殊要求,因此这里我们选择默认配置即可。单击 Finish 结束当前配置。

最后添加系统ID模块。系统ID是系统与其他系统区别的唯一标识。在元件库中搜索 system id peripheral,双击进行设置。这里我们随便进行设置,如设置为0x12345678。单击 Finish,结束当前配置。

以上设置好后,如图1.9所示。

图1.9 添加4个基础模块

添加完四个模块后,需要进行的连线,即将右面 Connections栏目中的相关线通过设置节点进行连接。这里有一个连线的规则:如果是存储器这类的 IP 核,需要将其 Slave 端口同 nios2_qsys 的 data_master 和 instruction_master 相连,而其他非存储器 IP 核则只需连接到 Nios II 的 data_master 即可。 可以参照 Altera 的官方文档《 Nios II Processor Reference Handbook》对 Nios II 的指令和数据总线的描述。

首先所有模块的clk和复位reset需要连接起来。然后片内存储器On-Chip Memory的s1和处理器nios2_qsys的data_master和instruction_master相连。JTAG调试模块jtag_uart的avalon_jtag_slave和处理器nios2_qsys的data_master相连。系统ID模块sysid_qsys的control_slave和处理器nios2_qsys的data_master相连。最后,处理器nios2_qsys的中断和jtag_uart的中断相连接。最终的完成效果如图1.10所示。

图1.10 Qsys Connections完成效果

首先双击nios2_qsys,进入处理器设置模块。在Core Nios II栏目下,将Reset vector memory 和 Exception vector memory 设置为onchip_memory.s1,如图1.11所示。然后双击clk,将时钟配置成65536000Hz(未使用锁相环的情况下配置成16384000Hz)。

图1.11 Nios II Processor设置二

然后,单击 System -> Assign Base Addresses,这时候我们会发现下部Messages窗口中原先的错误全部没有了,变为0 Errors,0 Warnings。如果不是这个结果,返回去按步骤检查。

接着,单击 File -> Save,进行保存,这里我们保存文件名为niosii_kernel.qsys。

最后,选择Generation选项卡,设置Create simulation model为None,然后单击下面的Generate,进行生成。时间较长,大家耐心等待。生成完成后单击close即可,然后关闭Qsys回到Quartus II界面。

单击 Project -> Add/Remove Files in Project…,单击File name后面的浏览按钮,选择.qsys文件,单击Add将其添加进来,然后单击OK。添加Nios II模块。

现在进行编译即可。单击Processing -> Start Complilation,进行编译。编译时间过长,大家耐心等待,通过后,使用Tools->Programmer将sof文件下载到FPGA中,具体的下载过程,这里就不在追溯,大家可以参考其他资料学习。注意一点:下载后,不要断电,否则下载的东西全部丢失,这是由FPGA特点决定的,大家可以自己了解一下。

我们将以上完成的项目备份一下,放在./history/save2文件夹中。同学们可以将这个文件夹中的项目拿出来参考一下。硬件部分到此结束,下面进行软件部分设计。

2、 软件设计

这里的软件设计是指使用Nios II 13.0 Software Build Tools for Eclipse工具搭建c环境,编译下载。

打开Tools->Nios II 13.0 Software Build Tools for Eclipse,首先,需要进行Workspace Launcher(工作空间)路径的设置,接触过Eclipse的朋友都熟悉,自己设定即可,需要注意的是路径中不要含有空格等,然后单击OK即可。

图1.12 Workspace Launcher(工作空间)路径的设置

新建工程。单击File -> New -> Nios II Application and BSP from Template,弹出Nios II Application and BSP from Template对话框。先选择对应的SOPC系统,单击SOPC Information File name后面的浏览按钮,选择我们之前硬件部分做好的软核文件,后缀名为.sopcinfo,这里一定要注意,选择的文件一定要对应起来,否则会因为软硬不匹配导致系统失败。我这里选择的niosii_kernel.sopcinfo,然后系统会自动读取CPU name,我们不用再进行设置,下面填写Project name,这里我们填写为helloword,工程模板(Project template)使用默认,如图1.13所示。然后单击Finish完成即可。

图1.13 Nios II Application and BSP from Template设置

这时候会在左侧的Project Explorer中生成两个工程文件,如图1.14所示。

图 1.14 生成的工程文件

我们双击打开helloword工程下面的hello_word.c文件,就可以看到c语言代码,我们添加一句printf("Hello word! \n");  然后,右击我们的helloword工程,选择Nios II -> BSP Editor,进入Nios II BSP Editor配置界面。我们主要在main选项卡下hall中进行配置。具体配置内容见图1.15。然后单击Generate,生成BSP库。生成完成后,单击Exit退出即可。

图 1.15 Nios II BSP Editor配置

下面我们编译helloword工程。右击选择Build Project。第一次编译的话,时间也会比较常,耐心等待一下。

编译完成后,右击工程,选择Run As -> Nios II Hardware,弹出Run Configurations对话框,默认Project选项卡中Project name和Project ELF file name应该都是有内容的,没有的选一下。然后进入Target Connection选项卡,Connections中如果没有东西的话,单击右侧的Refresh Connection来查找我们的下载器,查找后我们单击System ID Prroperties…,进行系统ID检测,检查是否是我们之前设置的ID号,无误后点击Apply,然后再点击Run,这是程序会被自动下载,最终在Nios II Console选项卡中会显示下载完成后程序运行的结果,即发回两句话,具体效果如图1.16所示。

图 1.16程序运行效果

至此,整个实验结束。对于初次接触sopc的同学而言,过程有点复杂,实验中需要保持认真和耐心的心态。

实验二 IO输出控制实验

上一个实验中,我们掌握了怎样搭建一个SOPC最小系统。本实验将在上一实验的基础上添加一个IO输出控制模块,同时我们将介绍如何将SOPC的程序固化到FLASH中,使得程序能够断电保留。

1、 硬件设计

根据实验一的过程,重新搭建一个一样工程,并将该工程命名为sopc2_pio_out,使用Qsys工具添加实验一介绍的4个核心模块。如文件夹./history/save3中工程所示。并根据下面的介绍,添加IO模块和FLASH模块。

1. 设计目标

基于Qsys和Nios II系统设计完成IO输出控制和程序固化。

2. 添加IO模块和FLASH模块

在Project Navigator 的FILE栏找到niosii_kernel.qsys文件,并双击之,即可弹出Qsys界面。从Qsys界面左上角Component Library查找窗口输入pio找到“PIO”后双击。在Basic Settings的Width选项中输入8,Direction选择Output,也就是默认值,点击Finish。在Export栏输入pio_0_pins。连接Connections的pio_0模块的左边三个节点。完成后如图2.1所示。

图2.1 添加pio模块

 在Component Library中查找并添加EPCS/EPCQx1 Serial Flash Controller,这里我们不用进行任何设置,直接单击Finish完成即可。在Export栏输入epcs_flash_controller_0_external。连接Connections的左边5个节点。完成后如图2.2所示。

图2.2 添加flash模块

将flash的基地址base锁定为0x0000,点击小锁,使得小锁变成闭合状态。然后顺手分配一下中断号(IRQ)。如图2.3所示。

图2.3配置FLASH地址以及中断号

在FPGA芯片的使用中,软硬件程序可通过JTAG口下载进FPGA芯片中,程序可立即执行,并且在掉电后程序丢失。为了避免这种情况的出现,可使用串行FLash芯片EPCS系列,EPCS系列芯片有EPCS1、4、16、128,本实验系统使用的是EPCS16,提供16MBit的ROM空间。软硬件程序可通过JTAG口下载进EPCS芯片中。它实际上是执行EPCS控制器的片内ROM的代码(即bootloader),把EPCS中程序的搬到RAM中执行。FPGA的配置数据从EPCS偏移为0的地址开始存放,紧挨着配置数据后面是一个32位的整数,指示程序段的长度,接着是一个32位的地址,指示程序执行时该程序段的地址,我们把这个长度和地址一起称为"程序记录","程序记录"随后就是程序段映象。为了达到上电后程序能立即运行,必须在Qsys系统中,将程序的复位地址设为EPCS的地址,这样上电后才能执行程序。

双击nios2_qsys,进入处理器设置模块。在Core Nios II栏目下,将Reset vector memory 和 Exception vector memory 设置为epcs_flash_controller_0.epcs_control_port,如图2.4所示。

图2.4 Nios II Processor设置三

然后,单击 System -> Assign Base Addresses,这时候我们会发现下部Messages窗口中原先的错误全部没有了,变为0 Errors,0 Warnings。如果不是这个结果,返回去按步骤检查。

接着,单击 File -> Save,进行保存,这里我们保存文件名为niosii_kernel.qsys。

最后,选择Generation选项卡,设置Create simulation model为None,然后单击下面的Generate,进行生成。时间较长,大家耐心等待。生成完成后单击close即可,然后关闭Qsys回到Quartus II界面。

在Quartuss II程序中,添加niosii_kernel模块新增加的几个引脚。

现在进行编译即可。单击Processing -> Start Complilation,进行编译。编译时间过长,大家耐心等待,通过后,使用Tools->Programmer将sof文件下载到FPGA中。注意一点:下载后,不要断电。

我们已经将以上完成的项目备份了,放在./history/save4文件夹中。同学们可以将这个文件夹中的项目拿出来参考一下。硬件部分到此结束,下面进行软件部分设计。

2、 软件设计

现在开始介绍通过Eclipse来操作Nios II的IO口。

打开Tools->Nios II 13.0 Software Build Tools for Eclipse,路径设置好后单击OK即可。

图2.5Workspace Launcher(工作空间)路径的设置

新建工程。单击File -> New -> Nios II Application and BSP from Template,弹出Nios II Application and BSP from Template对话框。选择niosii_kernel.sopcinfo填写Project name,这里我们填写为pioout,工程模板(Project template)使用默认,如图2.6所示。然后单击Finish完成即可。

图2.6 Nios II Application and BSP from Template设置

漫长的等待后,我们打开 system.h 文件,system.h 文件对比之前的多了如图2.7所示的内容,这部分内容就是我们Qsys设计软核中构建PIO_0模块。我们将要用到的是PIO_0_BASE,它是 PIO_0 所有寄存器的首地址。

图2.7 System.h文件中Pio_0的描述

下面,我们就来运用这个首地址来进行编程,完成对8个IO口的控制。右击pioout,选择new->Source Folder,新建一个分组driver。然后右键driver,选择new->Head File,新建一个头文件命名为pio_out.h。再右键driver,选择new->Source File,新建一个c文件命名为pio_out.c。如图2.8所示。

图 2.8添加pio_out.h文件

根据根据芯片手册《 n2cpu_Embedded Peripherals.pdf》version8.1的9-5页和9-6页,如图2.9所示。我们仔细阅读这一个表格,弄清每个寄存器的偏移量offset。第一项是数据 data,第二项是 IO 口方向,第三项是中断控制位,第四项是边沿控制位。他们每一项都有 n 位,这个 n 就是我们在软核构建中PIO的宽度(width)。我们之前设置为 8,那这里 n 等于8。

System.h文件中的基地址PIO_0_BASE加上偏移量就是图2.9中每个寄存器的最终地址了。我们定义一个宏,#define IOOUT ((PIO_STR *) PIO_0_BASE),其中PIO_STR是PIO寄存器构成的结构体。

编写好pio_out.h文件后,保存一下,然后编写pio_out.c文件。Pio_out.c文件十分简单,仅仅附上代码,不赘述。

图2.9芯片手册PIO Core

pio_out.h和pio_out.c源码:

/** pio_out.h** Created on: 2017-1-12* Author: whr*/#ifndef PIO_OUT_H_#define PIO_OUT_H_/*--------------------------------------------------------------* Include*-------------------------------------------------------------*/#include "system.h"

/*--------------------------------------------------------------* Define*-------------------------------------------------------------*/#define _IOOUT

/*--------------------------------------------------------------* Peripheral registers structures*-------------------------------------------------------------*/typedef struct{ unsigned long int DATA; unsigned long int DIRECTION; unsigned long int INTERRUPT_MASK; unsigned long int EDGE_CAPTURE;}PIO_STR;

/*--------------------------------------------------------------* Peripheral declaration*-------------------------------------------------------------*/#ifdef _IOOUT#define IOOUT ((PIO_STR *) PIO_0_BASE)#endif /*_IOOUT*/

/*--------------------------------------------------------------* *-------------------------------------------------------------*/int pioouttest(void);

#endif /* PIO_OUT_H_ */

/** pio_out.c** Created on: 2017-1-12* Author: whr*//*-------------------------------------------* Include*-------------------------------------------*/#include "pio_out.h"/** === FUNCTION ============================* Name: pioouttest* Description:* ===========================================*/#include int pioouttest(void){ while(1){ IOOUT->DATA = 0xaa; IOOUT->DATA = 0x55; } return 0;}

我们双击打开pioout工程下面的hello_word.c文件,去掉 printf("Hello from Nios II!\n");然后添加调用函数pioouttest。右击pioout工程,选择Properties,点击Nios II Application Properties左边的三角,点击弹出的Nios II Application Paths ,在右侧界面Application include directories框中添加头文件路径driver.

图2.10 添加头文件路径

右击我们的helloword工程,选择Nios II -> BSP Editor,进入Nios II BSP Editor配置界面。我们主要在main选项卡下hall中进行配置。具体配置内容见图1.15。然后单击Generate,生成BSP库。生成完成后,单击Exit退出即可。

图 2.11 Nios II BSP Editor配置

下面我们编译工程。右击工程选择Build Project。编译完成后,右击工程,选择Run As -> Nios II Hardware,弹出Run Configurations对话框,默认Project选项卡中Project name和Project ELF file name应该都是有内容的,没有的选一下。然后进入Target Connection选项卡,Connections中如果没有东西的话,单击右侧的Refresh Connection来查找我们的下载器,查找后我们单击System ID Prroperties…,进行系统ID检测,检查是否是我们之前设置的ID号,无误后点击Apply,然后再点击Run,这时程序会被自动下载。

下载完程序后,使用示波器观察SOPC实验开发模块的前面8个铆孔,可以看到大约8Mhz的信号。这个信号就是NIOS II程序产生的。如图2.12所示。

图2.12 IO口输出波形

3、 固化程序

由于我们没有将程序烧写到flash中,所以断电后程序还是会消失。接下来我们介绍如何将程序烧写到flash(epcs16)中。

我们在利用Qsys设计软核的时候已经添加了EPCS模块了,并在Quartus II的顶层设计中分配了这几个引脚。如图2.2、图2.3、图2.4所示。

我们先断电,利用Quartus II的Programmer重新烧写sof文件。如图2.14。右键pioout工程,打开NIOS II/Flash Programmer界面,再File/New,按图2.13所示选择SOPC Information File,也就是Quartus II生成的niosii_kernel.sopcinfo文件,点击OK。

点击Connections按钮,出现界面后,点击Refresh Connections后确认与已经上电的目标板可以连接上。

图2.13Flash Programmer设置

图2.14烧写sof文件

在NIOS II/Flash Programmer界面的"Files for flash conversion"框中分别添加FPGA的.sof文件和NIOS II的软件目标文件.elf文件,系统会自动合成这两个文件下载。

图2.15添加下载文件

最后在NIOS II/Flash Programmer界面点击START按钮,稍等片刻,即可将程序和FPGA配置一起下载到EPCS中。下载完成后,重启实验箱,程序即可运行。

至此,整个实验结束。有时Nios II会存在一些bug,使用起来非常不方便,每次编译完硬件程序,首先将BSP重新生一下 ,还有一个值得提醒的是,需要执行一下下面的操作,右键点击工程,选择Index>rebuild一下,然后再编译整个工程。

如果实验过程中出现下载失败或者Error 等问题,建议从实验一开始重新操作一遍,研究工程搭建、编译、下载的过程,了解其中工作原理,从原理上查找问题的原因。实验一和实验二十分重要,也十分基础,如果这两个实验没有顺利完成,笔者不建议贸然进行后面的实验。另外在后面的实验中,我们不再详细介绍操作步骤。

实验三 中断实验

ISR(Interrupt Service Routine)中断服务函数是为硬件中断服务的子程序。NIOS II处理器支持32个硬件中断,每一个使能了的硬件中断都应该有一个ISR与之对应。中断发生时,硬件中断处理器会根据检测到的有效中断级别,调用相应的ISR为其进行中断服务。

要完成硬件中断工作,我们需要做两件事。 第一, 注册中断函数ISR,它的函数原型如下所示: int alt_irq_register(alt_u32 id, void* context, void(*handler) (void*,alt_u32));其中id是指中断优先级,即所注册的ISR是为哪个中断优先级的中断服务的。中断优先级在Qsys中分配的。

1、 硬件设计

本实验需要在Qsys中添加中断功能的IO口。

1. 设计目标

基于Qsys和Nios II系统设计完成FPGA平台上的外部中断功能。

2. FPGA项目搭建和引脚分配

使用前面实验用的通用模块即可,添加按键功能。实验开发模块上按键采用的是3*3矩阵按键,所以我们事先用Verilog语言做了一个驱动。这个驱动将矩阵按键转化为单体按键,以降低实验的复杂度。

代码如下:

/////////////////////////////////////////////////////////按键驱动///////////////////////////////////////////////////////

wire [3:0]keyboard_val_sig ;matrixKeyboard_drive matrixKeyboard_drive_inst( .i_clk(clk) , // output i_clk_sig .i_rst_n(reset_n) , // output i_rst_n_sig .row({KEY1 ,KEY2 , KEY3 }) , // output [2:0] row_sig .col({KEY4 ,KEY5 , KEY6 }) , // intput [2:0] col_sig .keyboard_val (keyboard_val_sig ) // output [3:0] );wire [8:0] key_direct;assign key_direct[0] = keyboard_val_sig ==0;assign key_direct[1] = keyboard_val_sig ==1;assign key_direct[2] = keyboard_val_sig ==2;assign key_direct[3] = keyboard_val_sig ==3;assign key_direct[4] = keyboard_val_sig ==4;assign key_direct[5] = keyboard_val_sig ==5;assign key_direct[6] = keyboard_val_sig ==6;assign key_direct[7] = keyboard_val_sig ==7;assign key_direct[8] = keyboard_val_sig ==8;

3. 软核设计:添加io中断模块

按照如图3.1、图3.2所示添加IO中断模块。Width设置为8,Direction为input,上升沿捕捉,Generate IRQ选中,中断号设置为2;export设置为pio_1_pins,连接左边三个节点。

图3.1 添加IO中断模块

图3.2连接节点

回到Quartus II界面,修改Nios模块。

2、 软件开发

按照实验二的描述搭建工程,然后我们打开system.h,里面有一个pio_1 configuration,有两个比较重要的宏定义:

#define PIO_1_BASE 0x1800

#define PIO_1_IRQ 2

接下来利用这两个宏定义搞出一些事情来。

在前面的pio_out.h文件里面添加如下部分:

将pio_out.c文件修改成如下:

/*

* pio_out.c

* Created on: 2017-1-13

* Author: whr

*/

/*-------------------------------------------

* Include

*-------------------------------------------*/

#include "pio_out.h"

#include

#include

#include "sys/alt_irq.h"

/*----------------------------------------------------

* Variable

*----------------------------------------------------*/

int key_flag = 0;

/*

* === FUNCTION ====================================

* Name: ISR_key,中断处理函数

* Description:

* ===================================================

*/

void ISR_key(void * context,unsigned long id)

{

key_flag = ~key_flag;

}

/*

* === FUNCTION =====================================

* Name: init_key,中断初始化函数

* Description:

* ====================================================

*/

int init_key(void)

{

KEY->INTERRUPT_MASK = 0xff;

KEY->EDGE_CAPTURE = 0xff;

return alt_irq_register(PIO_1_IRQ,NULL,ISR_key);

}

/*

* === FUNCTION =====================================

* Description:

* ====================================================

*/

int key_deal(void)

{

if(!init_key()){

printf("register successfully!\n");

}

else{

printf("Error: register failure!\n");

}

while(1){

if(key_flag){

IOOUT->DATA = 0xff;

}

else{

IOOUT->DATA =0x00;

}

}

return 0;

}

这个程序没有对按键进行防抖处理,只是为了展示外部中断处理的操作过程,如想作为项目中应用必须加入按键防抖处理,在此不具体说明。

修改完后,在main函数中调用key_deal()函数即可。这个程序通过外部按键来产生中断,所以当按一下按键时,就会产生了一个脉冲,这时就会进入中断函数ISR_key()。在中断函数ISR_key()中,我们对key_flag进行取反。而在函数key_deal()中,我们不断地进行查询,当key_flag为1时,IOOUT->DATA = 0xff,也就是输出高电平;当key_flag为0时,IOOUT->DATA =0x00,这时,输出低电平电平。

KEY->INTERRUPT_MASK = 0xff;这个语句的目的是,使能中断位,实验二我已经讲过了,PIO模块对应的结构体中的INTERRUPT_MASK是中断控制寄存器的内存映射,当该位置1时,允许中断,否则,禁止中断。return alt_irq_register(PIO_1_IRQ,NULL,ISR_key)语句,用它来完成中断的注册,KEY_IRQ来自system.h,ISR_key是ISR函数指针。用return返回为了在函数key_deal()中判断注册是否成功,如果成功返回0,非0表示注册失败。

最后,再简单总结一下中断需要注意的地方,大家知道中断程序主要处理一些实时性比较强的操作,因此不能在中断程序中进行等待或者阻塞性的操作。所以,尽量保持中断服务程序精简,不要在中断程序中处理复杂的处理,比如浮点型操作,printf函数等。

实验四 SPI接口以及SD卡编程

通过本章的实验,我们将了解并掌握基于SOPC平台的spi接口SD卡初始化以及数据读写的方法。

 一 、 SPI接口和SD卡简介

SPI(Serial Peripheral Interface--串行外设接口)总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息。常见的外围设备有SD卡、FLASHRAM、网络控制器、LCD显示驱动器、A/D转换器和MCU等。SPI接口一般使用4条线:串行时钟线(SCLK)、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOSI和低电平有效的从机选择线NSS(有的SPI接口芯片带有中断信号线INT、有的SPI接口芯片没有主机输出/从机输入数据线MOSI)。

SD 卡数据接口有 SDIO 和 SP I两种模式 ,相对于 SDIO 模式 ,SPI 模式可以简化主机设计 ,降低成本 。SPI模式下的SD 卡驱动程序在 SD 卡的 R1 应答模式和处理器进行 SPI 总线通信的通信协议的基础上实现的。

二 、 硬件设计

在SPI设计中,接口信号如下:

(1)MOSI – 主器件数据输出,从器件数据输入

(2)MISO – 主器件数据输入,从器件数据输出

(3)SCLK –时钟信号,由主器件产生,一般不超过主设备主频的1/2

(4)CS– 从器件使能信号,由主器件控制,有的IC会标注为NSS

在点对点的通信中,SPI接口不需要进行寻址操作,且为全双工通信,显得简单高效。

在多个从器件的系统中,每个从器件需要独立的使能信号,硬件上比I2C系统要稍微复杂一些。

图4.1 SPI多个从器件总线结构

3、 SPI时序:

各个工作模式的不同在于SCLK不同, 具体工作由Clock Polarity,Clock Phase决定

CPOL: (Clock Polarity),时钟极性

当CPOL为0时,时钟空闲idle时候的电平是低电平;

当CPOL为1时,时钟空闲idle时候的电平是高电平;

CPHA:(Clock Phase),时钟相位

当CPHA为0时,时钟周期的前一边缘采集数据;

当CPHA为1时,时钟周期的后一边缘采集数据;

CPOL和CPHA,分别都可以是0或时1,对应的四种组合就是:

图4.2 CPOL和CPHA的四种组合

四、Qsys设计

因为本实验使用的ram可能要比前面的实验多,所以在实验前先将opchip_memory调大一点,这里我们将数据位宽设置为32,大小设置为45000bytes。

在元件库中搜索 SPI。选择SPI(3 Wire Serial),双击进行设置。Type分为Master 和 Slave,本实验SOPC作为主设备,选择Master。Data width设置的是数据位宽,这里我们设置成8位。根据SD卡得时序,Shift direction选择MSB first高位在前。空闲时钟为高电平,时钟周期的第二边沿采集数据,所以Clock Polarity,Clock Phase都选择1.单击 Finish,结束当前配置。

图4.3 SPI配置

然后添加一个宽度为1的输出IO口,命名为SPI_CS,作为片选控制信号。

五、 SD卡通信过程

SD卡比较复杂,篇幅有限,这里仅简单介绍其工作方式。详细命令描叙等请查阅文档《SD卡操作》。

SPI 模式下 SD 卡总 线采用 的是一种主从问答式协议 。 首先主机端发送命令 Co mmand ,SD 卡应答主机发送 Respo nse 。 SPI 模式命令集是 SD 模式命令集的子集 ,其命令 Co mmand 格式是确定的,如表2所示:

SD 卡的应答有多种 ,有 R1 , R1 b , R2 , R3 等 。 在这些应答中 R1 居多 ,其格式如图 2 所示 。 R1 长度为 1 字节 ,最高位 ( MSB) 始终为“0” ,如 果产生错误则 在其他相应位置“1 ”。

SD 卡初始化及实现 SD 卡与 MMC 卡的兼容对 SD 卡进行初始化操作,是 SD 卡进行正常数据读写的前提 。 SD 卡插入后 ,默认进入 SD 模式 ,等待电压稳定需上电延时 ( Power up Time) 250 ms 及等待至少 74 个时钟周期 ( Supply Ramp up Time) 。 将时钟频率设置为 1 00~ 400 k Hz ,置低片选信号 CS ,发送CMD0 。 如 果 收 到 应 答信号 01 H , 则 表 示 SD 卡 进 入SPI 模式 。由于 SD 卡兼容 MMC 卡 ,都可以采用 SPI 总 线驱动 ,因此为实现 SD 卡与 MMC 卡的 兼容性 ,首先发送ACMD41 ,能够正确应答则识别 为 SD 卡 ,否 则 再发送CMD1 ,能够正确应答则识别为 MMC 卡 。初始化过程如下图所示 。 初始化完成后 ,需将时钟频率重新设置 。

SD 卡的读写以 块为 单位 。 初 始 化完 成后 , 使用 CMD16 设 置SD卡 读 写 块 长 度, 发 送CMD1 8 或 CMD25 进行 SD 卡的连续多块读或写操作 。读取连续多块数据向 SD 卡发送 CMD1 8 ,收到有效应答信号 0x00 后 ,开始接收数据 。 每块数据由 起始令牌 (0xFE) 、有效数据和 1 6 位 CRC 校验位组成 ,在接收到起始令牌后 ,开始接收有效数据 。 接收完所有块数据后 ,发送停止传输命令 CMD1 2 ,完成读操作 。写入连续多 块数据向 SD 卡发送 CMD24 ,收到有效应答信号 0x00 后 ,开始发送数据 。 每块数据由 起始令牌 (0xFC) 、有效数据和 16 位填充位组成 。 发送完所有块数据 ,发送 0xFD 停止传输 ,完成写操作 。

六、 软件开发说明

Qsys.h文件定义了SPI的寄存器结构体,SD_driver.c和SD_driver.h文件包含基于SPI接口的所有SD卡操作的函数,hello_world.c存放主函数。主函数中先调用SD_Init(); 初始化SD卡,然后写入100个字节,再将这100个字节读出来。如果读出来的等于写进去的,表明SD卡读写成功。

连线说明:

assign MISO = PORT9;

assign PORT10 = MOSI;

assign PORT11 = SCLK;

assign PORT12 = CS;

免责声明:本例程中SD卡没有集成文件系统,数据的读写可能会破坏SD卡中原有的文件数据,请实验前做好备份。如造成数据丢失,恕不负责。

实验五 数码管驱动CH451

通过本章的实验,我们将了解并掌握基于SOPC平台的利用CH451驱动芯片驱动数码管的实验。

 一 、CH451简介

CH451 是一个整合了数码管显示驱动和键盘扫描控制以及μP 监控的多功能外围芯片。CH451 内置 RC 振荡电路,可以动态驱动 8 位数码管或者 64 位 LED,具有 BCD 译码、闪烁、移位等功能;同时还可以进行 64 键的键盘扫描;CH451 通过可以级联的串行接口与微处理器交换数据;并且提供上电复位和看门狗等监控功能。

本实验我们使用CH451驱动4位数码管。 CH451内置大电流驱动级,段电流不小于 25mA,字电流不小于 150mA。 动态显示扫描控制,直接驱动 8 位数码管或者 64 位发光管 LED。 可选数码管的段与数据位相对应的不译码方式或者 BCD 译码方式。 数码管的字数据左移、右移、左循环、右循环。 各数码管数字独立闪烁控制。 通过占空比设定提供 16 级亮度控制。 支持段电流上限调整,可以省去所有限流电阻。 扫描极限控制,支持 1 到 8 个数码管,只为有效数码管分配。

二 、 数字接口时序

CH451 具有硬件实现的高速 4 线串行接口,包括 4 个信号线:串行数据输入线 DIN、串行数据时钟线 DCLK、串行数据加载线 LOAD、串行数据输出线 DOUT。其中,DIN、DCLK、LOAD 是带上拉的输入信号线,默认是高电平。 DIN 用于提供串行数据,串行数据输入的顺序是低位在前,高位在后。另外,在 CH451 上电复位后,单片机必须在 DCLK 输出串行时钟之前,先在 DIN上输出一个低电平脉冲(由高电平变为低电平再恢复为高电平) ,通知 CH451 使能 4 线串行接口。 DCLK 用于提供串行时钟, CH451 在其上升沿从 DIN 输入数据。 CH451内部具有 12 位移位寄存器,在 DCLK 的上升沿,DIN 上的位数据被移入移位寄存器的最高位寄存器,以此类推。 LOAD 用于加载串行数据,CH451 在其上升沿加载移位寄存器中的 12 位数据,作为操作命令分析并处理。也就是说,LOAD 的上升沿是串行数据帧的帧完成标志,此时无论移位寄存器中的 12 位数据是否有效,CH451 都会将其当作操作命令。

图5.1 数字接口时序图

3、 操作指令:

CH451 的操作命令均为 12 位, 下表列出了 CH451 的各个操作命令所对应的 12 位串行数据。 其中,标注为 x 的位表示该位可以是任意值;标有名称的位表示该位在 CH451 芯片内部具有相应的寄存器,其数据根据操作命令的不同而变化。

CH451 默认情况下工作于不译码方式,此时 8 个数据寄存器中字数据的位 7~位 0 分别对应 8 个数码管的小数点和段 G~段 A,对于发光二极管阵列,则每个字数据的数据位唯一地对应一个发光二级管。当数据位为 1 时,对应的数据管的段或者发光管就会点亮;当数据位为 0 时,则对应的数据管的段或者发光管就会熄灭。通过设定,CH451 还可以工作于 BCD 译码方式,该方式主要应用于数码管驱动,微处理器只要给出二进制数 BCD 码,由 CH451 将其译码后直接驱动数码管显示对应的字符。

四、Qsys设计

因为本实验使用的硬件资源比较简单,添加完基出模块后再添加3个位宽为1的输出PIO即可。

图5.2 QSYS设计要素

五、 软件开发说明

CH451_SMG.h里面定义了三个IO操作宏,对这些宏定义赋值可以直接改变IO的高低电平。

#define DCLK *((volatile unsigned long int *) LCLK_BASE)

#define DIN *((volatile unsigned long int *) LDA_BASE)

#define LOAD *((volatile unsigned long int *) LOAD_BASE)

CH451_SMG.c文件存放了一个BCD译码表,以及向CH451进行寄存器写操作的函数,这个函数通过控制上面的三个IO口来实现数字接口的时序操作。然后封装了一些应用层函数,这些应用层函数可以方便的在数码管上显示数值。

示例程序实现了四个数码管显示0到f的功能。

连线说明:

.pio_lclk_export(PORT9) ,// output pio_lclk_export_sig.pio_load_export(PORT10) ,// output pio_load_export_sig.pio_lda_export(PORT11) // output pio_lda_export_sig

实验六 字符屏LCD12864

通过本章的实验,我们将了解并掌握基于SOPC平台的利用并行接口驱动字符屏12864。

 一 、LCD12864简介

在小型的智能化电子产品中,普通的7段LED数码管只能用来显示数字,若遇到要显示英文字母或图像、汉字时,则必须选择使用液晶显示器(简称LCD)。

LCD显示器的应用很广,简单的如手表、计算器上的液晶显示器,复杂如笔记本电脑上的显示器等,都使用LCD。在一般的商务办公机器上,如复印机和传真机,以及一些娱乐器材、医疗仪器上,也常常看见LCD的足迹。

LCD12864 是一种具有4 位/8 位并行、2 线或3 线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示模块;其显示分辨率为128×64, 内置8192 个16*16 点汉字,和128 个16*8点ASCII 字符集。利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。

可以显示8×4 行16×16 点阵的汉字。也可完成图形显示。低电压低功耗是其又一显著特点。由该模块构成的液晶显示方案与同类型的图形点阵液晶显示模块相比,不论硬件电路结构或显示程序都要简洁得多,且该模块的价格也略低于相同点阵的图形液晶模块。

二 、 数字接口时序

对于液晶需要写显示数据,还需要写一些命令,例如数据显示的位置,光标的位置等。LCD通过控制线RS、R/W、EN来实现写数据、写指令,读数据。这三根线分别通过铜铆孔引出,可根据设计需要连接任意I/O口。Blight为液晶背景灯电源输入端,改变输入电源电压可以改变液晶背景灯的亮度,注意电压不要超过5V。图2-1 为LCD引脚定义电路原理示意图,原理图上只是液晶引脚的一种表示方式,只要引脚和液晶引脚数量对即可,而PCB图上需要严格按照液晶引脚的顺序、液晶尺寸、液晶固定孔位置和大小来设计封装。学生通过该模块了解并掌握液晶显示的原理及驱动芯片HD44780的使用方法,通过编程实现液晶字符和汉字的显示。

图6.1 LCD引脚定义电路原理示意图

图6.2 数字接口时序图

三、 操作指令:

在使用LCD12864前先必须了解以下功能器件才能进行编程。12864有两个寄存器;指令寄存器(IR)是用于寄存指令码,与数据寄存器数据相对应。当D/I=0时,在E信号下降沿的作用下,指令码写入IR。数据寄存器(DR)是用于寄存数据的,与指令寄存器寄存指令相对应。当D/I=1时,在下降沿作用下,图形显示数据写入DR,或在E信号高电平作用下由DR读到DB7∽DB0数据总线。DR和DDRAM之间的数据传输是模块内部自动执行的。

模块有一个BF标志,提供内部工作情况。BF=1表示模块在内部操作,此时模块不接受外部指令和数据。BF=0时,模块为准备状态,随时可接受外部指令和数据。我们每次操作后都延时一段时间,来等待模块准备好。

LCD12864液晶显示模块的指令系统比较简单,总共只有七种。其指令表如下所示:

指令名称

控制信号

控制代码

R/W

RS

DB7

DB6

DB5

DB4

DB3

DB2

DB1

DB0

显示开关

0

0

0

0

1

1

1

1

1

1/0

显示起始行设置

0

0

1

1

X

X

X

X

X

X

页设置

0

0

1

0

1

1

1

X

X

X

列地址设置

0

0

0

1

X

X

X

X

X

X

读状态

1

0

BUSY

0

ON/OFF

RST

0

0

0

0

写数据

0

1

写数据

读数据

1

1

读数据

  写数据指令每执行完一次写操作,列地址就自动增一。显示ASCII码 ,只需将字符对应的ASCII的数据送入液晶进行显示即可。一个汉字的大小是16*16,占两个ASCII字符的位置,将相应的汉字的编码分两次送入液晶显示即可。也可以用数组的方式,编译器编译时自动将转换成对应的编码。

四、Qsys设计

因为本实验使用的硬件资源比较简单,添加完基出模块后再添加3个位宽为1的输出PIO,一个位宽为8的并行输出IO口即可。

图6.4 QSYS设计要素

五、 软件开发说明

lcd.h里面定义了四个IO操作宏,对这些宏定义赋值可以直接改变IO的高低电平。

//IO操作函数,用于数据通信

#define RS *((volatile unsigned long int *) RS_BASE)

#define RW *((volatile unsigned long int *) R_W_BASE)

#define EN *((volatile unsigned long int *) EN_BASE)

#define DATA *((volatile unsigned long int *) PIO_0_BASE)

lcd.c文件存放了一个BCD译码表,以及向LCD12864写指令的函数void WR_ZL_DATA(uchar ZL_DATA)和显示数据函数void WR_SJ_DATA(uchar SJ_DATA)。

示例程序实现了利用LCD12864显示"南京润众科技有限公司SOPC实验系统"的功能。

连线说明:

.pio_0_pins_export({P12,P10,P8,P6,P4,P2,P21,P19 })

.pio_rs_export(PORT9) ,// output pio_lclk_export_sig

.pio_rw_export(PORT10) ,// output pio_load_export_sig

.pio_en_export(PORT11) // output pio_lda_export_sig

实验七 基于W5500的SOPC网口通信

通过本章的实验,我们将了解并掌握基于SOPC平台的利用W5500实现网口通信。

 一 、W5500简介

W5500 是一款全硬件 TCP/IP 嵌入式以太网控制器,为嵌入式系统提供了更加简易的互联网连接方案。 W5500 集成了 TCP/IP 协议栈, 10/100M 以太网数据链路层( MAC)及物理层( PHY),使得用户使用单芯片就能够在他们的应用中拓展网络连接。

久经市场考验的 WIZnet 硬件 TCP/IP 协议栈支持TCP,UDP,IPv4,ICMP,ARP,IGMP 以及 PPPoE 协议。 W5500 内嵌 32K 字节片上缓存以供以太网包处理。如果你使用 W5500,你只需要一些简单的 Socket 编程就能实现以太网应用。这将会比其他嵌入式以太网方案更加快捷、简便。用户可以同时使用 8 个硬件 Socket 独立通讯。

图7.1 W5500内部结构框图

二 、 数字接口时序

W5500 提供了 SPI(外设串行接口)从而能够更加容易与外设 MCU 整合。而且,W5500 的使用了新的高效 SPI 协议支持 80MHz 速率,从而能够更好的实现高速网络通讯。

SPI 的模式 0 和 3,数据都是在 SCLK 的上升沿锁存,在下降沿输出。W5500 支持 SPI 模式 0 及模式 3.MOSI 和 MISO 信号无论是接收或发送,均遵从最高标志位( MSB)到最低标志位( LSB)的传输序列。

图7.2数字接口时序图

三、 操作指令:

W5500的指令和详细操作时序比较复杂,请参考W5500数据手册。

4、 Qsys设计

本实验接口和SDCARD实验完全相同,QSYS设计可以直接使用SDCARD的工程。

五、 软件开发说明

本例程移植了官方例程,并进行了一些优化。所有芯片相关的代码全部在文件夹《W5500》中。其中SPI5500.c和SPI5500.h提供了一些接口支持,device.h和device.c中做了一些硬件的初始化(IP、MAC的配置,内存分配,服务器地址、端口号等)和tcp客户端的代码。其他代码都是官方提供的,如果没有特殊要求,使用时不需要改动。

本例程实现了一个TCP客户端的功能,模块IP为10.10.10.208,服务器地址为:10.10.10.203,端口号7777。用网线将实验箱和电脑相连,在电脑端使用网络调试助手,本地IP设置为10.10.10.203,掩码设置为255.255.255.0,然后创建一个服务器,端口号为7777.实验箱会主动连上服务器,并将服务器发送下来的数据自环回去。

实验八 ili9320液晶显示

本章将向大家介绍ili9320液晶显示,包括ili9320的接口设计、液晶驱动调用、汉字显示等。在本章,通过对汉子字模的有规则打印来了解液晶显示器中汉子显示的原理。在本章实验中,我们通过软件实现ili9320液晶的驱动,以及ASCII码和汉子的显示。通过本章的实验,我们最终将了解并掌握ili9320液晶的基本使用方法。

 一 、ili9320接口设计

 我们的SOPC实验平台上搭载一副3.2_TFT彩色LCD模块,该模块采用 TFTLCD 面板,可以显示 16位色的真彩图片。从图8.1可以看出, ALIENTEK TFTLCD 模块采用 16 位的并方式与外部连接, 之所以不采用 8 位的方式,是因为彩屏的数据量比较大,尤其在显示图片的时候,如果用 8 位数据线,就会比 16 位方式慢一倍以上,我们当然希望速度越快越好,所以我们选择 16 位的接口。图8.1还列出了触摸屏芯片的接口,关于触摸屏本章我们不多介绍。

图8.1 ili9320原理图

CS:TFTLCD 片选信号。

WR:向 TFTLCD 写入数据。

RD:从 TFTLCD 读取数据。

DB[15:0]:16 位双向数据线。

RESET:硬复位 TFTLCD。

RS:命令/数据标志(0,读写命令;1,读写数据)。

LCD模块的 RST 信号线是连接到液晶下发的按键上的,并不由软件控制,这样可以省下来一个 IO口。

关于液晶屏的寄存器和始化操作,请参阅TFT的芯片手册和参考例程,不同型号的液晶寄存器分布不同,但是功能大同小异。由于工作量大,我们写液晶的底层驱动时,都是移植官方参考驱动的。

二 、 点阵汉字显示

液晶的汉字显示:对于每个汉字,我们都定义一组数据。根据这组数据,经过一定的排列算法打印点阵,就会打印出该汉字。如汉字“当”,我们在vc上用printf函数打印:

#include "stdio.h"

unsigned char cc[] = //汉字"当"的字库数据,也就上面说的数组

{

0x00,0x80,0x10,0x90,0x08,0x98,0x0C,0x90,0x08,0xA0,0x00,0x80,

0x3F,0xFC,0x00,0x04,0x00,0x04,0x1F,0xFC,0x00,0x04,0x00,0x04,

0x00,0x04,0x3F,0xFC,0x00,0x04,0x00,0x00

};

void main()

{

int i,j;

unsigend char kk;

for (i=0;i<16;i++)

{

for(j=0;j<8;j++)

{

kk=cc[2*i]<

if(kk & 0x80)

{

printf("8");

}else

{

printf(" ");

}

}

for(j=0;j<8;j++)

{

kk=cc[2*i+1]<

if(kk & 0x80)

{

printf("8");

}else

{

printf(" ");

}

}

printf("\n");\

}

printf("\n\n");

}

我们测试打印出来的结果如图1.2:

图8.2 点阵打印的汉字当

如图所示,我们可以存储所有需要的汉字信息放入字库文件中,然后显示某一汉字时,利用类似上面的算法调用该汉字的数据。

要显示汉子我们先要得到这个字符集的点阵数据,网上一些字符提取软件可以提供各种字符,包括汉字(字体和大小都可以自己设置)阵提取,取模方式可以设置好几种,常用的取模方式,一般软件都支持。

我们利用字符提取软件得到取模数据,然后把对应汉字(和ASCII 字符)集按12*12大小和16*16 大小取模出来(ASCII 字符集按 12*6大小和 16*0 大小取模ASCII字符的只有汉字的一半大!),保存在存储字库的font.h文件里面。

三 、 Qsys设计

虽然使用的引脚比较多,但是本实验使用的硬件资源并不复杂,添加完基出模块后再添加4个位宽为1的输出PIO,一个位宽为16的并行输出IO口即可(因为我们不需要读取数据,这里16位的IO口不需要设置成双向的)。

图8.3 Qsys设计要素

四、 软件开发说明

本例程移植了官方例程,并进行了一些优化。Lcd.c和lcd.h文件中包含液晶的初始化函数,描点函数,字符显示函数,汉字显示函数等。

本例程实现了使用ili9320彩色液晶显示"SOPC-LCD-编码"。

连线说明:

.pio_0_pins_export({P27,P25,P23,P22,P20,P18,P16,P14,P12,P10,P8,P6,P4,P2,P21,P19}) ,

.pio_rs_export(P13) ,// output pio_lclk_export_sig

.pio_rw_export(P15) ,// output pio_load_export_sig

.pio_cs_export(P11) ,// output pio_load_export_sig

.pio_rd_export(P17) // output pio_lda_export_sig

因为USB和ili9320使用了同一个数据接口,所以这里要将USB的片选拉高。

实验九 USB通信

本章将向大家介绍SOPC平台通过USB和PC端通信。

 一 、模块介绍

 USB接口模块,提供的USB驱动芯片为国产的CH372。CH372是一个USB总线的通用设备接口芯片,是CH371的升级产品,是CH375芯片的功能简化版。在本地端,CH372具有8位数据总线和读、写、片选控制线以及中断输出,可以方便地挂接到Nios II/DSP/MCU/MPU等控制器的系统总线上;在计算机系统中,CH372 的配套软件提供了简洁易用的操作接口,与本地端的单片机通讯就如同读写文件。CH372内置了USB通讯中的底层协议,具有省事的内置固件模式和灵活的外置固件模式。在内置固件模式下,CH372自动处理默认端点0的所有事务,本地端单片机只要负责数据交换,所以单片机程序非常简洁。在外置固件模式下,由外部单片机根据需要自行处理各种USB请求,从而可以实现符合各种USB 类规范的设备。

图9.1 USB接口芯片CH372电路原理示意图

CH372 芯片在本地端提供了通用的并行接口,包括:8 位双向数据总线D7~D0、读选通输入引脚RD#、写选通输入引脚WR#、片选输入引脚CS#、中断输出引脚INT#以及地址输入引脚A0。当WR#为高电平并且CS#和RD#及A0 都为低电平时,CH372 中的数据通过D7~D0输出;当RD#为高电平并且CS#和WR#及A0 都为低电平时,D7~D0上的数据被写入CH372 芯片中;当RD#为高电平并且CS#和WR#都为低电平而A1 为高电平时,D7~D0 上的数据被作为命令码写入CH372 芯片中。

二 、Qsys设计

在Qsys系统中个,创建以下几个PIO元件

USB_DB:位宽8位,方向Bidir,与CH372的数据线D7~D0连接

USB_nINT:位宽1位,方向Input,与CH372的中断输出引脚INT#连接

USB_WR:位宽1位,方向Output,与CH372写选通输入引脚WR#连接

USB_RD:位宽1位,方向Output,与CH372读选通输入引脚RD#连接

USB_A0:位宽1位,方向Output,与CH372地址输入引脚A0连接

下图为Qsys系统设计

图9.2 Qsys设计要素

三、 软件开发说明

CH372芯片占用两个地址位,当A0 引脚为高电平时选择命令端口,可以写入命令;当A0引脚为低电平时选择数据端口,可以读写数据。

Nios II通过8 位并口对CH372 芯片进行读写,所有操作都是由一个命令码、若干个输入数据和若干个输出数据组成,部分命令不需要输入数据,部分命令没有输出数据。命令操作步骤如下:

①、 在A0=1 时向命令端口写入命令代码;

②、 如果该命令具有输入数据,则在A0=0 时依次写入输入数据,每次一个字节;

③、 如果该命令具有输出数据,则在A0=0 时依次读取输出数据,每次一个字节;

④、 命令完成,可以暂停或者转到①继续执行下一个命令。

CH372 芯片专门用于处理USB 通讯,在接收到数据后或者发送完数据后,CH372 以中断方式通知Nios II,Nios II通过CH372 芯片接收数据的处理步骤如下:

①、 当CH372 接收到USB主机发来的数据后,首先锁定当前USB 缓冲区,防止被后续数据覆盖,然后将INT#引脚设置为低电平,向Nios II请求中断;

②、 Nios II进入中断服务程序,首先执行GET_STATUS 命令获取中断状态;

③、 CH372 在GET_STATUS 命令完成后将INT#引脚恢复为高电平,取消中断请求;

④、 由于通过上述GET_STATUS 命令获取的中断状态是“下传成功”,所以Nios II执行RD_USB_DATA 命令从CH372 读取接收到的数据;

⑤、 CH372 在RD_USB_DATA 命令完成后释放当前缓冲区,从而可以继续USB 通讯;

⑥、 Nios II退出中断服务程序。

Nios II通过CH372 芯片发送数据的处理步骤如下:

①、 Nios II执行WR_USB_DATA 命令向CH372 写入要发送的数据;

②、 CH372 被动地等待USB 主机在需要时取走数据;

③、 当USB主机取走数据后,CH372首先锁定当前USB缓冲区,防止重复发送数据,然后将INT#引脚设置为低电平,向Nios II请求中断;

④、 Nios II进入中断服务程序,首先执行GET_STATUS 命令获取中断状态;

⑤、 CH372 在GET_STATUS 命令完成后将INT#引脚恢复为高电平,取消中断请求;

⑥、 由于通过上述GET_STATUS 命令获取的中断状态是“上传成功”,所以Nios II执行WR_USB_DATA 命令向CH372 写入另一组要发送的数据,如果没有后续数据需要发送,那么Nios II不必执行WR_USB_DATA 命令;

⑦、 Nios II执行UNLOCK_USB 命令;

⑧、 CH372 在UNLOCK_USB 命令完成后释放当前缓冲区,从而可以继续USB 通讯;

⑨、 Nios II退出中断服务程序;

⑩、 如果Nios II已经写入了另一组要发送的数据,那么转到②,否则结束。

该实例实现了开发板与计算机(计算机端使用CH372的DEBUG软件)通过CH372通信,包括CH372接口Qsys实现。

连线说明:

.usb_db_external_connection_export ({P12,P10,P8,P6,P4,P2,P21,P19 }),

.usb_nint_external_connection_export (~P29),

.usb_wr_external_connection_export (P31),

.usb_rd_external_connection_export (P33),

.usb_a0_external_connection_export (P35)