4 - AXI GPIO按键控制LED实验

news2025/2/25 9:02:02

文章目录

  • 1 实验任务
  • 2 系统框图
  • 3 软件设计

1 实验任务

本实验任务是通过调用PL端AXI GPIO IP核,使用中断机制,实现PL端按键控制 PS端LED的功能。

2 系统框图

在这里插入图片描述

3 软件设计

注意事项:

  1. AXI GPIO IP核是双沿触发中断,不可设置;
  2. AXI GPIO IP核的中断使能和中断状态都是以通道为单位。
/***************************** Include Files ********************************/
#include <stdio.h>
#include "xil_exception.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "xgpio.h"
#include "xscugic.h"
#include "xstatus.h"
#include "sleep.h"
/************************** Constant Definitions ****************************/
#define PSGPIO_DEVICE_ID  		XPAR_XGPIOPS_0_DEVICE_ID
#define AXIGPIO_DEVICE_ID		XPAR_GPIO_0_DEVICE_ID
#define INTC_DEVICE_ID			XPAR_SCUGIC_SINGLE_DEVICE_ID

#define AXIGPIO_INTR_ID	    	XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR

#define PS_LED0_GPIO_PIN		0
#define AXIGPIO_CHANNEL1		0x1
/**************************** Type Definitions ******************************/

/***************** Macros (Inline Functions) Definitions ********************/

/************************** Function Prototypes *****************************/
int  PsGpioInit(XGpioPs* PsGpioInstPtr);
int  AxiGpioInit(XGpio* AxiGpioInstPtr);
int  SetupIntrSystem(XScuGic* IntcInstPtr, XGpio* AxiGpioInstPtr, u16 AxiGpioIntrId);
void AxiGpioIntrHandler(void *CallBackRef);
/************************** Variable Definitions ****************************/
XGpioPs PsGpioInst;
XGpio   AxiGpioInst;
XScuGic IntcInst;

u32 KeyPress = 0;
/****************************************************************************/

int PsGpioInit(XGpioPs* PsGpioInstPtr)
{
	//
	int Status;
	XGpioPs_Config* PsGpioConfigPtr;
	//
	PsGpioConfigPtr = XGpioPs_LookupConfig(PSGPIO_DEVICE_ID);
	Status = XGpioPs_CfgInitialize(PsGpioInstPtr, PsGpioConfigPtr, PsGpioConfigPtr->BaseAddr);

	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	// 设置输出
	XGpioPs_SetDirectionPin(PsGpioInstPtr, PS_LED0_GPIO_PIN, 1);
	// 使能输出
	XGpioPs_SetOutputEnablePin(PsGpioInstPtr, PS_LED0_GPIO_PIN, 1);
	//
	return XST_SUCCESS;
}

int  AxiGpioInit(XGpio* AxiGpioInstPtr)
{
	//
	int Status;
	XGpio_Config* AxiGpioConfigPtr;
	//
	AxiGpioConfigPtr = XGpio_LookupConfig(AXIGPIO_DEVICE_ID);
	Status = XGpio_CfgInitialize(AxiGpioInstPtr, AxiGpioConfigPtr, AxiGpioConfigPtr->BaseAddress);

	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	// 设置输入
	XGpio_SetDataDirection(AxiGpioInstPtr, AXIGPIO_CHANNEL1, 0x1);
	// 使能中断
	XGpio_InterruptEnable(AxiGpioInstPtr, XGPIO_IR_CH1_MASK);
	XGpio_InterruptGlobalEnable(AxiGpioInstPtr);
	//
	return XST_SUCCESS;
}

/*
 * 如何设置AXI GPIO引脚方向
 *
 * XGpio gpio_instance;
 * int channel = 1; // 假设使用通道1
 * int bit_to_change = 3; // 假设要修改第3位
 *
 * // 初始化GPIO
 * XGpio_Initialize(&gpio_instance, XPAR_XGPIOPS_0_DEVICE_ID);
 *
 * // 读取当前方向寄存器的值
 * u32 current_direction = XGpio_GetDataDirection(&gpio_instance, channel);
 *
// 将第3位设置为输出(0)
 * u32 new_direction_output = current_direction & ~(1 << bit_to_change);
 * XGpio_SetDataDirection(&gpio_instance, channel, new_direction_output);
 *
 * // 将第3位设置为输入(1)
 * u32 new_direction_input = current_direction | (1 << bit_to_change);
 * XGpio_SetDataDirection(&gpio_instance, channel, new_direction_input);
 *
 */

int  SetupIntrSystem(XScuGic* IntcInstPtr, XGpio* AxiGpioInstPtr, u16 AxiGpioIntrId)
{
	//
	int Status;
	XScuGic_Config* IntcConfigPtr;

	// step1. 初始化中断控制器GIC
	IntcConfigPtr= XScuGic_LookupConfig(INTC_DEVICE_ID);
	if (NULL == IntcConfigPtr) {
		return XST_FAILURE;
	}

	Status = XScuGic_CfgInitialize(IntcInstPtr, IntcConfigPtr, IntcConfigPtr->CpuBaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	// step2. 在处理器中初始化异常处理功能
	Xil_ExceptionInit();

	// step3. 在处理器中为IRQ中断异常注册处理程序
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, IntcInstPtr);

	// step4. 在处理器中使能IRQ中断异常
	Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);

	// step5. 在GIC中为外设注册中断处理程序
	// XScuGic_Connect函数将中断源(Int_Id)与中断处理程序(Handler)关联起来;当中断发生时,GIC会调用中断处理程序来处理中断
	Status = XScuGic_Connect(IntcInstPtr, AxiGpioIntrId, (Xil_ExceptionHandler)AxiGpioIntrHandler, (void *)AxiGpioInstPtr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	// step6. 在GIC中设置外设中断的优先级和触发类型
	XScuGic_SetPriorityTriggerType(IntcInstPtr, AxiGpioIntrId, 0xA0, 0x1);

	// step7. 在GIC中使能外设中断
	XScuGic_Enable(IntcInstPtr, AxiGpioIntrId);

	//
	return XST_SUCCESS;
}

void AxiGpioIntrHandler(void *CallBackRef)
{
	//
	XGpio* AxiGpioInstPtr = (XGpio*)CallBackRef;
	u32 IntrStatus;
	//
	IntrStatus = XGpio_InterruptGetStatus(AxiGpioInstPtr);
	if (IntrStatus==1)
	{
		// 禁用中断
		XGpio_InterruptDisable(AxiGpioInstPtr, XGPIO_IR_CH1_MASK);
		printf("Interrupt Detected.\n");
		KeyPress = 1;
	}
	//
	return;
}

int main()
{
	//
	int Status;
	u32 LedValue;
	u32 KeyValue;
	//
	printf("AXI GPIO Interrupt Control LED Test\n");
	//
	Status = PsGpioInit(&PsGpioInst);
	if (Status == XST_FAILURE) {
		printf("PS GPIO Init Failed.\n");
	}
	//
	Status = AxiGpioInit(&AxiGpioInst);
	if (Status == XST_FAILURE) {
		printf("AXI GPIO Init Failed.\n");
	}
	//
	Status = SetupIntrSystem(&IntcInst, &AxiGpioInst, AXIGPIO_INTR_ID);
	if (Status == XST_FAILURE) {
		printf("Setup Interrupt System Failed.\n");
	}
	//
	while(1)
	{
		if (KeyPress==1)
		{
			usleep(200000);
			KeyValue = XGpio_DiscreteRead(&AxiGpioInst, AXIGPIO_CHANNEL1);
			if ((KeyValue & (1 << 0)) == 0) {
				LedValue = ~XGpioPs_ReadPin(&PsGpioInst, PS_LED0_GPIO_PIN);
				XGpioPs_WritePin(&PsGpioInst, PS_LED0_GPIO_PIN, LedValue);
			}
			KeyPress = 0;
			XGpio_InterruptClear(&AxiGpioInst, XGPIO_IR_CH1_MASK);
			XGpio_InterruptEnable(&AxiGpioInst, XGPIO_IR_CH1_MASK);
		}
	}
	//
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2304802.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

题海拾贝:扫雷

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》 欢迎点赞&#xff0c;关注&#xff01; 1、题…

Deepseek本地部署小实践(c盘)

目录 前言 一、安装ollama 二、打开终端执行run 三、可视化 前言 小鲸鱼出来以后看到很多大佬本地部署AI&#xff0c;自己也想试一试&#xff0c;第一次部署AI&#xff0c;选了一个简单的办法&#xff0c;实践一下&#xff0c;写得比较粗糙。 一、安装ollama 先简单的介绍…

详细解析d3dx9_27.dll丢失怎么办?如何快速修复d3dx9_27.dll

运行程序时提示“d3dx9_27.dll文件缺失”&#xff0c;通常由DirectX组件损坏或文件丢失引起。此问题可通过系统化修复方法解决&#xff0c;无需重装系统或软件。下文将详细说明具体步骤及注意事项。 一.d3dx9_27.dll缺失问题的本质解析 当系统提示“d3dx9_27.dll丢失”时&…

【LeetCode刷题之路】leetcode155.最小栈

LeetCode刷题记录 &#x1f310; 我的博客主页&#xff1a;iiiiiankor&#x1f3af; 如果你觉得我的内容对你有帮助&#xff0c;不妨点个赞&#x1f44d;、留个评论✍&#xff0c;或者收藏⭐&#xff0c;让我们一起进步&#xff01;&#x1f4dd; 专栏系列&#xff1a;LeetCode…

Vue全局变量的定义和使用,创建 Store变量、读取、修改

在VUE中&#xff0c;当需要各js、各页面都能读写的全局变量时&#xff0c;可以用store变量&#xff0c;从定义到使用的方法如下 一&#xff0e;定义变量&#xff0c;例&#xff1a;我们定一个全局变量gxh 找到 vue的/ src/ store路径, 在 modules文件夹下创建文件gvar.js 在…

基于Docker的前端环境管理:从开发环境到生产部署的实现方案

# 基于Docker的前端环境管理&#xff1a;从开发环境到生产部署的实现方案 简介及前端开发环境挑战 简介 是一种容器化平台&#xff0c;可以将应用程序及其依赖项打包为一个容器&#xff0c;提供一种轻量级、可移植的环境。它能够简化开发、部署和运维的流程&#xff0c;提高…

单片机延时函数怎么写规范?

我们以前在开发产品的时候&#xff0c;肯定会碰到一些延时需求&#xff0c;比如常见的LED闪烁&#xff0c;按键消抖&#xff0c;控制IO口输出时序等等。 别小看延时&#xff0c;这个小问题&#xff0c;想做好&#xff0c;甚至要考虑到程序架构层面。 在开发板上&#xff0c;可能…

数据结构 1-2 线性表的链式存储-链表

1 原理 顺序表的缺点&#xff1a; 插入和删除移动大量元素数组的大小不好控制占用一大段连续的存储空间&#xff0c;造成很多碎片 链表规避了上述顺序表缺点 逻辑上相邻的两个元素在物理位置上不相邻 头结点 L&#xff1a;头指针 头指针&#xff1a;链表中第一个结点的存储…

vue2版本elementUI的table分页实现多选逻辑

1. 需求 我们需要在表格页上实现多选要求&#xff0c;该表格支持分页逻辑。 2. 认识属性 表格属性 参数说明类型可选值默认值data显示的数据array——row-key行数据的 Key&#xff0c;用来优化 Table 的渲染&#xff1b;在使用 reserve-selection 功能与显示树形数据时&…

设计模式-解释器模式、装饰器模式

解释器模式 定义 给分析对象定义一个语言&#xff0c;并定义语言的文法表示&#xff0c;再设计一个解释器来解释语言中的句子。也就是说&#xff0c;用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口&#xff0c;该接口解释一个特定的上下文。 类图 …

linux 命令+相关配置记录(持续更新...)

linux 命令记录相关配置记录 磁盘切换 cd D&#xff1a;#这里表示切换到D盘查看wsl 安装的linux 子系统 wsl --list -vwsl 卸载 linux 子系统 wsl --unregister -xxx # xxx 表示子系统的名字备份Linux 子系统 导出 wsl --export xxx yyy # xxx 表示子系统的名字 yyy 表示压…

【PDF预览】使用iframe实现pdf文件预览,加盖章

使用iframe实现pdf文件预览&#xff0c;以及在pdf上添加水印。另外还包括批注、打印、下载、缩放、分页等功能 <iframesrc"http://static.shanhuxueyuan.com/test.pdf"width"100%"height"100%"frameborder"0"></iframe>&l…

网络运维学习笔记(DeepSeek优化版)002网工初级(HCIA-Datacom与CCNA-EI)子网划分与协议解析

文章目录 子网划分与协议解析1. VLSM与CIDR技术解析1.1 VLSM&#xff08;Variable Length Subnetwork Mask&#xff0c;可变长子网掩码&#xff09;1.2 CIDR&#xff08;Classless Inter-Domain Routing&#xff0c;无类域间路由&#xff09; 2. 子网划分方法与计算2.1 常规划分…

在线骑行|基于SpringBoot的在线骑行网站设计与实现(源码+数据库+文档)

在线骑行网站系统 目录 基于SpringBoot的在线骑行设计与实现 一、前言 二、系统设计 三、系统功能设计 5.1用户信息管理 5.2 路线攻略管理 5.3路线类型管理 5.4新闻赛事管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取…

BUUCTF-Web方向21-25wp

目录 [HCTF 2018]admin弱口令session伪造 [MRCTF2020]你传你&#x1f40e;呢[护网杯 2018]easy_tornado[ZJCTF 2019]NiZhuanSiWei[MRCTF2020]Ez_bypass第一层第二层 [HCTF 2018]admin 打开环境&#xff0c;有三处提示&#xff0c;一个跳转链接&#xff0c;一个登录注册&#x…

软考——WWW与HTTP

1.万维网&#xff08;world wide web&#xff09; 是一个规模巨大的、可以资源互联的资料空间。由URL进行定位&#xff0c;通过HTTP协议传送给使用者&#xff0c;又由HTML来进行文件的展现。 它的主要组成部分是&#xff1a;URL、HTTP、HTML。 &#xff08;1&#xff09;URL…

GO 进行编译时插桩,实现零码注入

Go 编译时插桩 Go 语言的编译时插桩是一种在编译阶段自动注入监控代码的技术&#xff0c;目的是在不修改业务代码的情况下&#xff0c;实现对应用程序的监控和追踪。 基本原理 Go 编译时插桩的核心思想是通过在编译过程中对源代码进行分析和修改&#xff0c;将监控代码注入到…

为人工智能驱动的交通研究增强路面传感器数据采集

论文标题 英文标题&#xff1a;Enhancing Pavement Sensor Data Harvesting for AI-Driven Transportation Studies 中文标题&#xff1a;为人工智能驱动的交通研究增强路面传感器数据采集 作者信息 Manish Kumar Krishne Gowda Purdue University, 465 Northwestern Avenue,…

unordered_set和unordered_map的使用

Hello&#xff0c;今天我来为大家介绍一下前几年才刚刚新出的两个容器——unordered_map和unordered_set&#xff0c;这两个容器属于是map系列和set系列中的一种&#xff0c;和map/set不同的是它们的底层&#xff0c;map/set的底层是红黑树&#xff0c;而unordered_map/unorder…

【实体类】分层设计

【实体类】分层设计 【一】实体类的PO、VO、DO、DAO、BO、DTO、POJO有什么区别【1】PO&#xff08;Persistent Object&#xff09;【2】VO&#xff08;View Object&#xff09;【3】DO&#xff08;Domain Object&#xff09;【4】DAO&#xff08;Data Access Object&#xff09…