Xilinx AX7103 MicroBalze学习笔记——MicroBlaze 按键中断实验

文章来源:Linest-5的CSDN博客

注:本文由作者授权转发,如需转载请联系作者本人

实验任务

通过 AXI GPIO 检测按键状态产生中断信号,中断控制器检测到中断后,给处理器发送中断请求,处理器接收到中断并控制 LED 灯的亮灭。

本实验基于 Vivado2018.2 实现。

实验框图

系统框图中,按键 KEY 作为 AXI GPIO 的输入,LED 作为 AXI GPIO 的输出。当 AXI GPIO 检测到按键状态发生变化时,AXI GPIO 就会产生一个中断信号传入中断控制器(AXI Interrupt Controller),中断控制器生成中断输出信号,传入 MicroBlaze 处理器,MicroBlaze 处理器通过接收到的中断信号控制 LED。中断控制器通过 AXI Interconnect 与 MicroBlaze 互联,MicroBlaze 可以通过 AXI 接口对中断控制器进行配置。

1.png

硬件设计(Vivado部分)

同之前 AXI GPIO 控制 LED 灯的操作,将 Hello World 实验另存为,命名为 key_intr 。

Block Design 搭建

添加两个AXI GPIO,分别控制 LED 和按键,并对 AXI GPIO IP 进行配置,其中连接到按键的 AXI GPIO 在GPIO位宽配置成1,而连接到 LED 灯的 GPIO 位宽配置成4,因为有4个 LED 灯需要控制。可以对IP的名称进行修改,以便更好的分辨。

按键

3.png

LED

3.png添加 AXI Interrupt Controller IP

无需对其进行配置

5.png

Number of Peripheral Interrupts(Auto):外围中断设备数量。此选项允许选择外围中断输入的数量。在 IP Integrator 中,此值由连接中断信号的数量自动确定。

Enable Fast Interrupt Logic:使能快速中断逻辑。此选项使 AXI INTC 能够在快速中断模式下工作。在这种模式下,AXI INTC 使用 interrupt_address 信号提供中断向量地址,处理器通过 processor_ack 信号确认中断。当选择单信号中断输出时,不可用快速中断模式。一般不使用。

Peripheral Interrupts Type:外部设备中断类型,该选项用于设置输入的中断信号。

Interrupts type - Edge or Level:中断类型-边缘或电平。此选项用于将输入中断设置为边缘或电平类型。0 表示电平类型,1 表示边缘类型。

Level type - High or Low:电平类型-高电平或低电平。0 表示低电平,1 表示高电平。

Edge type - Rising or Falling:边缘类型-上升沿或下降沿。0 表示下降沿,1 表示上升沿。

Processor Interrupt Type and Connection:处理器中断类型和连接。该目录用于设置中断控制器的输出信号。在该目录可以设置中断类型为电平或边缘类型,以及触发方式。

Interrupt Output Connection:该选项用于设置中断控制器输出的中断信号是单信号还是总线类型的信号。

点击自动连线

6.png

最后依次点击 Generate Output Products 和 Create HDL Wrapper

添加约束文件,和之前 AXI GPIO 控制LED灯的约束一致

set_property PACKAGE_PIN T6 [get_ports reset_n]

set_property IOSTANDARD LVCMOS15 [get_ports reset_n]

set_property PACKAGE_PIN N15 [get_ports uart_txd]

set_property PACKAGE_PIN P20 [get_ports uart_rxd]

set_property IOSTANDARD LVCMOS33 [get_ports uart_rxd]

set_property IOSTANDARD LVCMOS33 [get_ports uart_txd]

set_property PACKAGE_PIN R4 [get_ports diff_clk_clk_p]

set_property IOSTANDARD DIFF_SSTL15 [get_ports diff_clk_clk_p]

create_clock -period 5.000 [get_ports diff_clk_clk_p]

 

set_property IOSTANDARD LVCMOS33 [get_ports {gpio_rtl_2_tri_io[3]}]

set_property IOSTANDARD LVCMOS33 [get_ports {gpio_rtl_2_tri_io[2]}]

set_property IOSTANDARD LVCMOS33 [get_ports {gpio_rtl_2_tri_io[1]}]

set_property IOSTANDARD LVCMOS33 [get_ports {gpio_rtl_2_tri_io[0]}]

set_property IOSTANDARD LVCMOS33 [get_ports {gpio_rtl_0_tri_io[0]}]

set_property PACKAGE_PIN B13 [get_ports {gpio_rtl_2_tri_io[0]}]

set_property PACKAGE_PIN C13 [get_ports {gpio_rtl_2_tri_io[1]}]

set_property PACKAGE_PIN D14 [get_ports {gpio_rtl_2_tri_io[2]}]

set_property PACKAGE_PIN D15 [get_ports {gpio_rtl_2_tri_io[3]}]

set_property PACKAGE_PIN J21 [get_ports {gpio_rtl_0_tri_io[0]}]


生成比特流文件,导入到硬件并启动SDK进入到软件设计部分。

软件设计(SDK部分)

同之前的实验操作一样,新建一个应用工程

7.png

代码部分

在src文件夹中添加一个新的main.c文件,将下方的代码复制。

 #include "xparameters.h"

 #include "xintc.h"

 #include "xgpio.h"

 #include "sleep.h"

 

 #define KEY_DEV_ID XPAR_AXI_GPIO_KEY_DEVICE_ID //按键 AXI GPIO ID

 #define LED_DEV_ID XPAR_AXI_GPIO_LED_DEVICE_ID //LED AXI GPIO ID

 #define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID //中断控制器 ID

 #define EXCEPTION_ID XIL_EXCEPTION_ID_INT //中断异常 ID

 #define AXI_GPIO_INTR_ID XPAR_INTC_0_GPIO_0_VEC_ID //AXI GPIO 中断 ID

 

 static XIntc Intc; //中断控制器实例

 static XGpio KEY_Gpio; //GPIO 中断实例

 static XGpio LED_Gpio; //GPIO 实例

 

 int led_value; //LED 值

 int key_value; //按键值

 int Intr_times = 0; //有效中断计数

 int key_intr_flag = 0; //中断标志

 

 void GpioHandler(void *CallbackRef);

 

 int main(){

 xil_printf("AXI GPIO INTERRUPT TEST!\r\n");

 //AXI_GPIO 器件初始化

 XGpio_Initialize(&KEY_Gpio, KEY_DEV_ID);

 XGpio_Initialize(&LED_Gpio, LED_DEV_ID);

 //为指定的 GPIO 信道设置所有独立信号的输入/输出方向 0为输出

 XGpio_SetDataDirection(&LED_Gpio, 1, 0);

 //设置 LED 初始值,全1即初始时四个 LED 全亮

 XGpio_DiscreteWrite(&LED_Gpio, 1, 0x00);

 //设置 LED 为输入,1为输入

 XGpio_SetDataDirection(&KEY_Gpio, 1, 1);

 //初始化中断控制器

 XIntc_Initialize(&Intc, INTC_DEVICE_ID);

 //关联中断 ID 和中断服务函数

 XIntc_Connect(&Intc,AXI_GPIO_INTR_ID,(Xil_ExceptionHandler)GpioHandler,&KEY_Gpio );

//使能中断

 XGpio_InterruptEnable(&KEY_Gpio, 1);

 //使能全局中断

 XGpio_InterruptGlobalEnable(&KEY_Gpio);

 //在中断控制器上启用中断向量

 XIntc_Enable(&Intc,AXI_GPIO_INTR_ID);

 //启动中断控制器

 XIntc_Start(&Intc, XIN_REAL_MODE);

 //设置并打开中断异常处理

 Xil_ExceptionInit();

 Xil_ExceptionRegisterHandler(EXCEPTION_ID,

 (Xil_ExceptionHandler)XIntc_InterruptHandler,&Intc);

 Xil_ExceptionEnable();

 

 while(1){

 if(key_intr_flag){ //检测中断标志信号有效

 key_value = XGpio_DiscreteRead(&KEY_Gpio, 1); //读取按键值

 if(key_value == 0){ //检测按键是否按下

 if(Intr_times == 0) //根据有效中断数点亮 LED

 led_value = 0x0E;

 else if(Intr_times == 1)

 led_value = 0x0D;

 else if(Intr_times == 2)

 led_value = 0x0B;

 else

 led_value = 0x07;

 //按键按下后点亮对应 LED 灯

 XGpio_DiscreteWrite(&LED_Gpio, 1, led_value);

 xil_printf("i = %d\r\n",Intr_times); //打印当前的 Intr_times

 Intr_times = (Intr_times + 1)%4; //将计数值约束在 0 到 3 之间

 //延迟 1 秒消抖

 sleep(1);

 }

 key_intr_flag = 0; //中断标志清零

 }

 }

 return 0;

 }

 

 void GpioHandler(void *CallbackRef){

 XGpio *GpioPtr = (XGpio *)CallbackRef;

 key_intr_flag = 1; //接收到中断,标志信号拉高

 XGpio_InterruptDisable(GpioPtr, 1); //关闭中断

 XGpio_InterruptClear(GpioPtr, 1); //清除中断

 XGpio_InterruptEnable(GpioPtr, 1); //使能中断

 }

//代码来源正点原子

上板验证

添加串口,在 SDK Treminal 中添加串口,波特率设定为115200。

8.png

对工程 Run As -> GDB

9.png

最后连续间隔1s按键一次,就可以看到4个 LED 依次亮起,实验成功。

最新文章

最新文章