sdk模板程序:gpio_irq - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

说明

  • AXI_GPIO的中断,只区分CH1和CH2,不区分具体是哪个bit产生的IRQ
  • AXI_GPIO的中断,每按键一次,会产生2次中断,上升沿一次,下降沿一次。这让人很难用。

程序

/*
 * 使用PS_GPIO实现了按键控制LED功能:
 * PS端按键按下→PL端的灯亮起,松开熄灭
 * PL端按键按下→PS端的灯亮起,松开熄灭
*/
#include "ACZ702_Lib/COMMON.h"


#define PS_KEY 15
#define PS_LED 11

#define PS_EMIO_KEY (54+0)
#define PS_EMIO_KEY2 (54+1)
#define PS_EMIO_LED (54+2)

uint8_t State=0;

void PS_GPIO_IRQ_Handler(void *CallBackRef, uint32_t Bank, uint32_t Status)
{
    if(XGpioPs_IntrGetStatusPin(&GpioPs, PS_EMIO_KEY)) {
    	State=!State; PS_GPIO_SetPort(PS_LED,State);

    	printf("ps_emio_key pressed!\r\n");
    	XGpioPs_IntrClearPin(&GpioPs, PS_EMIO_KEY);

    }

    if(XGpioPs_IntrGetStatusPin(&GpioPs, PS_EMIO_KEY2)) {
    	State=!State; PS_GPIO_SetPort(PS_LED,State);

    	printf("ps_emio_key2 pressed!\r\n");
    	XGpioPs_IntrClearPin(&GpioPs, PS_EMIO_KEY2);

    }

    /*
     * 说明,不知道为什么ps_io能触发中断,但这里的if函数判断一直为0?但ps_emio可以正常工作
     */

    if(XGpioPs_IntrGetStatusPin(&GpioPs, PS_KEY)) {
    //if(PS_GPIO_GetPort(PS_KEY)==0){
    	State=!State; PS_GPIO_SetPort(PS_LED,State);

    	//printf("ps_io_key pressed!\r\n");
    	XGpioPs_IntrClearPin(&GpioPs, PS_KEY);

    }
}

//GPIO的中断处理程序,只要GPIO通道0有电平变化就会进入该中断
void AXI_GPIO_IRQ_Handler(void *CallbackRef)
{
    uint32_t Key_Int_State;

    //判断哪一位出现中断(只有bit0和bit1有效,分别对应ch1和ch2,不能区分ch1和ch2中具体是哪个gpio)
    //axi-gpio有点扯淡,每按一次按键,会触发2次中断,上升沿一次,下降沿一次。
    Key_Int_State = XGpio_InterruptGetStatus(&AXI_GPIO0);

    /* ↓↓↓用户处理↓↓↓ */
	if(Key_Int_State & 0b00000001) {
		State=!State; PS_GPIO_SetPort(PS_LED,State);

//		if(AXI_GPIO_GetPin(&AXI_GPIO0,XGPIO_IR_CH1_MASK,0)==1)
//			printf("axi_ch1_io_key0 pressed!\r\n");
//
//		if(AXI_GPIO_GetPin(&AXI_GPIO0,XGPIO_IR_CH1_MASK,1)==1)
//			printf("axi_ch1_io_key1 pressed!\r\n");
	}
	if(Key_Int_State & 0b00000010) {
	}
    /* ↑↑↑结束处理↑↑↑ */

    //清除中断标志
    XGpio_InterruptClear(&AXI_GPIO0, XGPIO_IR_CH1_MASK);
}

/*
 * PS_GPIO的地址0xe000a000
 */

int main_gpio_irq(void)
{
	//GIC通用中断控制器初始化
	ScuGic_Init();

	{
		//初始化AXI GPIO 驱动程序
		AXI_GPIO_Init(&AXI_GPIO0, XPAR_AXI_GPIO_0_DEVICE_ID);

		//设置KEY_S1方向
		AXI_GPIO_SetPin_Dir(&AXI_GPIO0,XGPIO_IR_CH1_MASK,0,INPUT);
		AXI_GPIO_SetPin_Dir(&AXI_GPIO0,XGPIO_IR_CH1_MASK,1,INPUT);

		//初始化AXI GPIO中断
		AXI_GPIO_Intc_Init(&AXI_GPIO0,XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR,
				XGPIO_IR_CH1_MASK, AXI_GPIO_IRQ_Handler);
	}


	{
		//初始化PS端GPIO
		PS_GPIO_Init();
		PS_GPIO_SetMode(PS_LED, OUTPUT, 0);

		//设置PS_KEY(MIO47)方向为输入
		PS_GPIO_SetMode(PS_EMIO_KEY, INPUT, 0);
		//设置按键PS_KEY的中断为边沿敏感
		PS_GPIO_SetInt(PS_EMIO_KEY,XGPIOPS_IRQ_TYPE_EDGE_RISING);

		//设置PS_KEY(MIO47)方向为输入
		PS_GPIO_SetMode(PS_EMIO_KEY2, INPUT, 0);
		//设置按键PS_KEY的中断为边沿敏感
		PS_GPIO_SetInt(PS_EMIO_KEY2,XGPIOPS_IRQ_TYPE_EDGE_RISING);

		//设置PS_KEY(MIO47)方向为输入
		PS_GPIO_SetMode(PS_KEY, INPUT, 0);
		//设置按键PS_KEY的中断为边沿敏感
		PS_GPIO_SetInt(PS_KEY,XGPIOPS_IRQ_TYPE_EDGE_RISING);

		//初始化PS GPIO中断
		PS_GPIO_Int_Init(PS_GPIO_IRQ_Handler);
	}


	while(1)
	{

	}
	return 0;
}


int main(void)
{
	main_gpio_irq();
	return 0;
}


波形

image

AXI_GPIO,每按下一次会触发2次中断。上升沿一次,下降沿一次。