ZYNQ+Vivado2015.2系列(十四)按键中断控制LED亮灭

前面我们介绍了按键中断,其实我们稍作修改就可以用按键控制LED了。做个小实验,两个按键分别控制两个led亮灭。

板子:zc702。

硬件部分

添加zynq核:

勾选串口用于打印信息,勾选EMIO,我们控制两个led,所以需要2bit

PL 到PS的中断勾选上:

PL时钟什么的都用不到,我们用的按键不需要时钟,EMIO属于PS。

再添加一个concat IP用于合并两路按键信号:

最后连接完的系统:

In0,In1和GPIO_0需要自己右键make external。

生成顶层文件。

添加约束文件:

在顶层模块找到相应的信号名称,将SW0,SW1连接到SW5,SW7;将GPIO[1:0]连接到两个led:
#GPIO PMOD1
set_property PACKAGE_PIN E15 [get_ports {gpio_0_tri_io[0]}]
set_property IOSTANDARD LVCMOS25 [get_ports {gpio_0_tri_io[0]}]
set_property PACKAGE_PIN D15 [get_ports {gpio_0_tri_io[1]}]
set_property IOSTANDARD LVCMOS25 [get_ports {gpio_0_tri_io[1]}]

#SW5 SW7
set_property PACKAGE_PIN G19 [get_ports {SW0[0]}]
set_property IOSTANDARD LVCMOS25 [get_ports {SW0[0]}]
set_property PACKAGE_PIN F19 [get_ports {SW1[0]}]
set_property IOSTANDARD LVCMOS25 [get_ports {SW1[0]}]

生成bit文件。打开SDK。

软件部分

原理就是产生中断后在中断处理程序里完成控制led的操作。

#include
#include "xscugic.h"
#include "xil_exception.h"
#include "xgpiops.h"
#include "sleep.h"

#define SW1_INT_ID 61
#define SW2_INT_ID 62
#define INTC_DEVICE_ID XPAR_PS7_SCUGIC_0_DEVICE_ID

static XScuGic INTCInst;
static void SW_intr_Handler(void *param);
static int IntcInitFunction(u16 DeviceId);
static int cnt1=0,cnt2=0;

static void SW_intr_Handler(void *param){
int sw_id = (int)param;

XGpioPs psGpioInstancePtr;
XGpioPs_Config* GpioConfigPtr;
int xStatus;
//-- EMIO的初始化
GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,GpioConfigPtr,
GpioConfigPtr->BaseAddr);

if(sw_id==1){
cnt1++;
XGpioPs_SetDirectionPin(&psGpioInstancePtr, 54,1);
XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 54,1);
if(cnt1%2){
XGpioPs_WritePin(&psGpioInstancePtr, 54, 1);//EMIO的第0位输出1
}else{
XGpioPs_WritePin(&psGpioInstancePtr, 54, 0);
}
XGpioPs_IntrClearPin(&psGpioInstancePtr, 54);
}
if(sw_id==2){
cnt2++;
XGpioPs_SetDirectionPin(&psGpioInstancePtr, 55,1);
XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 55,1);
if(cnt2%2){
XGpioPs_WritePin(&psGpioInstancePtr, 55, 1);//EMIO的第1位输出0
}
else{
XGpioPs_WritePin(&psGpioInstancePtr, 55, 0);
}
XGpioPs_IntrClearPin(&psGpioInstancePtr, 55);
}
printf("led %d on\n\r",sw_id);
}

int IntcInitFunction(u16 DeviceId){

XScuGic_Config *IntcConfig;
int status;
// Interrupt controller initialisation
IntcConfig = XScuGic_LookupConfig(DeviceId);
status = XScuGic_CfgInitialize(&INTCInst, IntcConfig,
IntcConfig->CpuBaseAddress);
if(status != XST_SUCCESS) return XST_FAILURE;
// Call to interrupt setup
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
&INTCInst);
Xil_ExceptionEnable();
// Connect SW1~SW3 interrupt to handler
status = XScuGic_Connect(&INTCInst,
SW1_INT_ID,
(Xil_ExceptionHandler)SW_intr_Handler,
(void *)1);
if(status != XST_SUCCESS) return XST_FAILURE;
status = XScuGic_Connect(&INTCInst,
SW2_INT_ID,
(Xil_ExceptionHandler)SW_intr_Handler,
(void *)2);
if(status != XST_SUCCESS) return XST_FAILURE;

// Enable SW1~SW3 interrupts in the controller
XScuGic_Enable(&INTCInst, SW1_INT_ID);
XScuGic_Enable(&INTCInst, SW2_INT_ID);
return XST_SUCCESS;
}
int main(void){

printf("key interrupt control leds\n\r");
IntcInitFunction(INTC_DEVICE_ID);
while(1);
return 0;
}

定义使用GIC需要的两个结构体:XScuGic  XScuGic_Config
初始化GIC:XScuGic_LookupConfig  XScuGic_CfgInitialize

Xil_ExceptionRegisterHandler  //在ARM里注册中断异常

Xil_ExceptionEnable  //异常使能

XScuGic_Connect  //连接到自定义中断处理函数

XScuGic_Enable  //GIC使能

自定义异常处理函数SW_intr_Handler()里:

传进来的参数表明当前是哪个按键按下;

定义使用GPIO需要的两个结构体:XGpioPs  XGpioPs_Config

EMIO初始化:XGpioPs_LookupConfig  XGpioPs_CfgInitialize

XGpioPs_SetDirectionPin  //设置GPIO是输入还是输出,1表示输出

XGpioPs_SetOutputEnablePin  //GPIO输出使能

XGpioPs_WritePin  //向pin脚写数据

XGpioPs_IntrClearPin  //废弃这个pin

---------------------
作者:ChuanjieZhu
来源:CSDN
原文:https://blog.csdn.net/u014485485/article/details/79069047

最新文章

最新文章