zoukankan      html  css  js  c++  java
  • 第六章 ZYNQ-MIZ701 GPIO使用之MIO

     

    6.0 本章难度系数★★☆☆☆☆☆

    6.1 GPIO简介

    Zynq7000系列芯片有54个MIO(multiuse I/O),它们分配在 GPIO 的Bank0 和Bank1隶属于PS部分,这些IO与PS直接相连。不需要添加引脚约束,MIO信号对PL部分是透明的,不可见。所以对MIO的操作可以看作是纯PS的操作。

    GPIO的控制和状态寄存器基地址为:0xE000_A000,我们SDK下软件操作底层都是对于内存地址空间的操作。

    wps237A.tmp

    Bank0:MI0[31:0]

    Bank1:MI0[52:53]

    Bank2:EMI0[31:0]

    Bank3:EMI0[63:32]

    6.1.1 GPIO的控制寄存器地址空间

    我们在SDK下操作的时候底层都是对这些寄存器的操作,具体的相关参数请参考技术手册ug585-Zynq-7000-TRM.pdf

    wps237B.tmpwps237C.tmp

    wps237D.tmp

    6.1.2MIO内部构造分析

    wps238D.tmp

    DATA_RO: 此寄存器使能软件观察PIN脚,当GPIO被配置成输出的时候,这个寄存器的值会反应输出的PIN脚情况。

    DATA:此寄存器控制输出到GPIO的值,读这个寄存器的值可以读到最后一次写入该寄存器的值。 

    MASK_DATA_LSW:位操作寄存器,写入GPIO 低16bit 其他没有改变的位置保存原先的状态

    MASK_DATA_MSW:位操作寄存器,写入GPIO 高16bit 其他没有改变的位置保存原先的状态

    DIRM:此寄存器控制输出的开关,当DIRM[x]==0时候,禁止输出

    OEN: 输出使能,当OEN[x]==0 的时候输出关闭,PIN脚处于三态

    因此,如果要读IO状态就得读DATA_RO的值,如果是对某一位进行操作就是写MASK_DATA_LSW/MASK_DATA_MSW

    具体的相关参数请参考技术手册ug585-Zynq-7000-TRM.pdf

    6.1.3 EMIO的特性

    与MIO大部分类似但是一下几点需要注意下

    • EMIO在PL部分,输入与OEN寄存器无关,当DIRM设置为0的时候设置为输入可以读DATA_RO寄存器获取数据。

    • 输出不能设置成三态,当DIRM设置为1的时候为输出,写入DATA寄存器或者MASK_DATA_LSW/MASK_DATA_MSW寄存器

    • EMIOGPIOTN[x]=DIRM[x] & OEN[x],实现输出的控制。

    具体的相关参数请参考技术手册ug585-Zynq-7000-TRM.pdf

    6.2 电路分析及实验预期

    在MiZ702的开发板上有一个MIO是与开发板上的一个LD9相连的,这个MIO就是MIO7。实验通过操作该MIO来实现LD9的闪烁。

    6.3 ZYNQ核的添加及配置

    Step1:新建一个名为为Miz701_sys的工程

    wps238E.tmp

    Step2:选择RTL Project 勾选Do not specify source at this time

    wps238F.tmp

    Step3:选择芯片xc7z010clg400-1。

    wps2390.tmp

    Step4:单击Finish

    wps2391.tmp

    6.4使用IP Integrator创建硬件系统

    Step1:单击Create Block Design

    Step2:输入system

    wps2392.tmp

    Step3:单击下图中wps2393.tmp添加IP按钮

    wps23A4.tmp

    Step4:搜素单词z选择ZYNQ7 Processing System,然后双击

    wps23A5.tmp

    Step5:添加进来了ZYNQ CPU IP,双击ZYNQ7 Processing System。

    wps23A6.tmp
    Step6: 修改时钟输入为50MHZ,可以看到ARM时钟为650MHZ DDR为525MHZ(1050MHZ),并且修改FCLK_CLK0 为100MHZ。

    wps23A7.tmp

    Step7: 修改MIO的配置 修改IO电压,增加ENT0 和UART1接口,在这个实验中将会使用到MIO7确保勾选(默认勾选)单击OK退出.

    wps23A8.tmp

    wps23A9.tmp

    wps23AA.tmp

    Step8:修改内存型号为MT41K256M16RE-125 M。

    wps23BB.tmp

    Step9:单机Run Block Automation 进行自动连线,VIVADO软件会根据信号的命名规则智能连线。

    wps23BC.tmp

    Step10:勾选如下,直接单机OK

    wps23BD.tmp

    Step11:在你点击了OK后,你会发现DDR以及FICED_IO自劢的延伸出来,然后把时钟FCLK_CLK0和M_AXI_GPI0_ACLK连接。方法:当把鼠标靠近的时候会自动连接。

    wps23BE.tmp

    Step12:为了让以太网PHY RTL8211E-VL可以工作,必须让其复位PIN脚设置为1,只要简单添加一个常量IP并且映射到PL部分的PIN脚(复位脚在FPGA 部分(PL)),和添加CPU方法一样

    wps23BF.tmp

    Step13:双击设置常量为1

    wps23C0.tmp

    Step14:右击PIN脚选择Make External

    wps23C1.tmp

    wps23C2.tmp

    Step15:取个有意义的名字如下图,只要单击相应的模块就可以在右手边修改

    wps23D2.tmp

    Step16: 右击 system.bd, 单击Generate Output Products

    wps23D3.tmp

    Step17:支部操作会产生执行、仿真、综合的文件,可以看出来最后的硬件设计步骤还是回到了我们前面的FPGA开发上来了。

    wps23D4.tmp

    Step18:右击system.bd 选择 Create HDL Wrapper 这步的作用是产生顶层的HDL文件

    wps23D5.tmp

    Step19:选择Leave Let Vivado manager wrapper and auto-update 然后单击OK

    wps23D6.tmp

    Step20:单机Add Sources。

    wps23D7.tmp

    Step21:选择Add or create constraints

    wps23D8.tmp

    Step22:选择Create File

    wps23E9.tmp

    Step23:输入zynq_pin。

    wps23EA.tmp

    Step24:如图,单击Finish

    wps23EB.tmp

    Step25:双击打开zynq_pin.xdc文件,添加PIN脚约束

    wps23EC.tmp

    wps23ED.tmp

    Step26:执行->产生bit文件wps23EE.tmp

    6.5导出SOC硬件到SDK

    Step1:File->Export->Export Hardware

    wps23EF.tmp

    Step2:勾选Include bitstream 直接单击OK

    wps23F0.tmp

    Step3:File->Launch SDK加载到SDK

    wps23F1.tmp

    Step4:单击OK

    wps2401.tmp

    6.6 新建LED_Flash SDK工程

    Step1:在SDK界面中,新建一个名为LED_Flash的工程,单击Next。

    wps2402.tmp

    Step2:建立一个空的工程

    wps2403.tmp

    Step3:新建一个C的源文件

    wps2404.tmp

    Step4:取名为LED_Flash.c

    wps2405.tmp

    Step5:取名为LED_Flash.c

    接下来就向LED_Flash.c中添加内容了,之前讲过,其中MIO7接到了LD9这个灯上,接下来我们利用程序让他闪起来。

    #include "xgpiops.h"

    #include "sleep.h"

    int main()

    {

    static XGpioPs psGpioInstancePtr;

    XGpioPs_Config* GpioConfigPtr;

    int iPinNumber= 7; //LD9连接的是MIO7

    u32 uPinDirection = 0x1; //1表示输出,0表示输入

    int xStatus;

    //--MIO的初始化

        GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);

    if(GpioConfigPtr == NULL)

    return XST_FAILURE;

    xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,GpioConfigPtr, GpioConfigPtr->BaseAddr);

    if(XST_SUCCESS != xStatus)

    print(" PS GPIO INIT FAILED ");

    //--MIO的输入输出操作

         XGpioPs_SetDirectionPin(&psGpioInstancePtr, iPinNumber,uPinDirection);//配置MIO输出方向

    XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumber,1);//配置MIO的第7位输出

    while(1)

    {

    XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 1);//点亮MIO的第7位输出1

    sleep(1); //延时

    XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 0);//熄灭MIO的第7位输出0

    sleep(1); //延时

    }

        return 0;

    }

    6.7 程序分析

    具体内容请对照注释说明,这里想说明的是iPinNumber这个参数,应为我们要操作的是MIO7,所以这里所以这里的iPinNumber等于7,在后一章的EMIO中也有这个参数,具体怎么算请参看下一节内容,这里就做个铺垫吧。

    6.8 IO寄存器直接输出

    实际上以上代码的销量是非常低的,因为封装好的函数,里面有很多调用开销,还有很多自动化的代码,特别是当要求IO输出速度很高的时候,差距会很明显。笔者这里把IO部分的函数做一点小的改动,改为直接控制寄存器地址空间。

    while(1)

    {

    //XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 1);//点亮MIO的第7位输出1

    Value = ~((u32)1 << (iPinNumber + 16U)) & ((1 << iPinNumber) | 0xFFFF0000U);

    Xil_Out32(0xE000A000,Value);//直接寄存器操作

    sleep(1); //延时

    Value = ~((u32)1 << (iPinNumber + 16U)) & ((0 << iPinNumber) | 0xFFFF0000U);

    Xil_Out32(0xE000A000,Value);//

    //XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 0);//熄灭MIO的第7位输出0

    sleep(1); //延时

    }

    这个地址0xE000A000是不是很熟悉呢?没错这就是前面笔者贴出的一张表格,而且正是位控制 寄存器MASK_DATA_0_LSW

    wps2406.tmp

    6.9电平翻转速度库函数和寄存器对比

    库函数测试函数

    XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 1);//点亮MIO的第7位输出1

    XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 0);//熄灭MIO的第7位输出0

    寄存器测试函数

    while(1)

    {

    Value = ~((u32)1 << (iPinNumber + 16U)) & ((1 << iPinNumber) | 0xFFFF0000U);

    Xil_Out32(0xE000A000,Value);//直接寄存器操作

    Value = ~((u32)1 << (iPinNumber + 16U)) & ((0 << iPinNumber) | 0xFFFF0000U);

    Xil_Out32(0xE000A000,Value);//

    }

    库函数测试函数出来的频率

    wps2417.tmp

    寄存器测试函数出来的频率(由于示波器带宽太低,波形已经变形)

    wps2418.tmp

    6.10 本章小结

    本章讲解了ZYNQ芯片的GPIO的一些知识,然后通过使用SDK进行编程点亮一个LED。同时分析了程序的代码。测试结果说明了,库函数使用方便,但是效率地下,寄存器效率高,但是使用不方便。因此在设计系统的时候如何优化是需要综合考虑的。

  • 相关阅读:
    BootStrap 学习笔记一
    ROW_NUMBER() OVER的用法
    Angularjs学习笔记(五)----显示和格式化数据
    &&和||的妙用
    形象的讲解angular中的$q与promise(转)
    Angularjs学习笔记(四)----与后端服务器通信
    Angularjs学习笔记(一)
    Angularjs学习笔记(二)----模块
    Angularjs学习笔记(三)----依赖注入
    StringBuilder类型
  • 原文地址:https://www.cnblogs.com/milinker/p/5891078.html
Copyright © 2011-2022 走看看