OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 536|回复: 6

[XILINX] zynq7020如何设置PL端多个按键的中断

[复制链接]

5

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
95
金钱
95
注册时间
2022-6-19
在线时间
25 小时
发表于 2024-1-5 16:10:09 | 显示全部楼层 |阅读模式
1金钱
请问领航者文档中的AXI按键中断拓展训练,如何设置多个PL按键的中断啊,我使用两个通道中断函数,按下去就没有反应了。
  1. #include "xparameters.h"
  2. #include "xgpiops.h"
  3. #include "xgpio.h"
  4. #include "xscugic.h"
  5. #include "xil_exception.h"
  6. #include "xplatform_info.h"
  7. #include <xil_printf.h>
  8. #include "sleep.h"

  9. /************************** Constant Definitions *****************************/

  10. //以下常量映射到xparameters.h文件
  11. #define GPIOPS_DEVICE_ID    XPAR_XGPIOPS_0_DEVICE_ID     //PS端GPIO器件ID
  12. #define AXI_GPIO_DEVICE_ID  XPAR_AXI_GPIO_0_DEVICE_ID    //PL端AXI GPIO器件ID
  13. #define SCUGIC_ID           XPAR_SCUGIC_SINGLE_DEVICE_ID //通用中断控制器ID
  14. #define AXI_GPIO_INT_ID     XPAR_FABRIC_GPIO_0_VEC_ID    //PL端AXI GPIO中断ID

  15. #define MIO_LED       0                                  //LED 连接到 MIO0
  16. #define LED2          8                                  //LED连接到MIO8
  17. #define KEY_CHANNEL1  1                                  //PL 按键0使用 AXI GPIO 通道 1
  18. #define KEY_CH1_MASK  XGPIO_IR_CH1_MASK                  //通道 1的中断位定义
  19. #define KEY_CHANNEL2  2                                  //PL 按键1使用 AXI GPIO 通道 2
  20. #define KEY_CH2_MASK  XGPIO_IR_CH2_MASK                  //通道 2的中断位定义

  21. /************************** Function Prototypes ******************************/
  22. void instance_init();
  23. int setup_interrupt_system(XScuGic *gic_inst_ptr, XGpio *axi_gpio_inst_ptr,
  24.      u16 AXI_GpioIntrId);
  25. static void intr_handler(void *callback_ref);
  26. int setup_interrupt_system2(XScuGic *gic_inst_ptr, XGpio *axi_gpio_inst_ptr, u16 AXI_GpioIntrId);
  27. static void intr_handler2(void *callback_ref);

  28. /**************************Global Variable Definitions ***********************/
  29. XGpioPs gpiops_inst;        //PS端GPIO驱动实例
  30. XGpio   axi_gpio_inst;      //PL端AXI GPIO驱动实例
  31. XScuGic scugic_inst;        //通用中断控制器驱动实例
  32. int led_value=1;            //ps端LED0的显示状态
  33. int led1_value=1;            //ps端LED1的显示状态

  34. /************************** Function Definitions *****************************/

  35. int main(void)
  36. {
  37.      int status;
  38.      int status2;

  39.      //初始化各器件驱动
  40.      instance_init();

  41.      xil_printf("AXI_Gpio interrupt test \r\n");

  42.      //设置LED所连接的MIO引脚的方向为输出并使能输出
  43.      XGpioPs_SetDirectionPin(&gpiops_inst, MIO_LED, 1);
  44.      XGpioPs_SetOutputEnablePin(&gpiops_inst, MIO_LED, 1);
  45.      XGpioPs_WritePin(&gpiops_inst, MIO_LED, led_value);

  46.      XGpioPs_SetDirectionPin(&gpiops_inst, LED2, 1);
  47.      XGpioPs_SetOutputEnablePin(&gpiops_inst, LED2, 1);
  48.      XGpioPs_WritePin(&gpiops_inst, LED2, led_value);

  49.      //建立中断,出现错误则打印信息并退出
  50.      status = setup_interrupt_system(&scugic_inst, &axi_gpio_inst, AXI_GPIO_INT_ID);
  51.      if (status != XST_SUCCESS) {
  52.          xil_printf("Setup interrupt system failed\r\n");
  53.          return XST_FAILURE;
  54.      }

  55.      status2 = setup_interrupt_system2(&scugic_inst, &axi_gpio_inst, AXI_GPIO_INT_ID);
  56.      if (status2 != XST_SUCCESS) {
  57.          xil_printf("Setup interrupt system failed\r\n");
  58.          return XST_FAILURE;
  59.      }

  60.      return XST_SUCCESS;
  61. }

  62. //初始化各器件驱动
  63. void instance_init()
  64. {
  65.      XScuGic_Config *scugic_cfg_ptr;
  66.      XGpioPs_Config *gpiops_cfg_ptr;

  67.      //初始化中断控制器驱动
  68.         scugic_cfg_ptr = XScuGic_LookupConfig(SCUGIC_ID);
  69.      XScuGic_CfgInitialize(&scugic_inst, scugic_cfg_ptr, scugic_cfg_ptr->CpuBaseAddress);

  70.      //初始化PS端  GPIO驱动
  71.      gpiops_cfg_ptr = XGpioPs_LookupConfig(GPIOPS_DEVICE_ID );
  72.      XGpioPs_CfgInitialize(&gpiops_inst, gpiops_cfg_ptr, gpiops_cfg_ptr->BaseAddr);

  73.      //初始化PL端  AXI GPIO驱动
  74.      XGpio_Initialize(&axi_gpio_inst, AXI_GPIO_DEVICE_ID);
  75. }

  76. //建立中断系统,使能KEY按键的下降沿中断
  77. //  [url=home.php?mod=space&uid=271674]@param[/url]   GicInstancePtr是一个指向XScuGic驱动实例的指针
  78. //  @param   gpio是一个指向连接到中断的GPIO组件实例的指针
  79. //  @param   GpioIntrId是Gpio中断ID
  80. //  @return  如果成功返回XST_SUCCESS, 否则返回XST_FAILURE
  81. int setup_interrupt_system(XScuGic *gic_inst_ptr, XGpio *axi_gpio_inst_ptr, u16 AXI_GpioIntrId)
  82. {
  83.      //设置并使能中断异常
  84.      Xil_ExceptionInit();
  85.      Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
  86.              (Xil_ExceptionHandler) XScuGic_InterruptHandler, gic_inst_ptr);
  87.      Xil_ExceptionEnable();

  88.      //设置中断源的优先级和触发类型(高电平触发)
  89.      XScuGic_SetPriorityTriggerType(gic_inst_ptr, AXI_GpioIntrId, 0xA0, 0x01);
  90.      //为中断设置中断处理函数
  91.      XScuGic_Connect(gic_inst_ptr, AXI_GpioIntrId,
  92.              (Xil_ExceptionHandler) intr_handler, (void *) axi_gpio_inst_ptr);

  93.      //使能来自于axi_Gpio器件的中断
  94.      XScuGic_Enable(gic_inst_ptr, AXI_GpioIntrId);

  95.      //配置PL端 AXI GPIO
  96.          //设置 AXI GPIO 通道 1方向为输入
  97.      XGpio_SetDataDirection(axi_gpio_inst_ptr, KEY_CHANNEL1, 1);
  98.      XGpio_InterruptEnable(axi_gpio_inst_ptr, KEY_CH1_MASK);  //使能通道1的中断
  99.      XGpio_InterruptGlobalEnable(axi_gpio_inst_ptr);          //使能axi gpio全局中断

  100.      return XST_SUCCESS;
  101. }

  102. //中断处理函数
  103. //  @param   CallBackRef是指向上层回调引用的指针
  104. static void intr_handler(void *callback_ref)
  105. {
  106.      XGpio *axi_gpio_inst_ptr = (XGpio *)callback_ref;
  107.      usleep(20000);                                               //延时20ms,按键消抖
  108.    if (XGpio_DiscreteRead(axi_gpio_inst_ptr, KEY_CHANNEL1) == 0) {//按键有效按下
  109.           print("Interrupt Detected!\r\n");
  110.           led_value = ~led_value;
  111.           XGpioPs_WritePin(&gpiops_inst, MIO_LED, led_value);          //改变LED显示状态
  112.           XGpio_InterruptDisable(axi_gpio_inst_ptr, KEY_CH1_MASK);//关闭 AXI GPIO中断使能
  113.     }
  114.           XGpio_InterruptClear(axi_gpio_inst_ptr, KEY_CH1_MASK);  //清除中断
  115.           XGpio_InterruptEnable(axi_gpio_inst_ptr, KEY_CH1_MASK); //使能AXI GPIO中断
  116. }

  117. int setup_interrupt_system2(XScuGic *gic_inst_ptr, XGpio *axi_gpio_inst_ptr, u16 AXI_GpioIntrId)
  118. {
  119.      //设置并使能中断异常
  120.      Xil_ExceptionInit();
  121.      Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
  122.              (Xil_ExceptionHandler) XScuGic_InterruptHandler, gic_inst_ptr);
  123.      Xil_ExceptionEnable();

  124.      //设置中断源的优先级和触发类型(高电平触发)
  125.      XScuGic_SetPriorityTriggerType(gic_inst_ptr, AXI_GpioIntrId, 0xA0, 0x01);
  126.      //为中断设置中断处理函数
  127.      XScuGic_Connect(gic_inst_ptr, AXI_GpioIntrId,
  128.              (Xil_ExceptionHandler) intr_handler2, (void *) axi_gpio_inst_ptr);

  129.      //使能来自于axi_Gpio器件的中断
  130.      XScuGic_Enable(gic_inst_ptr, AXI_GpioIntrId);

  131.      //配置PL端 AXI GPIO
  132.          //设置 AXI GPIO 通道 1方向为输入
  133.      XGpio_SetDataDirection(axi_gpio_inst_ptr, KEY_CHANNEL2, 1);
  134.      XGpio_InterruptEnable(axi_gpio_inst_ptr, KEY_CH2_MASK);  //使能通道1的中断
  135.      XGpio_InterruptGlobalEnable(axi_gpio_inst_ptr);          //使能axi gpio全局中断

  136.      return XST_SUCCESS;
  137. }

  138. static void intr_handler2(void *callback_ref)
  139. {
  140.      XGpio *axi_gpio_inst_ptr = (XGpio *)callback_ref;
  141.      usleep(20000);                                               //延时20ms,按键消抖
  142.    if (XGpio_DiscreteRead(axi_gpio_inst_ptr, KEY_CHANNEL2) == 0) {//按键有效按下
  143.           print("Interrupt Detected2!\r\n");
  144.           led1_value = ~led1_value;
  145.           XGpioPs_WritePin(&gpiops_inst, MIO_LED, led1_value);          //改变LED显示状态
  146.           XGpio_InterruptDisable(axi_gpio_inst_ptr, KEY_CH2_MASK);//关闭 AXI GPIO中断使能
  147.     }
  148.           XGpio_InterruptClear(axi_gpio_inst_ptr, KEY_CH2_MASK);  //清除中断
  149.           XGpio_InterruptEnable(axi_gpio_inst_ptr, KEY_CH2_MASK); //使能AXI GPIO中断
  150. }
复制代码


最佳答案

查看完整内容[请看2#楼]

在中断处理函数中,读取axi gpio通道的数据,然后看32位中每个数据位宽,对应bit位读到的是0,就是那个bit位连接的按键按下了
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

50

帖子

0

精华

高级会员

Rank: 4

积分
528
金钱
528
注册时间
2021-3-25
在线时间
109 小时
发表于 2024-1-5 16:10:10 | 显示全部楼层
lzqstm 发表于 2024-1-12 15:50
你好,我将位宽改为2后,绑定了两个PL引脚,想请问一下我把两个按键引脚互换,第0位给了了KEY1,第1位给 ...

在中断处理函数中,读取axi gpio通道的数据,然后看32位中每个数据位宽,对应bit位读到的是0,就是那个bit位连接的按键按下了
回复

使用道具 举报

0

主题

50

帖子

0

精华

高级会员

Rank: 4

积分
528
金钱
528
注册时间
2021-3-25
在线时间
109 小时
发表于 2024-1-6 11:15:32 | 显示全部楼层
如果是想实现PL多个按键的中断,可以AXI GPIO 的位宽设置为 2 位,然后分别路由到底
板上的两个 PL 端的按键 PL_KEY0、 PL_KEY1。(将例程中vivado工程中axi gpio软核ip的位宽改成2位位宽,并且引脚约束到PL端的两个按键引脚上,重新编译后导出硬件xsa文件到vitis,然后重新编写C语言代码。)

axi_gpio.png


回复

使用道具 举报

5

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
95
金钱
95
注册时间
2022-6-19
在线时间
25 小时
 楼主| 发表于 2024-1-12 15:50:05 | 显示全部楼层
caojunye 发表于 2024-1-6 11:15
如果是想实现PL多个按键的中断,可以AXI GPIO 的位宽设置为 2 位,然后分别路由到底
板上的两个 PL 端的按 ...

你好,我将位宽改为2后,绑定了两个PL引脚,想请问一下我把两个按键引脚互换,第0位给了了KEY1,第1位给了KEY0,按照原来的代码,还是只有KEY0可以点亮灯,KEY1就没反应,系统怎么知道是哪个按键触发的中断呢
回复

使用道具 举报

5

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
95
金钱
95
注册时间
2022-6-19
在线时间
25 小时
 楼主| 发表于 2024-1-16 23:09:34 | 显示全部楼层
caojunye 发表于 2024-1-5 16:10
在中断处理函数中,读取axi gpio通道的数据,然后看32位中每个数据位宽,对应bit位读到的是0,就是那个bi ...

请问这里用XGpio_DiscreteRead这个函数如何判断呢,比如按键1按下,按键0不按下,代表触发了按键1的中断,那么这个时候XGpio_DiscreteRead读取到的值应该是???
回复

使用道具 举报

0

主题

50

帖子

0

精华

高级会员

Rank: 4

积分
528
金钱
528
注册时间
2021-3-25
在线时间
109 小时
发表于 2024-1-18 09:17:39 | 显示全部楼层
lzqstm 发表于 2024-1-16 23:09
请问这里用XGpio_DiscreteRead这个函数如何判断呢,比如按键1按下,按键0不按下,代表触发了按键1的中断 ...

PL_KEY0按下是0x02,PL_KEY1按下是0x01,两个按键都按下是0x00,可以参照压缩包里的.c文件里的代码 main.rar (2.26 KB, 下载次数: 2)
回复

使用道具 举报

5

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
95
金钱
95
注册时间
2022-6-19
在线时间
25 小时
 楼主| 发表于 2024-1-18 21:55:46 | 显示全部楼层
caojunye 发表于 2024-1-18 09:17
PL_KEY0按下是0x02,PL_KEY1按下是0x01,两个按键都按下是0x00,可以参照压缩包里的.c文件里的代码

成功了,感谢感谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-6-16 21:43

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表