ZYNQ——GPIO之MIO控制LED

2023-11-10 05:40
文章标签 led 控制 gpio zynq mio

本文主要是介绍ZYNQ——GPIO之MIO控制LED,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

开发环境        vivado 19.2     vitis

开发板            zynq7010

内容                呼吸灯

        ZYNQ 分为 PS PL 两部分,器件的引脚(Pin)资源同样也分成了两部分。ZYNQ PS 中的外设 可以通过 MIOmultiplexed I/O,多路复用 I/O)模块连接到 PS 端的引脚上,也可以通过 EMIOextended  multiplexed I/O interface,扩展多路 I/O 接口)连接到 PL 端的引脚。Zynq-7000 系列芯片一般有 54 MIO

        MIO是将来自PS外设和静态存储器接口的访问多路复用到ps端的引脚上。

        GPIO 是英文“general purpose I/O”的缩写,即通用的输入/输出。它是 ZYNQ PS 中的一个外设,用于观测(input)和控制(output)器件引脚的状态。如图为GPIO 的框图,从中我们可以看到 GPIO 分为 4 Bank,其中 Bank0 Bank1 连接到 MIO;而 Bank2 Bank3 连接到EMIO

        除 Bank1 之外的 Bank 都具有 32bitBank1 只具有 22bit 是因为总共只有 54 MIO,其中 32bit Bank0 控制了 MIO[0~31],剩下的 MIO[31~53]就由 22bit Bank1 控制。Bank2 Bank3 用于控制扩展的 MIO EMIO,也就是说总共可以有 32+32=64 EMIO

        MIO 一但选定,引脚位置就已经确定下来了,不需要添加引脚约束。

        我们可以看到 PS 通过 APB 总线对控制、状态寄存器的读写实现对 GPIO 的驱动,具体可以参见下图:

        DATA_RO: 数据只读寄存器,通过该寄存器能够观察器件引脚上的值。如果 GPIO 信号配置为输出, 通常会反映输出上驱动的值,写入此寄存器将被忽略。
        DATA :数据寄存器,该寄存器控制 GPIO 信号配置为输出时要输出的值。该寄存器的所有 32 位都是 一次写入的。读取该寄存器返回写入 DATA MASK_DATA_ {LSW MSW} 的先前值,它不会返回器件引 脚上的当前值。
        MASK_DATA_LSW MASK_DATA_MSW 是数据掩码寄存器,该寄存器使软件能够有选择地一次更改所需的输出值。可以写入最多 16 位的任意组合, MASK_DATA_LSW 控制 Bank 的低 16 位, MASK_DATA_MSW 控制高 16 位。未写入的那些位保持不变并保持其先前的值。读取该寄存器返回写入 DATA 或 MASK_DATA_ {LSW MSW} 的先前值 ; 它不会返回器件引脚上的当前值。该寄存器避免了对未更改位的读- 修改 - 写序列的需要。
        DIRM 是方向模式寄存器,用于控制 I/O 引脚是用作输入还是输出。当 DIRM [x] == 0 时,输出驱动器
被禁用,该引脚作为输入引脚使用。
        OEN 是输出使能寄存器。将 I/O 配置为输出时,该寄存器控制是否启用输出。禁用输出时,引脚为 3 态。当 OEN [x] == 0 时,输出被禁用。
        从这些寄存器中我们可以看到,如果配置引脚为输出,不仅需要设置方向,还要使能输出。

硬件平台配置

创建工程

选择对应芯片型号

使用IP Integrator创建Processing System

        接下来在Diagram窗口中给设计添加 IP。点击上图中箭头所指示的加号“+”,会打开IP目录(IP Catalog),也可以通过快捷键Ctrl + I,或者右键点击Diagram工作区中的空白位置,然后选择“ADDIP”。

        打开IP目录后,在搜索栏中键入“zynq”,找到并双击“ZYNQ7 Processing System”,将ZYNQ7处理系统IP添加到设计中。

        添加完成后,ZYNQ7 Processing System模块出现在Diagram中,如下图所示:

        双击所添加的ZYNQ7 Processing System模块,进入ZYNQ7处理系统的配置界面。界面左侧为页面导航面板,右侧为配置信息面板,如下图所示:

        下面我们简要地介绍一下页面导航面板中各个页面的作用。

        在Zynq Block Design页面,显示了Zynq处理系统(PS)的各种可配置块,其中灰色部分是固定的,绿色部分是可配置的,按工程实际需求配置。可以直接单击各种可配置块(以绿色突出显示)进入相应的配置页面进行配置,也可以选择左侧的页导航面板进行系统配置。

        PS-PL Configuration页面能够配置PS-PL接口,包括AXI、HP和ACP总线接口。

        Peripheral IO Pins页面可以为不同的I/O外设选择对应的MIO/EMIO引脚。

        MIO Configuration页面可以为不同的I/O外设具体配置MIO/EMIO引脚,例如电平标准等。

        Clock Configuration页面用来配置PS输入时钟、外设时钟,以及DDR和CPU时钟等。

        DDR Configuration页面用于设置DDR控制器配置信息。

        SMC Timing Calculation页面用于执行SMC时序计算。

        Interrupts页面用于配置PS-PL中断端口。

配置PSDDR3控制器

        XC7Z010的核心板选择MT41J128M16 HA-125。需要注意的是,我们在这里选择的型号并不是领航者核心板上的DDR3型号,而是参数接近的型号,或者兼容的型号。“Effective DRAM Bus Width” 一栏选择32bit,2片DDR,每片16bit。

配置PS的时钟

点击左侧的Clock Configuration页面,该界面主要是配置ZYNQ PS中的时钟频率。比如输入时钟默认是33.33333Mhz,这与我们领航者核心板上的PS端输入时钟频率相同。对于CPU的时钟、DDR的时钟以及其它外设的时钟,我们直接保持默认设置即可。如果想设置成其他的时钟频率,可以在Requested Frequency一栏里输入想要的频率,只要保证输入的频率保持在Range一栏中的频率范围之内。配置好的选项卡如下图所示:

配置好DDR3和时钟之后,我们需要取消勾选其中的几个选项,如下所示:

​​​​​​​

勾选GPIO_MIO

点击左侧的PeripheralI/O Pins,在右侧的界面中勾选GPIO_MIO,另外领航者开发板上的Bank1即原理图中的BANK501为1.8V,所以我们选择Bank1电压为LVCOMS1.8V

​​​​​​​

        最后点击ok,配置完成

​​​​​​​

​​​​​​​

​​​​​​​

        本次实验不需要添加其它IP,直接按快捷键Ctrl+S保存当前设计。接下来点击上图箭头所指示的按钮或者是在Block design界面右击弹出的菜单中点击Validate Design,以验证Block design当前的设计和连接是否有错误。验证完成后弹出对话框提示没有错误或者关键警告,点击“OK”,

生成顶层HDL

​​​​​​​

创建Block DesignHDL封装器文件

​​​​​​​

生成Bitstream文件并导出硬件

如果设计中使用了PL的资源,则需要添加引脚约束并对该设计进行综合、实现并生成Bitstream文件。由于本次实验未用到PL部分,所以无需生成Bitstream文件,只需将硬件导出即可。 ​​​​​​​

打开vitis

​​​​​​​

​​​​​​​

新建工程

添加从vivado中导出的文件

在弹出的会话框选择empty(空工程)即可

        接下来编程即可,在这里给出源程序:

#include "stdio.h"
//#include "xparameters.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "sleep.h"
#define GPIO_DEVICE_ID		XPAR_XGPIOPS_0_DEVICE_ID
#define MIO0_LED    0
#define MIO7_LED    7
#define MIO8_LED    8
XGpioPs_Config *ConfigPtr;//定义ConfigPtr为结构体指针类型 (指针理解为地址)
XGpioPs Gpio;
int main(){//printf("GPIO MIO TEST\n");u32 led=0;int i,j;//根据器件的ID查找器件的配置信息ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);//初始化GPIO的驱动XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);//&是取地址  ->表示结构体的第一个元素//把GPIO的方向设置为输出(0输入/1输出)XGpioPs_SetDirectionPin(&Gpio, MIO0_LED, 1);//(地址  引脚  方向)XGpioPs_SetDirectionPin(&Gpio, MIO7_LED, 1);//(地址  引脚  方向)XGpioPs_SetDirectionPin(&Gpio, MIO8_LED, 1);//(地址  引脚  方向)//设置输出使能(0关闭  1打开)XGpioPs_SetOutputEnablePin(&Gpio, MIO0_LED, 1);XGpioPs_SetOutputEnablePin(&Gpio, MIO7_LED, 1);XGpioPs_SetOutputEnablePin(&Gpio, MIO8_LED, 1);//写数据到GPIO的输出引脚(最后一个数是32位,但是只有最低为有效)XGpioPs_WritePin(&Gpio, MIO0_LED, 1);XGpioPs_WritePin(&Gpio, MIO7_LED, 1);XGpioPs_WritePin(&Gpio, MIO8_LED, 1);//点亮while(1){/*//XGpioPs_WritePin(&Gpio, MIO0_LED, 1);XGpioPs_WritePin(&Gpio, MIO7_LED, 1);XGpioPs_WritePin(&Gpio, MIO8_LED, 1);//延时usleep(100000);//微秒为单位,延迟0.1s//熄灭//XGpioPs_WritePin(&Gpio, MIO0_LED, 0);XGpioPs_WritePin(&Gpio, MIO7_LED, 0);XGpioPs_WritePin(&Gpio, MIO8_LED, 0);//延时usleep(100000);*/for (i=0;i<1000;i++){for (j=0;j<1000;j=j+1){usleep(1);if(i<j){XGpioPs_WritePin(&Gpio, MIO0_LED, ~led);}else{XGpioPs_WritePin(&Gpio, MIO0_LED, led);}}}led=~led;}return 0;
}

        代码部分也有注释,编程思路就是:1.先根据器件的ID查找器件的配置信息;2.然后初始化GPIO的驱动3.把GPIO的方向设置为输出;4.设置输出使能;5.写数据到GPIO的输出引脚。

        其中第1,2步是一些必要的初始化信息;

        3,4,5正好对应DATA,DIRM,OEN寄存器的配置,当然这些底层寄存器的配置都是在函数里面实现的,具体实现过程我们可以不用关心,只要会用就可以。

        最后补充一点内容,在初始化GPIO驱动部分用到了结构体指针的内容,在这里作简单说明:

XGpioPs_Config *ConfigPtr;//定义ConfigPtr为结构体指针类型 (指针理解为地址)
//初始化GPIO的驱动XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);//&是取地址  ->表示结构体的第一个元素

        指针的基本功能就是简介引用,也就是通过指针变量间接的引用另一个变量。给出一个例子,变量间的间接引用

        以上代码就是定义a,再定义p为指针变量。把a的地址赋给p,此时p就指向了a的地址,最后把123赋值给了p所指向的变量,那实际上就是a,所以a输出结果就是123 。

        结构体指针c语言结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合。说的通俗一点就是一个集合。c语言是一门面向过程的编程语言,而结构体的使用在某些层次上跟面向对象有点异曲同工之处了。

        例:一名学生各项信息如下:学号:1234      姓名:张三   年龄:18      成绩:300

        要求:先用初始化方式,把这些数据存入一个结构体变量中,再将该结构体变量的内容复制到另一个结构体变量中,最后,输出第二个结构体变量中的各项内容。

        方法一:采用直接引用的方式,直接把结构体变量st1赋值给st2

        方法二:采用间接引用的方式

        1.首先定义一个包含4个成员的结构体变量

        2.通过初始化,将各项数据存入结构体变量中。

        3.通过间接引用方式,实现结构体变量的整体赋值

        4.最后依次输出第二个结构体变量成员的值。(pq是两个结构体指针变量

        以上就是利用结构体指针来引用结构体变量,同样结构体指针也可以引用结构体变量的成员。一般形式为(*结构体指针变量).成员名    如图所示:

        更简洁的引用方式:结构体指针变量->成员名    如下图所示:

        这就与我们初始化GPIO驱动中,利用结构体指针来引用结构体变量的部分对应上了。

这篇关于ZYNQ——GPIO之MIO控制LED的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/380667

相关文章

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

使用DrissionPage控制360浏览器的完美解决方案

《使用DrissionPage控制360浏览器的完美解决方案》在网页自动化领域,经常遇到需要保持登录状态、保留Cookie等场景,今天要分享的方案可以完美解决这个问题:使用DrissionPage直接... 目录完整代码引言为什么要使用已有用户数据?核心代码实现1. 导入必要模块2. 关键配置(重点!)3.

SpringSecurity 认证、注销、权限控制功能(注销、记住密码、自定义登入页)

《SpringSecurity认证、注销、权限控制功能(注销、记住密码、自定义登入页)》SpringSecurity是一个强大的Java框架,用于保护应用程序的安全性,它提供了一套全面的安全解决方案... 目录简介认识Spring Security“认证”(Authentication)“授权” (Auth

python之流程控制语句match-case详解

《python之流程控制语句match-case详解》:本文主要介绍python之流程控制语句match-case使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录match-case 语法详解与实战一、基础值匹配(类似 switch-case)二、数据结构解构匹

Spring Security注解方式权限控制过程

《SpringSecurity注解方式权限控制过程》:本文主要介绍SpringSecurity注解方式权限控制过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、摘要二、实现步骤2.1 在配置类中添加权限注解的支持2.2 创建Controller类2.3 Us

Python中如何控制小数点精度与对齐方式

《Python中如何控制小数点精度与对齐方式》在Python编程中,数据输出格式化是一个常见的需求,尤其是在涉及到小数点精度和对齐方式时,下面小编就来为大家介绍一下如何在Python中实现这些功能吧... 目录一、控制小数点精度1. 使用 round() 函数2. 使用字符串格式化二、控制对齐方式1. 使用

Springboot控制反转与Bean对象的方法

《Springboot控制反转与Bean对象的方法》文章介绍了SpringBoot中的控制反转(IoC)概念,描述了IoC容器如何管理Bean的生命周期和依赖关系,它详细讲解了Bean的注册过程,包括... 目录1 控制反转1.1 什么是控制反转1.2 SpringBoot中的控制反转2 Ioc容器对Bea

浅析如何使用Swagger生成带权限控制的API文档

《浅析如何使用Swagger生成带权限控制的API文档》当涉及到权限控制时,如何生成既安全又详细的API文档就成了一个关键问题,所以这篇文章小编就来和大家好好聊聊如何用Swagger来生成带有... 目录准备工作配置 Swagger权限控制给 API 加上权限注解查看文档注意事项在咱们的开发工作里,API

Spring IOC控制反转的实现解析

《SpringIOC控制反转的实现解析》:本文主要介绍SpringIOC控制反转的实现,IOC是Spring的核心思想之一,它通过将对象的创建、依赖注入和生命周期管理交给容器来实现解耦,使开发者... 目录1. IOC的基本概念1.1 什么是IOC1.2 IOC与DI的关系2. IOC的设计目标3. IOC