• STM32WL开发之易智联LORA评估板上按键KEY的配置与应用


    前言:在前一篇《STM32WL开发之LORA评估板上通过GPIO控制LED》中已经基于易智联的LoRa评估板LM401-Pro-Kit介绍了在其Demo例程上如何实现GPIO控制LED闪烁的功能,本文将介绍如何基于LoRa评估板和Demo例程实现按键KEY的配置与应用。

    功能描述

    本文将基于Demo例程实现一个通过按键KEY控制LED闪灯,当按键KEY按下,LED灯闪灯一次。

    STM32中按键的工作原理

    STM32中GPIO引脚自带上拉、下拉输入,因此硬件电路部分不需要加额外的电阻实现上拉下拉。主要有以下两种方式实现独立按键设计:

    (一)高电平检测独立按键:

    只需要从VCC引线通过一个按键开关到单片机I/O口,软件初始化配置为下拉输入或浮空输入。当按键开关按下时开关导通,单片机I/O口就检测到高电平输入。

    (二)低电平检测独立按键:

    同理从GND引线通过一个按键开关到单片机I/O口,软件初始化配置为上拉输入或浮空输入。当按键开关按下时开关导通,单片机I/O口就检测到低电平输入。

    注意:

    实现方式不同的独立按键,按键检测函数也不相同,需要修改到对应的检测方式功能才能正常使用,比如低电平和高电平的检测独立按键,它们的按键检测判断条件是相反的。接入的高电平使用对应STM32单片机GPIO引脚所能承受的最大电压(大多数IO能承受5V,推荐使用3.3V),否则将损坏芯片。

    按键控制电路分析

    LM401-Pro-Kit评估板上按键部分的原理图如下:

    由上图可知,按键连接到PA0,低电平有效,所以按键配置为上拉输入,默认情况下读取到GPIO的电平为高电平,当按键按下时,相关管脚变成低电平。

    GPIO控制函数

    1. 电平输入函数

           这里的输入是以MCU为参照而言的,也就是MCU读取指定GPIO端口的数据。

    1. 电平输出函数

           这里的输出也是以MCU为参照的,也就是MCU向指定GPIO端口写入数据。

    1. 电平翻转函数

           该函数完成GPIO端口状态0/1的变换,在前一篇文章中有解释。

    实现代码

           本文的代码是在上文《STM32WL开发之LORA评估板上通过GPIO控制LED》的基础上开发的,LED灯也沿用上文中的LED1,本文主要介绍按键KEY部分的代码,LED 部分的代码就不再赘述。

    1、宏定义

    1.  /****** 在stm32wlxx_LM401.h文件中 ******/
    2. typedef enum
    3.   BUTTON_SW1 = 0,                      // 按键定义
    4.   BUTTON_SW2 = 1,
    5.   BUTTON_SW3 = 2,
    6. }Button_TypeDef;
    7. typedef enum
    8.   BUTTON_MODE_GPIO = 0,
    9.   BUTTON_MODE_EXTI = 1                 // 按键采用中断触发方式
    10. }ButtonMode_TypeDef;
    11. #define BUTTON_SW1_PIN                          GPIO_PIN_0
    12. #define BUTTON_SW1_GPIO_PORT                    GPIOA
    13. #define BUTTON_SW1_GPIO_CLK_ENABLE()            __HAL_RCC_GPIOA_CLK_ENABLE()
    14. #define BUTTON_SW1_GPIO_CLK_DISABLE()           __HAL_RCC_GPIOA_CLK_DISABLE()
    15. #define BUTTON_SW1_EXTI_LINE                    EXTI_LINE_0
    16. #ifdef CORE_CM0PLUS
    17. #define BUTTON_SW1_EXTI_IRQn                    EXTI1_0_IRQn
    18. #else
    19. #define BUTTON_SW1_EXTI_IRQn                    EXTI0_IRQn
    20. #endif
    21. #define H_EXTI_0                                hpb_exti[BUTTON_SW1]
    22. #define BUTTONx_GPIO_CLK_ENABLE(__INDEX__)    do { if ((__INDEX__) == BUTTON_SW1) BUTTON_SW1_GPIO_CLK_ENABLE(); else \
    23.                                               if ((__INDEX__) == BUTTON_SW2) BUTTON_SW2_GPIO_CLK_ENABLE(); else \
    24.                                               if ((__INDEX__) == BUTTON_SW3) BUTTON_SW3_GPIO_CLK_ENABLE();} while(0)
    25. #define BUTTONx_GPIO_CLK_DISABLE(__INDEX__)    do { if ((__INDEX__) == BUTTON_SW1) BUTTON_SW1_GPIO_CLK_DISABLE(); else \
    26.                                               if ((__INDEX__) == BUTTON_SW2) BUTTON_SW2_GPIO_CLK_DISABLE(); else \
    27.                                               if ((__INDEX__) == BUTTON_SW3) BUTTON_SW3_GPIO_CLK_DISABLE();} while(0)

    2、按键初始化函数

    1. /***** 在stm32wlxx_LM401.c文件中 *****/
    2. int32_t BSP_PB_Init(Button_TypeDef Button, ButtonMode_TypeDef ButtonMode)
    3. {
    4. GPIO_InitTypeDef gpio_init_structure = {0};
    5. static BSP_EXTI_LineCallback button_callback[BUTTONn] = {BUTTON_SW1_EXTI_Callback, BUTTON_SW2_EXTI_Callback, BUTTON_SW3_EXTI_Callback};
    6. static uint32_t button_interrupt_priority[BUTTONn] = {BSP_BUTTON_USER_IT_PRIORITY, BSP_BUTTON_USER_IT_PRIORITY, BSP_BUTTON_USER_IT_PRIORITY};
    7. static const uint32_t button_exti_line[BUTTONn] = {BUTTON_SW1_EXTI_LINE, BUTTON_SW2_EXTI_LINE, BUTTON_SW3_EXTI_LINE};
    8. /* Enable the BUTTON Clock */
    9. BUTTONx_GPIO_CLK_ENABLE(Button);
    10. gpio_init_structure.Pin = BUTTON_PIN[Button];
    11. gpio_init_structure.Pull = GPIO_PULLUP;
    12. gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
    13. if(ButtonMode == BUTTON_MODE_GPIO)
    14. {
    15. /* Configure Button pin as input */
    16. gpio_init_structure.Mode = GPIO_MODE_INPUT;
    17. HAL_GPIO_Init(BUTTON_PORT[Button], &gpio_init_structure);
    18. }
    19. else /* (ButtonMode == BUTTON_MODE_EXTI) */
    20. {
    21. /* Configure Button pin as input with External interrupt */
    22. gpio_init_structure.Mode = GPIO_MODE_IT_FALLING; // 按键采用下降沿中断触发的方式
    23. HAL_GPIO_Init(BUTTON_PORT[Button], &gpio_init_structure); // 按键所用的GPIO初始化
    24. (void)HAL_EXTI_GetHandle(&hpb_exti[Button], button_exti_line[Button]);
    25. (void)HAL_EXTI_RegisterCallback(&hpb_exti[Button], HAL_EXTI_COMMON_CB_ID, button_callback[Button]);
    26. /* Enable and set Button EXTI Interrupt to the lowest priority */
    27. HAL_NVIC_SetPriority((BUTTON_IRQn[Button]), button_interrupt_priority[Button], 0x00); // 设置中断优先级
    28. HAL_NVIC_EnableIRQ((BUTTON_IRQn[Button])); // 启动中断
    29. }
    30. return BSP_ERROR_NONE;
    31. }

    3、中断处理函数

    1. /***** 在stm32wlxx_it.c文件中 ****/
    2. void EXTI0_IRQHandler(void)
    3. {
    4. /* USER CODE BEGIN EXTI0_IRQn 0 */
    5. /* USER CODE END EXTI0_IRQn 0 */
    6. HAL_GPIO_EXTI_IRQHandler(BUT1_Pin); // 调用HAL层的中断处理函数
    7. /* USER CODE BEGIN EXTI0_IRQn 1 */
    8. /* USER CODE END EXTI0_IRQn 1 */
    9. }
    10. /**
    11. * @brief Handle EXTI interrupt request.
    12. * @param GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
    13. * @retval None
    14. */
    15. void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
    16. {
    17. /* EXTI line interrupt detected */
    18. if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
    19. {
    20. __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    21. HAL_GPIO_EXTI_Callback(GPIO_Pin);
    22. }
    23. }
    24. /***** 在subghz_phy_app.c文件中 *****/
    25. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    26. {
    27. switch (GPIO_Pin)
    28. {
    29. case BUTTON_SW1_PIN: // 当按键SW1中断触发时
    30. BSP_LED_On(LED_BLUE) ; // LED1的蓝灯亮
    31. HAL_Delay(200); // 延迟200ms
    32. BSP_LED_Off(LED_BLUE) ; // LED1的蓝灯灭
    33. APP_PRINTF("BUTTON SW1\r\n");
    34. break;
    35. default:
    36. APP_PRINTF("Unkonw Button\r\n");
    37. break;
    38. }
    39. }

    4、主函数

    1. /***** 在main.c中 *****/
    2. int main(void)
    3. {
    4. /* USER CODE BEGIN 1 */
    5. /* USER CODE END 1 */
    6. /* MCU Configuration--------------------------------------------------------*/
    7. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    8. HAL_Init();
    9. /* USER CODE BEGIN Init */
    10. /* USER CODE END Init */
    11. /* Configure the system clock */
    12. /* 系统时钟初始化 */
    13. SystemClock_Config();
    14. /* USER CODE BEGIN SysInit */
    15. /* USER CODE END SysInit */
    16. /* Initialize all configured peripherals */
    17. /* 定时器初始化 */
    18. UTIL_TIMER_Init();
    19. /* 初始化LED灯 */
    20. BSP_LED_Init(LED_BLUE);
    21. /* 初始化按键,指定采用外部中断触发的方式 */
    22. BSP_PB_Init(BUTTON_SW1, BUTTON_MODE_EXTI);
    23. /* USER CODE BEGIN 2 */
    24. /* USER CODE END 2 */
    25. /* Infinite loop */
    26. /* USER CODE BEGIN WHILE */
    27. while (1)
    28. {
    29. /* USER CODE END WHILE */
    30. /* USER CODE BEGIN 3 */
    31. }
    32. /* USER CODE END 3 */
    33. }

    测试验证

           编译工程后下载到LM401-Pro-Kit评估板上,按下PA0按键可看到LED1的蓝灯亮起,符合设计预期。

    工程代码下载:

    链接: https://pan.baidu.com/s/1MpVU_UDMYITYdjSG7bccqA

    提取码: iyrz

  • 相关阅读:
    FFmpeg入门详解之20:视频编码原理简介
    C语言用数组实现打印学生成绩,分别打印每名学生的总成绩,平均成绩。每门学科的总成绩,平均成绩
    3D U-Net: Learning Dense Volumetric Segmentation from Sparse Annotation
    2022年度中国PCB百强榜单公布
    【2023美团后端-8】删除字符串的方案,限制不能连续删
    vmware中的linux虚拟机如何增加磁盘容量
    CentOS 7 安装 JDK11(注意版本号要与自己的版本一致)
    uniapp发行H5获取当前页面query
    ARM_基础之RAS
    leetcode刷题日记:141. Linked List Cycle(环形链表)
  • 原文地址:https://blog.csdn.net/enchen/article/details/127667538