ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

009-Zynq基操之如何去玩转PL向PS的中断(对新手友好,走过路过千万不要错过)

2026/9/12 2:03:42 拓冰建站 浏览量
009-Zynq基操之如何去玩转PL向PS的中断(对新手友好,走过路过千万不要错过)

文章目录

  • 前言
  • 一、PL-PS的中断是啥?
  • 二、PL-PS端中断详细步骤
    • 1.ZYNQ核配置
    • 2.PS端中断函数配置
    • 3.需要拓展多个中断函数
  • 总结


前言

本设计跟我的ZYNQ实战合集专栏中的脉冲触发电路有关系,也正好趁这个机会讲述一下PL-PS的中断系统,如何去触发中断,使其能够做一些响应工作。本文所提及的中断只涉及到PL向PS触发的中断,并不涉及到PS端双核的中断,做这个主要目的也就是为了让大家更加熟悉这个中断系统,并且能够用到自己的实际工程项目之中去。他的应用领域主要是,比如你用脉冲驱动电机运行,当这个电机停止运动了以后,根据我所给出的脉冲触发代码,会在停止脉冲输出后反馈一个中断信号,那么通过检测这个中断信号就可以执行一些特定的功能,比如电机停止以后你需要采集图像的某些特征,这个中断信号就是你可以开始采集图像特征的起始点。


一、PL-PS的中断是啥?

直接上图,我们也不说什么较为复杂的中断理论知识,我们直接将目光移到左下方Programmable Logic模块那里,可以看到它有一根显示16的线连接到了SPI那里,这个就是PL向PS可以触发的中断,约16个,中断号分别是61-68,和84-91。一旦PL这边有触发信号产生,就能够进入PS端设置的中断函数内,在中断函数中我们执行这条中断线上对应的任务。
在这里插入图片描述
下面这张图也说明的比较详细,PL到PS总共有16个中断号,其中触发方式也说得比较清楚,高电平或者上升沿触发。之前我在文章中做的脉冲触发模块,中断信号就是拉高一段时期,因此可以对应的触发PS上的中断。
在这里插入图片描述

二、PL-PS端中断详细步骤

1.ZYNQ核配置

interrupt_one是引出来的中断信号,如果我们有多个中断信号的话,只需要调用concat的ip核,输入接多个中断信号,输出一条线接到IRQ_F2P上,编译以后就会自动拓展IRQ的位宽,不需要我们自己设计。按照我的脉冲触发代码为例,只需要把motor_exti例化到interrupt_one这个信号处即可。
在这里插入图片描述
在这里插入图片描述

2.PS端中断函数配置

首先是两个初始化函数,这种你只需要学会去配就行了。你需要做更改的就是我注释PL中断下的三行代码,status=开始那个,如果你有两个PL中断,一个中断号为61,一个中断号为62,那么只需要复制粘贴三行代码,然后把里面的0改成1即可,在define里面注释一下。

#include "math.h"
#include "stdlib.h"
#include "interrupt.h"
int initIntr()
{int status;Xil_ExceptionInit();ScuGicCfgPtr = XScuGic_LookupConfig(GIC_ID);status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);if(status != XST_SUCCESS){return status;}Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);//pl中断status = XScuGic_Connect(&ScuGic,F2P_INTR0_ID,(Xil_ExceptionHandler)f2pIntr0Handler,&ScuGic);IntcTypeSetup(&ScuGic, F2P_INTR0_ID, INT_TYPE_RISING_EDGE);XScuGic_Enable(&ScuGic, F2P_INTR0_ID);Xil_ExceptionEnable();return XST_SUCCESS;
}void IntcTypeSetup(XScuGic *InstancePtr, int intId, int intType)
{int mask;intType &= INT_TYPE_MASK;mask = XScuGic_DistReadReg(InstancePtr, INT_CFG0_OFFSET + (intId/16)*4);mask &= ~(INT_TYPE_MASK << (intId%16)*2);mask |= intType << ((intId%16)*2);XScuGic_DistWriteReg(InstancePtr, INT_CFG0_OFFSET + (intId/16)*4, mask);
}

对应的中断函数,这里面可以放你想要进行中断操作的函数,我这里是用来计数。

void f2pIntr0Handler(void * callbackref)
{static u8 count;count++;printf("count=%d",count);
}

h文件,需要更改的就是F2P_INTR0_ID 61,这个是对应的中断号

/** interrupt.h**  Created on: 2023年12月27日*      Author: 16799*/#ifndef SRC_INTERRUPT_H_
#define SRC_INTERRUPT_H_
#endif /* SRC_INTERRUPT_H_ *//** interrupt.h**  Created on: 2020年6月22日*      Author: hewei*/#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_
#include <stdio.h>
#include "xscugic.h"
#include "xparameters.h"
#include "xil_mmu.h"
#include "xil_types.h"
#include "xscutimer.h"
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "xil_cache.h"
#include "xil_printf.h"
#include "xil_cache.h"
#define INT_CFG0_OFFSET 0x00000C00#define F2P_INTR0_ID 61#define GIC_ID XPAR_PS7_SCUGIC_0_DEVICE_ID
#define INT_TYPE_RISING_EDGE    0x03
#define INT_TYPE_HIGHLEVEL      0x01
#define INT_TYPE_MASK           0x03
XScuGic ScuGic;
XScuGic_Config * ScuGicCfgPtr;
int initIntr();
void IntcTypeSetup(XScuGic *InstancePtr, int intId, int intType);
void f2pIntr0Handler(void * callbackref);//行中断
#endif /* _INTERRUPT_H_ */

3.需要拓展多个中断函数

c文件中,initIntr函数里面在第一条中断,也就是中断0的下方加入

	status = XScuGic_Connect(&ScuGic,F2P_INTR1_ID,(Xil_ExceptionHandler)f2pIntr1Handler,&ScuGic);IntcTypeSetup(&ScuGic, F2P_INTR1_ID, INT_TYPE_RISING_EDGE);XScuGic_Enable(&ScuGic, F2P_INTR1_ID);

h文件里面加入中断号以及中断函数1

#define F2P_INTR1_ID 62
void f2pIntr1Handler(void * callbackref);//行中断

在你的主函数里面只需要初始化initIntr函数即可。


总结

今天吃了苗家菜酸汤鱼,感觉味道不错,值得下次再去一次。特别是有一个酸汤丸子,很新奇的东西。