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

  3. //key1 -- PA0
  4. //key2 -- PC13
  5. //key3 -- PF8
  6. //定义时钟地址
  7. // RCU 基地址:0x5802 4400  
  8. #define LU_RCU_AHB4EN (*(volatile uint32_t *)(uint32_t)(0x58024400+0x3C))
  9.        
  10. //定义GPIOA_CTL的地址:GPIOA基地址:0x5802 0000
  11. #define LU_GPIOA_CTL   (*(volatile uint32_t *)(uint32_t)0x58020000)
  12. #define LU_GPIOA_OMODE (*(volatile uint32_t *)(uint32_t)0x58020004)
  13. #define LU_GPIOA_OSPD  (*(volatile uint32_t *)(uint32_t)0x58020008)
  14. #define LU_GPIOA_OCTL  (*(volatile uint32_t *)(uint32_t)0x58020014)
  15. #define LU_GPIOA_PUD   (*(volatile uint32_t *)(uint32_t)0x5802000C)
  16. #define LU_GPIOA_TG           (*(volatile uint32_t *)(uint32_t)0x5802002C)

  17. //定义GPIOA_CTL的地址:GPIOC基地址:0x5802 0080
  18. #define LU_GPIOC_CTL   (*(volatile uint32_t *)(uint32_t)0x58020800)
  19. #define LU_GPIOC_OMODE (*(volatile uint32_t *)(uint32_t)0x58020804)
  20. #define LU_GPIOC_OSPD  (*(volatile uint32_t *)(uint32_t)0x58020808)
  21. #define LU_GPIOC_OCTL  (*(volatile uint32_t *)(uint32_t)0x58020814)
  22. #define LU_GPIOC_PUD   (*(volatile uint32_t *)(uint32_t)0x5802080C)
  23.        
  24. //GPIOF基地址:0x5802 1400
  25. #define LU_GPIOF_CTL   (*(volatile uint32_t *)(uint32_t)0x58021400)
  26. #define LU_GPIOF_OMODE (*(volatile uint32_t *)(uint32_t)(0x58021404))
  27. #define LU_GPIOF_OSPD  (*(volatile uint32_t *)(uint32_t)(0x58021408))
  28. #define LU_GPIOF_OCTL  (*(volatile uint32_t *)(uint32_t)(0x58021414))
  29. #define LU_GPIOF_ISTAT (*(volatile uint32_t *)(uint32_t)(0x58021410))
  30. #define LU_GPIOF_PUD   (*(volatile uint32_t *)(uint32_t)0x5802140C)
  31.        
  32. #define LU_SYSCFG_EXTISS3 (*(volatile uint32_t *)(uint32_t)0x58000414)

  33. // EXTI 基地址:0x5800 0000

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

  41. #endif

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


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

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

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

  11. void led_io_init(void);

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

  3. void led_io_init(void)
  4. {
  5.         //使能时钟
  6.         LU_RCU_AHB4EN |= (uint32_t)0x01<<5;  //使能GPIOF时钟 Led1 PF10
  7.         LU_RCU_AHB4EN  |= (uint32_t)0x01<<0; //使能GPIOA时钟 Led2 PA6
  8.       
  9.         //配置LED1 PF10
  10.         //先清除位,因为复位后该位为0b11
  11.         LU_GPIOF_CTL &= ~((uint32_t)0x03 <<(10*2));
  12.         LU_GPIOF_CTL |= ((uint32_t)0x01<<10*2);        //置21:20为0x01输出模式
  13.         LU_GPIOF_OMODE &= ~(0x01<<10);             //输出推挽模式
  14.         LU_GPIOF_OSPD &= ~((uint32_t)0x03 <<(10*2));
  15.         LU_GPIOF_OSPD &= ((uint32_t)0x01 <<(10*2));    //01:输出最大速度60M
  16.         //初始化输出低电平:
  17.         LU_GPIOA_OCTL &= ~((uint32_t)0x01<<10);
  18.       
  19.                 //先清除位,因为复位后该位为0b11
  20.         LU_GPIOA_CTL &= ~((uint32_t)0x03 <<(6*2));
  21.         LU_GPIOA_CTL |= ((uint32_t)0x01<<6*2);        //置21:20为0x01输出模式
  22.         LU_GPIOA_OMODE &= ~(0x01<<10);             //输出推挽模式
  23.         LU_GPIOA_OSPD &= ~((uint32_t)0x03 <<(6*2));
  24.         LU_GPIOA_OSPD &= ((uint32_t)0x01 <<(6*2));    //01:输出最大速度60M
  25.         //初始化输出低电平:
  26.         LU_GPIOA_OCTL &= ~((uint32_t)0x01<<6);
  27.       
  28. }
接着新建key.h
  1. #ifndef __KEY_H__
  2. #define __KEY_H__
  3. #include "lugl_gd32h7xx.h"

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

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


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