Zynq7020 SDK 初学篇(5)- 中断

1.开发背景

       基于上一个篇章 GPIO 使用,引入中断的使用。

2.开发需求

        PS 和 PL 按键输入中断,并输出对应的日志打印

3.开发环境

        Zynq7020 + Vivado2017.4

4.实现步骤

4.1 设计配置

PL Key0 56 

PS key0 12

PS key1 11

4.2 代码编写

GPIO 配置

#ifndef MSP_GPIO_H
#define MSP_GPIO_H

#include "xgpiops.h"

/* PS GPIO 映射 */
#define BOARD_LED0      (7)
#define BOARD_KEY0      (12)
#define BOARD_KEY1      (11)
#define CORE_LED        (0)

/* PL GPIO 映射 */
#define EMIO_LED0       (54)
#define EMIO_LED1       (55)
#define EMIO_KEY0       (56)


int mspGpio_Init(void);
void mspGpio_SetOutput(unsigned char gpioId, unsigned char state);
unsigned char mspGpio_GetInput(unsigned char gpioId);

XGpioPs* mspGpio_GetPsHandle(void);

#endif
#include "mspGpio.h"


/* gpio 设备,不知为何为 0 */
#define GPIO_DEVICE_ID      XPAR_XGPIOPS_0_DEVICE_ID    // 0

static XGpioPs s_psGpio = {0};

/* GPIO 初始化 */
int mspGpio_Init(void)
{
    /* 通过设备 ID 找到对应的配置指针 */
    XGpioPs_Config *ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);

    /* 通过配置指针初始化GPIO */
    int Status = XGpioPs_CfgInitialize(&s_psGpio, ConfigPtr,
                    ConfigPtr->BaseAddr);
    if (Status != XST_SUCCESS)
    {
        return -1;
    }

    /* 设置  GPIO 方向输出,这里为什么会共用一个 GPIO 结构体?参数一致?  */
    XGpioPs_SetDirectionPin(&s_psGpio, CORE_LED, 1);
    XGpioPs_SetDirectionPin(&s_psGpio, BOARD_LED0, 1);
    XGpioPs_SetDirectionPin(&s_psGpio, BOARD_KEY0, 0);
    XGpioPs_SetDirectionPin(&s_psGpio, BOARD_KEY1, 0);

    XGpioPs_SetDirectionPin(&s_psGpio, EMIO_LED0, 1);
    XGpioPs_SetDirectionPin(&s_psGpio, EMIO_LED1, 1);
    XGpioPs_SetDirectionPin(&s_psGpio, EMIO_KEY0, 0);

    /* 使能 GPIO */
    XGpioPs_SetOutputEnablePin(&s_psGpio, BOARD_LED0, 1);
    XGpioPs_SetOutputEnablePin(&s_psGpio, CORE_LED, 1);

    XGpioPs_SetOutputEnablePin(&s_psGpio, EMIO_LED0, 1);
    XGpioPs_SetOutputEnablePin(&s_psGpio, EMIO_LED1, 1);

    return 0;
}

/* 设置输出 */
void mspGpio_SetOutput(unsigned char gpioId, unsigned char state)
{
    XGpioPs_WritePin(&s_psGpio, gpioId, state);
}

/* 获取输入 */
unsigned char mspGpio_GetInput(unsigned char gpioId)
{
    return XGpioPs_ReadPin(&s_psGpio, gpioId);
}

/* 获取 PS GPIO 句柄 */
XGpioPs* mspGpio_GetPsHandle(void)
{
    return &s_psGpio;
}

        中断配置

#include "mspExit.h"

#include "xscugic.h"

#include "mspCore.h"
#include "mspGpio.h"
#include "mspTimer.h"

static XScuGic intc = {0};   //通用中断控制器驱动实例

//以下常量映射到xparameters.h文件
#define GPIO_DEVICE_ID      XPAR_XGPIOPS_0_DEVICE_ID      //PS端GPIO器件ID
#define INTC_DEVICE_ID      XPAR_SCUGIC_SINGLE_DEVICE_ID  //通用中断控制器ID
#define GPIO_INTERRUPT_ID   XPAR_XGPIOPS_0_INTR           //PS端GPIO中断ID

static void intr_handler(void *callback_ref);

/* 初始化中断接口 */
int setup_interrupt_system(XScuGic *gic_ins_ptr, XGpioPs *gpio, u16 GpioIntrId)
{
    int status;
    XScuGic_Config *IntcConfig;     //中断控制器配置信息

    //查找中断控制器配置信息并初始化中断控制器驱动
    IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
    if (NULL == IntcConfig)
    {
        return XST_FAILURE;
    }

    status = XScuGic_CfgInitialize(gic_ins_ptr, IntcConfig,
            IntcConfig->CpuBaseAddress);
    if (status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }

    //设置并使能中断异常
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
            (Xil_ExceptionHandler) XScuGic_InterruptHandler, gic_ins_ptr);
    Xil_ExceptionEnable();

    //为中断设置中断处理函数
    status = XScuGic_Connect(gic_ins_ptr, GpioIntrId,
            (Xil_ExceptionHandler) intr_handler, (void *) gpio);
    if (status != XST_SUCCESS)
    {
        return status;
    }

    //使能来自于Gpio器件的中断
    XScuGic_Enable(gic_ins_ptr, GpioIntrId);

    //设置KEY按键的中断类型为下降沿中断
    XGpioPs_SetIntrTypePin(gpio, BOARD_KEY0, XGPIOPS_IRQ_TYPE_EDGE_FALLING);
    XGpioPs_SetIntrTypePin(gpio, BOARD_KEY1, XGPIOPS_IRQ_TYPE_EDGE_FALLING);
    XGpioPs_SetIntrTypePin(gpio, EMIO_KEY0, XGPIOPS_IRQ_TYPE_EDGE_FALLING);

    //使能按键KEY中断
    XGpioPs_IntrEnablePin(gpio, BOARD_KEY0);
    XGpioPs_IntrEnablePin(gpio, BOARD_KEY1);
    XGpioPs_IntrEnablePin(gpio, EMIO_KEY0);

    return XST_SUCCESS;
}

/* 中断初始化 */
int mspExit_Init(void)
{
    setup_interrupt_system(&intc, mspGpio_GetPsHandle(), XPAR_XGPIOPS_0_INTR);
    return 0;
}

/* 中断处理 */
void intr_handler(void *callback_ref)
{
    /* 强行延时 */
//    mspTimer_DelayMs(100);
    XGpioPs *gpio = (XGpioPs *) callback_ref;

    //读取KEY按键引脚的中断状态,判断是否发生中断
    if (XGpioPs_IntrGetStatusPin(gpio, BOARD_KEY1))
    {
        printf("key = %d\r\n", BOARD_KEY1);
        XGpioPs_IntrClearPin(gpio, BOARD_KEY1);      //清除按键KEY中断
    }
    else if (XGpioPs_IntrGetStatusPin(gpio, BOARD_KEY0))
    {
        printf("key = %d\r\n", BOARD_KEY0);
        XGpioPs_IntrClearPin(gpio, BOARD_KEY0);      //清除按键KEY中断
    }
    else if (XGpioPs_IntrGetStatusPin(gpio, EMIO_KEY0))
    {
        printf("key = %d\r\n", EMIO_KEY0);
        XGpioPs_IntrClearPin(gpio, EMIO_KEY0);      //清除按键KEY中断
    }
}

4.3 运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值