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

相关文章

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

控制反转 的种类

之前对控制反转的定义和解释都不是很清晰。最近翻书发现在《Pro Spring 5》(免费电子版在文章最后)有一段非常不错的解释。记录一下,有道翻译贴出来方便查看。如有请直接跳过中文,看后面的原文。 控制反转的类型 控制反转的类型您可能想知道为什么有两种类型的IoC,以及为什么这些类型被进一步划分为不同的实现。这个问题似乎没有明确的答案;当然,不同的类型提供了一定程度的灵活性,但

深入解析秒杀业务中的核心问题 —— 从并发控制到事务管理

深入解析秒杀业务中的核心问题 —— 从并发控制到事务管理 秒杀系统是应对高并发、高压力下的典型业务场景,涉及到并发控制、库存管理、事务管理等多个关键技术点。本文将深入剖析秒杀商品业务中常见的几个核心问题,包括 AOP 事务管理、同步锁机制、乐观锁、CAS 操作,以及用户限购策略。通过这些技术的结合,确保秒杀系统在高并发场景下的稳定性和一致性。 1. AOP 代理对象与事务管理 在秒杀商品

PostgreSQL中的多版本并发控制(MVCC)深入解析

引言 PostgreSQL作为一款强大的开源关系数据库管理系统,以其高性能、高可靠性和丰富的功能特性而广受欢迎。在并发控制方面,PostgreSQL采用了多版本并发控制(MVCC)机制,该机制为数据库提供了高效的数据访问和更新能力,同时保证了数据的一致性和隔离性。本文将深入解析PostgreSQL中的MVCC功能,探讨其工作原理、使用场景,并通过具体SQL示例来展示其在实际应用中的表现。 一、

vue2实践:el-table实现由用户自己控制行数的动态表格

需求 项目中需要提供一个动态表单,如图: 当我点击添加时,便添加一行;点击右边的删除时,便删除这一行。 至少要有一行数据,但是没有上限。 思路 这种每一行的数据固定,但是不定行数的,很容易想到使用el-table来实现,它可以循环读取:data所绑定的数组,来生成行数据,不同的是: 1、table里面的每一个cell,需要放置一个input来支持用户编辑。 2、最后一列放置两个b

【电机控制】数字滤波算法(持续更新)

文章目录 前言1. 数字低通滤波 前言 各种数字滤波原理,离散化公式及代码。 1. 数字低通滤波 滤波器公式 一阶低通滤波器的输出 y [ n ] y[n] y[n] 可以通过以下公式计算得到: y [ n ] = α x [ n ] + ( 1 − α ) y [ n − 1 ] y[n] = \alpha x[n] + (1 - \alpha) y[n-1]

物联网之流水LED灯、正常流水灯、反复流水灯、移动流水灯

MENU 硬件电路设计软件程序设计正常流水LED灯反复流水LED灯移动流水LED灯 硬件电路设计 材料名称数量直插式LED1kΩ电阻杜邦线(跳线)若干面包板1 每一个LED的正极与开发板一个GPIO引脚相连,并串联一个电阻,负极接GND。 当然也可以选择只使用一个电阻。 软件程序设计 正常流水LED灯 因为要用到多个GPIO引脚,所以最好把所有的GPI

A20 操作GPIO口

例如:先在 Sys_config.fex文件中 [1302_para] 1302_used      = 1 1302_clk             = port:PD05<1><default><default><0> 1302_dat             = port:PD06<1><default><default><0> 1302_rs

OpenStack离线Train版安装系列—3控制节点-Keystone认证服务组件

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版

OpenStack离线Train版安装系列—1控制节点-环境准备

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版