【兆易创新GD32H759I-EVAL开发板】11、EXTI按键中断学习
【学习目的】
在上一篇的文章中我认真的阅读了《GD32H737_757_759_User_Manual_Rev1.1_CN.pdf》,并且对配置EXTI的流程、寄存器做了详细的说明,这一篇进行代码编写并实现展示。
1、为方便后期管理,我先新建了一个头文件,类似官方的gd32h7xx.h,取名为lugl_gd32h7xx.h,定义的寄存器的地址,方便用宏来调用。
容内如下:
#ifndef __LUGL_GD32H7XX_H__
  • #define __LUGL_GD32H7XX_H__

  • //key1 -- PA0
  • //key2 -- PC13
  • //key3 -- PF8
  • //定义时钟地址
  • // RCU 基地址:0x5802 4400  
  • #define LU_RCU_AHB4EN (*(volatile uint32_t *)(uint32_t)(0x58024400+0x3C))
  •        
  • //定义GPIOA_CTL的地址:GPIOA基地址:0x5802 0000
  • #define LU_GPIOA_CTL   (*(volatile uint32_t *)(uint32_t)0x58020000)
  • #define LU_GPIOA_OMODE (*(volatile uint32_t *)(uint32_t)0x58020004)
  • #define LU_GPIOA_OSPD  (*(volatile uint32_t *)(uint32_t)0x58020008)
  • #define LU_GPIOA_OCTL  (*(volatile uint32_t *)(uint32_t)0x58020014)
  • #define LU_GPIOA_PUD   (*(volatile uint32_t *)(uint32_t)0x5802000C)
  • #define LU_GPIOA_TG           (*(volatile uint32_t *)(uint32_t)0x5802002C)

  • //定义GPIOA_CTL的地址:GPIOC基地址:0x5802 0080
  • #define LU_GPIOC_CTL   (*(volatile uint32_t *)(uint32_t)0x58020800)
  • #define LU_GPIOC_OMODE (*(volatile uint32_t *)(uint32_t)0x58020804)
  • #define LU_GPIOC_OSPD  (*(volatile uint32_t *)(uint32_t)0x58020808)
  • #define LU_GPIOC_OCTL  (*(volatile uint32_t *)(uint32_t)0x58020814)
  • #define LU_GPIOC_PUD   (*(volatile uint32_t *)(uint32_t)0x5802080C)
  •        
  • //GPIOF基地址:0x5802 1400
  • #define LU_GPIOF_CTL   (*(volatile uint32_t *)(uint32_t)0x58021400)
  • #define LU_GPIOF_OMODE (*(volatile uint32_t *)(uint32_t)(0x58021404))
  • #define LU_GPIOF_OSPD  (*(volatile uint32_t *)(uint32_t)(0x58021408))
  • #define LU_GPIOF_OCTL  (*(volatile uint32_t *)(uint32_t)(0x58021414))
  • #define LU_GPIOF_ISTAT (*(volatile uint32_t *)(uint32_t)(0x58021410))
  • #define LU_GPIOF_PUD   (*(volatile uint32_t *)(uint32_t)0x5802140C)
  •        
  • #define LU_SYSCFG_EXTISS3 (*(volatile uint32_t *)(uint32_t)0x58000414)

  • // EXTI 基地址:0x5800 0000

  • #define LU_EXTI_INTEN0    (*(volatile uint32_t *)(uint32_t)0x58000000)  //中断使能寄存器 0
  • #define LU_EXTI_FTEN0     (*(volatile uint32_t *)(uint32_t)0x5800000C)  //下降沿触发使能寄存器 0(EXTI_FTEN0)
  • #define LU_EXTI_PD0       (*(volatile uint32_t *)(uint32_t)0x58000014)  //挂起寄存器 0(EXTI_PD0)
  •        
  • //中断使能基地址:RCU 基地址:0x5802 4400 APB4 使能寄存器(RCU_APB4EN)地址偏移:0x4C
  • #define LU_RCU_APB4EN     (*(volatile uint32_t *)(uint32_t)0x5802444C)
  •        

  • #endif
  • 复制代码

    为了方便LED的管理,我新建了LED的配置与宏定义函数,其中led.h为配置板载的两个LED的驱动,内容如下:
    #ifndef __LED_H__
  • #define __LED_H__
  • #include "lugl_gd32h7xx.h"


  • //定义LED1_ON\OFF
  • #define LED1_ON     LU_GPIOF_OCTL |= (uint32_t)0x01<<10;
  • #define LED1_OFF     LU_GPIOF_OCTL &= ~((uint32_t)0x01<<10);

  • #define LED2_ON     LU_GPIOA_OCTL |= (uint32_t)0x01<<6;
  • #define LED2_OFF     LU_GPIOA_OCTL &= ~((uint32_t)0x01<<6);

  • //LED2翻转
  • #define TG_LED2      LU_GPIOA_TG |= ((uint32_t)0x01<<6)

  • void led_io_init(void);

  • #endif
  • 复制代码
    led.c文件主要是对led进行了初始化,代码如下:
    #include "led.h"
  • #include "gd32h7xx.h"

  • void led_io_init(void)
  • {
  •         //使能时钟
  •         LU_RCU_AHB4EN |= (uint32_t)0x01<<5;  //使能GPIOF时钟 Led1 PF10
  •         LU_RCU_AHB4EN  |= (uint32_t)0x01<<0; //使能GPIOA时钟 Led2 PA6
  •       
  •         //配置LED1 PF10
  •         //先清除位,因为复位后该位为0b11
  •         LU_GPIOF_CTL &= ~((uint32_t)0x03 <<(10*2));
  •         LU_GPIOF_CTL |= ((uint32_t)0x01<<10*2);        //置21:20为0x01输出模式
  •         LU_GPIOF_OMODE &= ~(0x01<<10);             //输出推挽模式
  •         LU_GPIOF_OSPD &= ~((uint32_t)0x03 <<(10*2));
  •         LU_GPIOF_OSPD &= ((uint32_t)0x01 <<(10*2));    //01:输出最大速度60M
  •         //初始化输出低电平:
  •         LU_GPIOA_OCTL &= ~((uint32_t)0x01<<10);
  •       
  •                 //先清除位,因为复位后该位为0b11
  •         LU_GPIOA_CTL &= ~((uint32_t)0x03 <<(6*2));
  •         LU_GPIOA_CTL |= ((uint32_t)0x01<<6*2);        //置21:20为0x01输出模式
  •         LU_GPIOA_OMODE &= ~(0x01<<10);             //输出推挽模式
  •         LU_GPIOA_OSPD &= ~((uint32_t)0x03 <<(6*2));
  •         LU_GPIOA_OSPD &= ((uint32_t)0x01 <<(6*2));    //01:输出最大速度60M
  •         //初始化输出低电平:
  •         LU_GPIOA_OCTL &= ~((uint32_t)0x01<<6);
  •       
  • }
  • 复制代码
    接着新建key.h
    #ifndef __KEY_H__
  • #define __KEY_H__
  • #include "lugl_gd32h7xx.h"

  • void key_config(void);
  •        
  • #endif
  • 复制代码
    key.c,中我配置了PC13为中断输入,同时定义了EXTI10-15的中断处理函数,中断处理中,主要是判断是不是基于PC13的中断事件,如果是则翻转LED2,同时清除中断标志位。
    #include "lugl_gd32h7xx.h"
  • #include "gd32h7xx.h"
  • #include "led.h"
  • #include "key.h"

  • void key_config(void)
  • {
  •         //使能时钟
  •         LU_RCU_AHB4EN |= (uint32_t)0x01<<2;  //使能GPIOF时钟  PC13
  •         LU_RCU_APB4EN |= (uint32_t)0x01<<0;  //1:开启 SYSCFG 时钟
  •        
  •         /* 开启EXTI10-15线中断 */
  •     nvic_irq_enable(EXTI10_15_IRQn, 2U, 0U);
  •                 //配置KEY2 PC13
  •         //先清除位,因为复位后该位为
  •         LU_GPIOC_CTL &= ~((uint32_t)0x03 <<(13*2)); //清除位为0b00,即为输入模式
  •         LU_GPIOC_PUD &= ~((uint32_t)0x01<<(13*2));  //清除位为0b00,即为悬空
  •        
  •         LU_SYSCFG_EXTISS3 &= ~((uint32_t)0xF<<4);    //清除    EXTI 13 源选择
  •         LU_SYSCFG_EXTISS3 |= ((uint32_t)0x02<<4);     //0010:PC13 引脚
  •        
  •         LU_EXTI_INTEN0 |= ((uint32_t)0x01<<13);         //使能EXTI13 即INTEN13;
  •         LU_EXTI_FTEN0 |= ((uint32_t)0x01<<13);          //使能13线的下降沿触发
  •        
  •         LU_EXTI_PD0 |= ((uint32_t)0x01<<13);            //清除事件;
  • }


  • void EXTI10_15_IRQHandler(void)
  • {
  •         //获取exti13 的事件标志位
  •         if(RESET != ((LU_EXTI_PD0 >>13) &0x01))
  •         {
  •                 //翻转LED2
  •                 TG_LED2;
  •                 LU_EXTI_PD0 |= ((uint32_t)0x01<<13);            //清除事件;
  •         }
  • }
  • 复制代码
    在主程序中,我记LED周断闪烁,按建下KEY2 LED2会翻转。
    按键处理,我这里没有加入消抖处理,因为开板按键电路加了电容,进行了硬件消抖处理,所以按建非常好用。
    【总结】
    使用寄存器编程,一来学习GD32H7xx的基础知识,二来代码量非常少,三来运行速度相比库函数要快。
    GD32H759_key.zip (666.4 KB, 下载次数: 0)
    全部回复 0
    暂无评论,快来抢沙发吧