• stm32——hal库学习笔记(外部中断)


    一、什么是中断?(了解)
    打断CPU执行正常的程序,转而处理紧急程序,然后返回原暂停的程序继续运行,就叫中断
    在这里插入图片描述
    中断的作用和意义
    在这里插入图片描述
    中断的意义:高效处理紧急程序,不会一直占用CPU资源

    STM32 GPIO外部中断简图
    在这里插入图片描述

    二、NVIC(熟悉)
    2.1,NVIC基本概念
    2.2,NVIC相关寄存器介绍
    2.3,NVIC工作原理
    2.4,STM32中断优先级基本概念
    2.5,STM32中断优先级分组
    2.6,STM32 NVIC的使用

    2.1、NVIC基本概念
    Nested vectored interrupt controller,嵌套向量中断控制器,属于内核(M3/4/7)
    NVIC支持:256个中断(16内核 + 240外部),支持:256个优先级,允许裁剪!
    在这里插入图片描述
    什么是中断向量表?
    定义一块固定的内存,以4字节对齐,存放各个中断服务函数程序的首地址
    中断向量表定义在启动文件,当发生中断,CPU会自动执行对应的中断服务函数
    在这里插入图片描述
    2.2、NVIC相关寄存器介绍
    在这里插入图片描述
    NVIC还有:中断挂起,解挂,激活标志等非常用功能,不做介绍!

    2.3、NVIC工作原理
    在这里插入图片描述

    2.4、STM32中断优先级基本概念
    1,抢占优先级(pre):高抢占优先级可以打断正在执行的低抢占优先级中断
    2,响应优先级(sub):当抢占优先级相同时,响应优先级高的先执行,但是不能互相打断
    3,抢占和响应都相同的情况下,自然优先级越高的,先执行
    4,自然优先级:中断向量表的优先级
    5,数值越小,表示优先级越高

    2.5、 STM32中断优先级分组
    在这里插入图片描述

    STM32中断优先级举例(假设分组是2)
    在这里插入图片描述
    EXTI1和RTC可以打断:EXTI0和Systick的中断,获得优先执行!

    2.6、 STM32 NVIC的使用
    在这里插入图片描述

    三、EXTI(熟悉)
    3.1,EXTI基本概念
    3.2,EXTI主要特性
    3.3,EXTI工作原理(F1/F4/F7)

    3.1、EXTI基本概念
    External(Extended) interrupt/event Controller,外部(扩展)中断事件控制器
    包含20个产生事件/中断请求的边沿检测器,即总共:20条EXTI线(F1)
    中断和事件的理解:
    中断:要进入NVIC,有相应的中断服务函数,需要CPU处理
    事件:不进入NVIC,仅用于内部硬件自动控制的,如:TIM、DMA、ADC

    EXTI支持的外部中断/事件请求
    在这里插入图片描述

    3.2、EXTI主要特性
    F1/F4/F7系列
    每条EXTI线都可以单独配置:选择类型(中断或者事件)、触发方式(上升沿,下降沿或者双边沿触发)、支持软件触发、开启/屏蔽、有挂起状态位

    3.3、EXTI工作原理(F1/F4/F7系列)
    ①,边沿检测
    ②,软件触发
    ③,中断屏蔽/清除
    ④,事件屏蔽
    在这里插入图片描述

    四、EXTI和IO映射关系(熟悉)
    4.1,AFIO简介(F1)
    Alternate Function IO,即复用功能IO,主要用于重映射和外部中断映射配置
    在这里插入图片描述

    4.2,SYSCFG简介(F4/F7/H7)
    System configuration controller,即系统配置控制器,用于外部中断映射配置等
    在这里插入图片描述
    4.3,EXTI 与 IO对应关系
    在这里插入图片描述
    五、如何使用中断(掌握)
    在这里插入图片描述
    在这里插入图片描述
    STM32 EXTI的HAL库设置步骤(外部中断)
    在这里插入图片描述

    __HAL_RCC_GPIOx_CLK_ENABLE
    
    • 1

    在这里插入图片描述

    HAL_GPIO_Init
    
    • 1

    在这里插入图片描述

    HAL_NVIC_SetPriorityGrouping
    
    • 1

    在这里插入图片描述

    HAL_NVIC_SetPriority
    
    • 1

    在这里插入图片描述

     HAL_NVIC_EnableIRQ
    
    • 1

    在这里插入图片描述

    EXTIx_IRQHandler
    
    • 1

    STM32仅有:EXTI0~4、EXTI9_5、EXTI15_10,7个外部中断服务函数

    六、HAL库中断回调处理机制介绍(掌握)

    在这里插入图片描述

    七、demo程序——通过外部中断控制一个灯亮灭(掌握)

    exit.c

    #include "./SYSTEM/sys/sys.h"
    #include "./SYSTEM/delay/delay.h"
    #include "./BSP/LED/led.h"
    #include "./BSP/BEEP/beep.h"
    #include "./BSP/KEY/key.h"
    #include "./BSP/EXTI/exti.h"
    /**
     * @brief       外部中断初始化程序
     * @param       无
     * @retval      无
     */
    void extix_init(void)
    {
        GPIO_InitTypeDef gpio_init_struct;
    
        KEY0_GPIO_CLK_ENABLE();                                  /* KEY0时钟使能 */
        KEY1_GPIO_CLK_ENABLE();                                  /* KEY1时钟使能 */
        KEY2_GPIO_CLK_ENABLE();                                  /* KEY2时钟使能 */
        WKUP_GPIO_CLK_ENABLE();                                  /* WKUP时钟使能 */
    
        gpio_init_struct.Pin = KEY0_INT_GPIO_PIN;
        gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 下降沿触发 */
        gpio_init_struct.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(KEY0_INT_GPIO_PORT, &gpio_init_struct);    /* KEY0配置为下降沿触发中断 */
    
        gpio_init_struct.Pin = KEY1_INT_GPIO_PIN;
        gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 下降沿触发 */
        gpio_init_struct.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(KEY1_INT_GPIO_PORT, &gpio_init_struct);    /* KEY1配置为下降沿触发中断 */
        
        gpio_init_struct.Pin = KEY2_INT_GPIO_PIN;
        gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 下降沿触发 */
        gpio_init_struct.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(KEY2_INT_GPIO_PORT, &gpio_init_struct);    /* KEY2配置为下降沿触发中断 */
        
        gpio_init_struct.Pin = WKUP_INT_GPIO_PIN;
        gpio_init_struct.Mode = GPIO_MODE_IT_RISING;             /* 上升沿触发 */
        gpio_init_struct.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(WKUP_GPIO_PORT, &gpio_init_struct);        /* WKUP配置为上升沿触发中断 */
    
        HAL_NVIC_SetPriority(KEY0_INT_IRQn, 0, 2);               /* 抢占0,子优先级2 */
        HAL_NVIC_EnableIRQ(KEY0_INT_IRQn);                       /* 使能中断线1 */
    
        HAL_NVIC_SetPriority(KEY1_INT_IRQn, 1, 2);               /* 抢占1,子优先级2 */
        HAL_NVIC_EnableIRQ(KEY1_INT_IRQn);                       /* 使能中断线15 */
        
        HAL_NVIC_SetPriority(KEY2_INT_IRQn, 2, 2);               /* 抢占2,子优先级2 */
        HAL_NVIC_EnableIRQ(KEY2_INT_IRQn);                       /* 使能中断线15 */
    
        HAL_NVIC_SetPriority(WKUP_INT_IRQn, 3, 2);               /* 抢占3,子优先级2 */
        HAL_NVIC_EnableIRQ(WKUP_INT_IRQn);                       /* 使能中断线0 */
    }
    
    
    /**
     * @brief       KEY0 外部中断服务程序
     * @param       无
     * @retval      无
     */
    void KEY0_INT_IRQHandler(void)
    {
        HAL_GPIO_EXTI_IRQHandler(KEY0_INT_GPIO_PIN);         /* 调用中断处理公用函数 清除KEY0所在中断线 的中断标志位 */
        __HAL_GPIO_EXTI_CLEAR_IT(KEY0_INT_GPIO_PIN);         /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
    }
    
    /**
     * @brief       KEY1 外部中断服务程序
     * @param       无
     * @retval      无
     */
    void KEY1_INT_IRQHandler(void)
    { 
        HAL_GPIO_EXTI_IRQHandler(KEY1_INT_GPIO_PIN);         /* 调用中断处理公用函数 清除KEY1所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */
        __HAL_GPIO_EXTI_CLEAR_IT(KEY1_INT_GPIO_PIN);         /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
    }
    
    /**
     * @brief       KEY2 外部中断服务程序
     * @param       无
     * @retval      无
     */
    void KEY2_INT_IRQHandler(void)
    { 
        HAL_GPIO_EXTI_IRQHandler(KEY2_INT_GPIO_PIN);        /* 调用中断处理公用函数 清除KEY2所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */
        __HAL_GPIO_EXTI_CLEAR_IT(KEY2_INT_GPIO_PIN);        /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
    }
    
    /**
     * @brief       WK_UP 外部中断服务程序
     * @param       无
     * @retval      无
     */
    void WKUP_INT_IRQHandler(void)
    { 
        HAL_GPIO_EXTI_IRQHandler(WKUP_INT_GPIO_PIN);        /* 调用中断处理公用函数 清除KEY_UP所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */
        __HAL_GPIO_EXTI_CLEAR_IT(WKUP_INT_GPIO_PIN);        /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
    }
    /**
     * @brief       中断服务程序中需要做的事情
                    在HAL库中所有的外部中断服务函数都会调用此函数
     * @param       GPIO_Pin:中断引脚号
     * @retval      无
     */
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    {
        delay_ms(20);      /* 消抖 */
        switch(GPIO_Pin)
        {
            case KEY0_INT_GPIO_PIN:
                if (KEY0 == 0)
                {
                    LED0_TOGGLE();  /* LED0 状态取反 */ 
                    LED1_TOGGLE();  /* LED1 状态取反 */ 
                }
                break;
            case KEY1_INT_GPIO_PIN:
                if (KEY1 == 0)
                {
                    LED0_TOGGLE();  /* LED0 状态取反 */ 
                }
                break;
            case KEY2_INT_GPIO_PIN:
                if (KEY2 == 0)
                {
                    LED1_TOGGLE();  /* LED1 状态取反 */ 
                }
                break;
            case WKUP_INT_GPIO_PIN:
                if (WK_UP == 1)
                {
                    BEEP_TOGGLE();  /* 蜂鸣器状态取反 */ 
                }
                break;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135

    exti.h

    #ifndef __EXTI_H
    #define __EXTI_H
    
    #include "./SYSTEM/sys/sys.h"
    
    /******************************************************************************************/
    /* 引脚 和 中断编号 & 中断服务函数 定义 */ 
    #define KEY0_INT_GPIO_PORT              GPIOA
    #define KEY0_INT_GPIO_PIN               GPIO_PIN_4
    #define KEY0_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
    #define KEY0_INT_IRQn                   EXTI4_IRQn
    #define KEY0_INT_IRQHandler             EXTI4_IRQHandler
    
    #define KEY1_INT_GPIO_PORT              GPIOA
    #define KEY1_INT_GPIO_PIN               GPIO_PIN_3
    #define KEY1_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
    #define KEY1_INT_IRQn                   EXTI3_IRQn
    #define KEY1_INT_IRQHandler             EXTI3_IRQHandler
    
    #define KEY2_INT_GPIO_PORT              GPIOA
    #define KEY2_INT_GPIO_PIN               GPIO_PIN_2
    #define KEY2_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
    #define KEY2_INT_IRQn                   EXTI2_IRQn
    #define KEY2_INT_IRQHandler             EXTI2_IRQHandler
    
    #define WKUP_INT_GPIO_PORT              GPIOA
    #define WKUP_INT_GPIO_PIN               GPIO_PIN_0
    #define WKUP_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PA口时钟使能 */
    #define WKUP_INT_IRQn                   EXTI0_IRQn
    #define WKUP_INT_IRQHandler             EXTI0_IRQHandler
    
    /******************************************************************************************/
    void extix_init(void);  /* 外部中断初始化 */
    
    #endif
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    led.c

    #include "./BSP/LED/led.h"
    
    
    /**
     * @brief       初始化LED相关IO口, 并使能时钟
     * @param       无
     * @retval      无
     */
    void led_init(void)
    {
        GPIO_InitTypeDef gpio_init_struct;
        LED0_GPIO_CLK_ENABLE();                                 /* LED0时钟使能 */
        LED1_GPIO_CLK_ENABLE();                                 /* LED1时钟使能 */
    
        gpio_init_struct.Pin = LED0_GPIO_PIN;                   /* LED0引脚 */
        gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;            /* 推挽输出 */
        gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */
        HAL_GPIO_Init(LED0_GPIO_PORT, &gpio_init_struct);       /* 初始化LED0引脚 */
    
        gpio_init_struct.Pin = LED1_GPIO_PIN;                   /* LED1引脚 */
        HAL_GPIO_Init(LED1_GPIO_PORT, &gpio_init_struct);       /* 初始化LED1引脚 */
        
    
        LED0(1);                                                /* 关闭 LED0 */
        LED1(1);                                                /* 关闭 LED1 */
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    led.h

    #ifndef _LED_H
    #define _LED_H
    #include "./SYSTEM/sys/sys.h"
    
    
    /******************************************************************************************/
    /* 引脚 定义 */
    
    #define LED0_GPIO_PORT                  GPIOB
    #define LED0_GPIO_PIN                   GPIO_PIN_5
    #define LED0_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)             /* PB口时钟使能 */
    
    #define LED1_GPIO_PORT                  GPIOB
    #define LED1_GPIO_PIN                   GPIO_PIN_6
    #define LED1_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)             /* PE口时钟使能 */
    
    /******************************************************************************************/
    /* LED端口定义 */
    #define LED0(x)   do{ x ? \
                          HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_SET) : \
                          HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_RESET); \
                      }while(0)      /* LED0翻转 */
    
    #define LED1(x)   do{ x ? \
                          HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_SET) : \
                          HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_RESET); \
                      }while(0)      /* LED1翻转 */
    
    /* LED取反定义 */
    #define LED0_TOGGLE()   do{ HAL_GPIO_TogglePin(LED0_GPIO_PORT, LED0_GPIO_PIN); }while(0)        /* 翻转LED0 */
    #define LED1_TOGGLE()   do{ HAL_GPIO_TogglePin(LED1_GPIO_PORT, LED1_GPIO_PIN); }while(0)        /* 翻转LED1 */
    
    /******************************************************************************************/
    /* 外部接口函数*/
    void led_init(void);                                                                            /* 初始化 */
    
    #endif
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    beep.c

    #include "./BSP/BEEP/beep.h"
    
    
    /**
     * @brief       初始化BEEP相关IO口, 并使能时钟
     * @param       无
     * @retval      无
     */
    void beep_init(void)
    {
        GPIO_InitTypeDef gpio_init_struct;
        BEEP_GPIO_CLK_ENABLE();                             /* BEEP时钟使能 */
    
        gpio_init_struct.Pin = BEEP_GPIO_PIN;               /* 蜂鸣器引脚 */
        gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;        /* 推挽输出 */
        gpio_init_struct.Pull = GPIO_PULLUP;                /* 上拉 */
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;      /* 高速 */
        HAL_GPIO_Init(BEEP_GPIO_PORT, &gpio_init_struct);   /* 初始化蜂鸣器引脚 */
    
        BEEP(0);                                            /* 关闭蜂鸣器 */
    }
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    beep.h

    #ifndef __BEEP_H
    #define __BEEP_H
    
    #include "./SYSTEM/sys/sys.h"
    
    /******************************************************************************************/
    /* 引脚 定义 */
    
    #define BEEP_GPIO_PORT                  GPIOB
    #define BEEP_GPIO_PIN                   GPIO_PIN_8
    #define BEEP_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)   /* PB口时钟使能 */
    
    /******************************************************************************************/
    
    /* 蜂鸣器控制 */
    #define BEEP(x)         do{ x ? \
                                HAL_GPIO_WritePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN, GPIO_PIN_SET) : \
                                HAL_GPIO_WritePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN, GPIO_PIN_RESET); \
                            }while(0)
    
    /* BEEP状态翻转 */
    #define BEEP_TOGGLE()   do{ HAL_GPIO_TogglePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN); }while(0)     /* BEEP = !BEEP */
    
    void beep_init(void);   /* 初始化蜂鸣器 */
    
    #endif
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    key.c

    #include "./BSP/KEY/key.h"
    #include "./SYSTEM/delay/delay.h"
    
    
    /**
     * @brief       按键初始化函数
     * @param       无
     * @retval      无
     */
    void key_init(void)
    {
        GPIO_InitTypeDef gpio_init_struct;
        KEY0_GPIO_CLK_ENABLE();                                     /* KEY0时钟使能 */
        KEY1_GPIO_CLK_ENABLE();                                     /* KEY1时钟使能 */
        KEY2_GPIO_CLK_ENABLE();                                     /* KEY2时钟使能 */
        WKUP_GPIO_CLK_ENABLE();                                     /* WKUP时钟使能 */
    
        gpio_init_struct.Pin = KEY0_GPIO_PIN;                       /* KEY0引脚 */
        gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */
        gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */
        HAL_GPIO_Init(KEY0_GPIO_PORT, &gpio_init_struct);           /* KEY0引脚模式设置,上拉输入 */
    
        gpio_init_struct.Pin = KEY1_GPIO_PIN;                       /* KEY1引脚 */
        gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */
        gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */
        HAL_GPIO_Init(KEY1_GPIO_PORT, &gpio_init_struct);           /* KEY1引脚模式设置,上拉输入 */
    
        gpio_init_struct.Pin = KEY2_GPIO_PIN;                       /* KEY2引脚 */
        gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */
        gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */
        HAL_GPIO_Init(KEY2_GPIO_PORT, &gpio_init_struct);           /* KEY2引脚模式设置,上拉输入 */
    
        gpio_init_struct.Pin = WKUP_GPIO_PIN;                       /* WKUP引脚 */
        gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */
        gpio_init_struct.Pull = GPIO_PULLDOWN;                      /* 下拉 */
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */
        HAL_GPIO_Init(WKUP_GPIO_PORT, &gpio_init_struct);           /* WKUP引脚模式设置,下拉输入 */
    
    }
    
    /**
     * @brief       按键扫描函数
     * @note        该函数有响应优先级(同时按下多个按键): WK_UP > KEY2 > KEY1 > KEY0!!
     * @param       mode:0 / 1, 具体含义如下:
     *   @arg       0,  不支持连续按(当按键按下不放时, 只有第一次调用会返回键值,
     *                  必须松开以后, 再次按下才会返回其他键值)
     *   @arg       1,  支持连续按(当按键按下不放时, 每次调用该函数都会返回键值)
     * @retval      键值, 定义如下:
     *              KEY0_PRES, 1, KEY0按下
     *              KEY1_PRES, 2, KEY1按下
     *              KEY2_PRES, 3, KEY2按下
     *              WKUP_PRES, 4, WKUP按下
     */
    uint8_t key_scan(uint8_t mode)
    {
        static uint8_t key_up = 1;  /* 按键按松开标志 */
        uint8_t keyval = 0;
    
        if (mode) key_up = 1;       /* 支持连按 */
    
        if (key_up && (KEY0 == 0 || KEY1 == 0 || KEY2 == 0 || WK_UP == 1))  /* 按键松开标志为1, 且有任意一个按键按下了 */
        {
            delay_ms(10);           /* 去抖动 */
            key_up = 0;
    
            if (KEY0 == 0)  keyval = KEY0_PRES;
    
            if (KEY1 == 0)  keyval = KEY1_PRES;
    
            if (KEY2 == 0)  keyval = KEY2_PRES;
    
            if (WK_UP == 1) keyval = WKUP_PRES;
        }
        else if (KEY0 == 1 && KEY1 == 1 && KEY2 == 1 && WK_UP == 0) /* 没有任何按键按下, 标记按键松开 */
        {
            key_up = 1;
        }
    
        return keyval;              /* 返回键值 */
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    key.h

    #ifndef __KEY_H
    #define __KEY_H
    
    #include "./SYSTEM/sys/sys.h"
    
    /******************************************************************************************/
    /* 引脚 定义 */
    
    #define KEY0_GPIO_PORT                  GPIOA
    #define KEY0_GPIO_PIN                   GPIO_PIN_4
    #define KEY0_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
    
    #define KEY1_GPIO_PORT                  GPIOA
    #define KEY1_GPIO_PIN                   GPIO_PIN_3
    #define KEY1_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
    
    #define KEY2_GPIO_PORT                  GPIOE
    #define KEY2_GPIO_PIN                   GPIO_PIN_2
    #define KEY2_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
    
    #define WKUP_GPIO_PORT                  GPIOA
    #define WKUP_GPIO_PIN                   GPIO_PIN_0
    #define WKUP_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PA口时钟使能 */
    
    /******************************************************************************************/
    
    #define KEY0        HAL_GPIO_ReadPin(KEY0_GPIO_PORT, KEY0_GPIO_PIN)     /* 读取KEY0引脚 */
    #define KEY1        HAL_GPIO_ReadPin(KEY1_GPIO_PORT, KEY1_GPIO_PIN)     /* 读取KEY1引脚 */
    #define KEY2        HAL_GPIO_ReadPin(KEY2_GPIO_PORT, KEY2_GPIO_PIN)     /* 读取KEY2引脚 */
    #define WK_UP       HAL_GPIO_ReadPin(WKUP_GPIO_PORT, WKUP_GPIO_PIN)     /* 读取WKUP引脚 */
    
    
    #define KEY0_PRES    1              /* KEY0按下 */
    #define KEY1_PRES    2              /* KEY1按下 */
    #define KEY2_PRES    3              /* KEY2按下 */
    #define WKUP_PRES    4              /* KEY_UP按下(即WK_UP) */
    
    void key_init(void);                /* 按键初始化函数 */
    uint8_t key_scan(uint8_t mode);     /* 按键扫描函数 */
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    main.c

    #include "./SYSTEM/sys/sys.h"
    #include "./SYSTEM/usart/usart.h"
    #include "./SYSTEM/delay/delay.h"
    #include "./BSP/LED/led.h"
    #include "./BSP/BEEP/beep.h"
    #include "./BSP/EXTI/exti.h"
    
    
    int main(void)
    {
        HAL_Init();                            /* 初始化HAL库 */
        sys_stm32_clock_init(RCC_PLL_MUL9);    /* 设置时钟, 72Mhz */
        delay_init(72);                        /* 延时初始化 */
       
        led_init();                            /* 初始化LED */
        beep_init();                           /* 初始化蜂鸣器 */
        extix_init();                          /* 初始化外部中断输入 */
        LED0(0);                               /* 先点亮红灯 */
    
        while (1)
        {
          
            delay_ms(1000);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
  • 相关阅读:
    将Long类型转化为IP字符串
    linux设置应用开机自启(通用:mysql、jar、nginx、solr...)
    Android—Surface,BufferQueue
    某些设置由你的组织来管理
    每日简报 8月30日简报新鲜事 每天一分钟 了解新鲜事
    golang 多环境配置切换
    微服务保护-流量控制
    Linux中,查看Tomcat版本、如何查看Tomcat版本
    基于Html的某大学校园网展示静态网页设计 课程报告+源代码
    C++之模拟实现map和set
  • 原文地址:https://blog.csdn.net/wozhihecha/article/details/136122516