高云FPGA系列教程(7):ARM GPIO外部中断

文章目录

    • @[toc]
      • GPIO中断简介
      • FPGA配置
      • 常用函数
      • MCU程序设计
      • 工程下载

本文是高云FPGA系列教程的第7篇文章。

本篇文章介绍片上ARM Cortex-M3硬核处理器GPIO外部的使用,演示按键中断方式来控制LED亮灭,基于TangNano 4K开发板。

参考文档:Gowin_EMPU(GW1NS-4C)软件编程 参考手册

GPIO中断简介

高云GN1NSR-4C共有16个GPIO,每个GPIO可配置成输入或输出模式,支持中断输入,触发方式可选择:上升沿、下降沿、高电平、低电平触发。

typedef enum
{
  GPIO_Int_Disable = 0,    /* Disable : Interrupt enable=0 */
  GPIO_Int_Low_Level,      /* Low-level : Interrupt enable=1 */
  GPIO_Int_High_Level,     /* High-level : Interrupt enable=1 & polarity=1 */
  GPIO_Int_Falling_Edge,   /* Falling edge : Interrupt enable=1 & type=1 */
  GPIO_Int_Rising_Edge     /* Rising edge : Interrupt enable=1 & polarity=1 & type=1 */
}GPIOInt_TypeDef;

中断优先级可通过NVIC进行设置,支持 0-7 级可编程中断优先级。

FPGA配置

FPGA工程中,EMPU需要使能GPIO外设。

高云FPGA系列教程(7):ARM GPIO外部中断_第1张图片

顶层设计如下:

/***************************************************************
 * Copyright(C), 2010-2022, WeChat:MCU149.
 * ModuleName : top_hdl.v 
 * Date       : 2023年9月19日
 * Time       : 20:19:39
 * Author     : WeChat:MCU149
 * Function   : gw1nsr-4c gpio interrupt demo
 * Version    : v1.0
 *      Version | Modify
 *      ----------------------------------
 *       v1.0    .....
 ***************************************************************/

module top_hdl(
    //Inputs
    input gclk,      // 27MHz
    input gresetn,    
    input key,
    input uart_rxd,

    //Outputs
    output uart_txd,
    output led
);

wire clk_60m;

wire arm_clk = clk_60m;
wire arm_resetn = gresetn;

wire arm_uart0_rxd = uart_rxd;
wire arm_uart0_txd;
wire [15:0] arm_gpio_in;
wire [15:0] arm_gpio_out;
wire [15:0] arm_gpio_outen;

assign uart_txd = arm_uart0_txd;
assign led = arm_gpio_out[1];
assign arm_gpio_in[0] = key;

Gowin_PLLVR pll_ut0(
    .clkout(clk_60m), //output clkout
    .clkin(gclk) //input clkin
);

Gowin_EMPU_Top arm_cortex_m3_core(
    //Inputs
    .sys_clk(arm_clk),
    .reset_n(arm_resetn),
    .uart0_rxd(arm_uart0_rxd), 
    .gpioin(arm_gpio_in[15:0]),

    //Outputs
    .uart0_txd(arm_uart0_txd),
    .gpioout(arm_gpio_out[15:0]),
    .gpioouten(arm_gpio_outen[15:0])
);

endmodule   //top_hdl end

LED连接到GPIO1,按键连接到GPIO0,按键按下是低电平。

常用函数

常用的GPIO驱动库函数如下:

//清除中断
void GPIO_IntClear(GPIO_TypeDef* GPIOx,uint32_t GPIO_Pin)
//获取中断触发状态
uint32_t GPIO_GetIntStatus(GPIO_TypeDef* GPIOx)
//中断使能
uint32_t GPIO_SetIntEnable(GPIO_TypeDef* GPIOx,uint32_t GPIO_Pin)
//设置高电平触发方式
void GPIO_SetIntHighLevel(GPIO_TypeDef* GPIOx,uint32_t GPIO_Pin)
//设置上升沿触发方式
void GPIO_SetIntRisingEdge(GPIO_TypeDef* GPIOx,uint32_t GPIO_Pin)
//设置低电平触发方式
void GPIO_SetIntLowLevel(GPIO_TypeDef* GPIOx,uint32_t GPIO_Pin)
//设置下降沿触发方式
void GPIO_SetIntFallingEdge(GPIO_TypeDef* GPIOx,uint32_t GPIO_Pin)

一般配置流程:

1. 配置GPIO输入输入模式,中断触发方式
2. 配置NVIC中断优先级
3. 使能NVIC和GPIO中断
4. 实现中断服务函数,并注释掉系统提供的中断服务函数

MCU程序设计

中断触发方式,可以在GPIO管脚初始化时进行设置,也可以通过单独的设定函数来设定。
首先是按键和LED对应的GPIO初始化,按键默认为高电平,按下是低电平,如果要按键按下触发中断,即从高电平到低电平,就设置成下降沿触发,如果想要按键松开触发中断,就设置为上升沿触发:

int gpio_init(void)
{
	GPIO_InitTypeDef init;
    NVIC_InitTypeDef InitTypeDef_NVIC;
    //KEY
//    init.GPIO_Int = GPIO_Int_Falling_Edge;     //press trig
    init.GPIO_Int = GPIO_Int_Rising_Edge; //release trig
	init.GPIO_Mode = GPIO_Mode_IN;
	init.GPIO_Pin = GPIO_Pin_0;
	GPIO_Init(GPIO0, &init);
    //LED
    init.GPIO_Int = GPIO_Int_Disable;
	init.GPIO_Mode = GPIO_Mode_OUT;
	init.GPIO_Pin = GPIO_Pin_1;
	GPIO_Init(GPIO0, &init);

//    GPIO_SetIntRisingEdge(GPIO0, GPIO_Pin_0);   //release trig
//    GPIO_SetIntFallingEdge(GPIO0, GPIO_Pin_0);     //press trig
    GPIO_SetIntEnable(GPIO0, GPIO_Pin_0);
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);

    InitTypeDef_NVIC.NVIC_IRQChannel = PORT0_0_IRQn;
    InitTypeDef_NVIC.NVIC_IRQChannelPreemptionPriority = 1;
    InitTypeDef_NVIC.NVIC_IRQChannelSubPriority = 1;
    InitTypeDef_NVIC.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&InitTypeDef_NVIC);

	return 0;
}

需要注意的是,中断触发方式只能设置成一种,不支持设置成上升沿和下降沿都触发中断。

中断服务函数的实现:

void PORT0_0_Handler(void)
{
    static uint16_t data = 0;
    
    data = ~data;
    gpio_write(data);
    printf("GPIO0_0 Interrupt Trig\r\n");

    GPIO_IntClear(GPIO0, GPIO_Pin_0);
}

需要把gw1ns4c_it.c文件里的中断服务函数注释掉。

高云FPGA系列教程(7):ARM GPIO外部中断_第2张图片

编译,加载bin文件运行:
高云FPGA系列教程(7):ARM GPIO外部中断_第3张图片

按下按键,在串口会输出日志,LED同时状态翻转。
高云FPGA系列教程(7):ARM GPIO外部中断_第4张图片

工程下载

本文基于TangNano 4K的开发板,配套工程在以下链接,包括Keil和GMD开发环境,都可以正常使用。

  • gw1nsr_4c_gpio_int_demo.rar

本文是高云FPGA系列教程的第7篇文章。

你可能感兴趣的:(高云,FPGA,ARM,GPIO,中断)