HAL库学习02---按键(中断和扫描)控制LED

文章介绍了如何在STM32F103ZET3开发板上实现LED灯和按键的控制。通过按键按下时改变LED状态,提出了两种方法:扫描和中断。在中断方式下,详细说明了中断使能配置和优先级设置,并提供了函数封装的编程示例,包括主函数和中断回调函数的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、硬件设备

STM32F103ZET3开发板
STLink

1、实现功能

上电初始化后,LED0灯灭;
当按键按下时LED0状态翻转;

3、原理图分析

在这里插入图片描述
在这里插入图片描述
LED灯原理在上节已经解释,这节不再赘述,这里共有两个按键分别为KEY0、KEY1,以KEY0为例当按键按下时,电流流向按键,然后接地,则 PE4 为低电平0。
当按键松开时,电流流向 PE4 ,则 PE4 是高电平 1。
因此实现按键控制LED可以有两种方法
1、扫描:读取PE4引脚的电平,当为低电平时LED状态发生反转
2、中断:按键按下,触发外部中断,则将LED2灯状态翻转。

3、CubeMX配置

这里不再详细阐释步骤,采用中断控制LED时,记得要开启中断使能,这里的优先级采用默认的抢占优先级0,子优先级0,其中优先级数越小代表该中断的优先级也就越高。
按键

配置RCC时钟源
在这里插入图片描述

3、程序编写

采用模块化编程方式,适合后续的程序调用和移植,也可以理解为函数封装

函数封装: 函数封装是指将一组相关的功能封装到一个函数中,以便重复使用。它可以帮助程序员更有效地编写代码,并减少重复代码的重复编写。
方法一:

key.c

#include "key.h"
#include "led.h"

void Key(void)
{
	if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4))
	{
		HAL_Delay(100);//按键消抖
		if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4))
			Red_ON();
		else Red_OFF();
	}
}

key.h

#ifndef _KEY_H
#define _KEY_H
#include "main.h"
void Key(void);
#endif

main.c
直接在while后面加入

key();

方法二:

在main.c中直接增加中断回调函数,当检测到中断时执行中断回调函数,翻转LED0灯的状态。

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)//中断回调函数,当有中断发生时,将LED0灯进行翻转
{		
	 HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);	//sorry,忘记在上一章中定义LED翻转了,自己可以直接在后面定义的,如:#define LEDTOGGLE 	 HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin)
}

### STM32F103 HAL移植到UCOS-II操作系统的概述 将STM32F103 HAL移植到UCOS-II操作系统是一项复杂但可行的任务。该过程涉及多个方面的调整,包括但不限于中断管理、任务调度以及资源分配等核心模块的适配。 #### 中断服务程序的修改 在未使用UCOS-II的情况下,中断服务函数通常直接执行特定的功能逻辑。然而,在引入UCOS-II之后,为了确保RTOS能够正确管理调度任务,所有的中断都需要调用`OSIntEnter()``OSIntExit()`来通知系统当前处于中断上下文中[^2]。例如,对于串口中断服务函数: ```c void USART1_IRQHandler(void) { OSIntEnter(); // 告知uC/OS-II进入中断状态 // 处理实际的中断逻辑 if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { uint8_t data = USART_ReceiveData(USART1); os_msg_queue_put(&rxQueue, &data); // 将接收到的数据放入消息队列 } OSIntExit(); // 告知uC/OS-II退出中断状态 } ``` 这种封装方式可以防止因长时间占用CPU而导致其他高优先级任务被延迟的情况发生。 #### 初始化与任务创建 当把HAL应用于UCOS-II环境中时,还需要注意初始化顺序的问题。一般做法是在启动完成后先建立好各个基础组件(比如GPIO、TIM器等),再由main函数里通过API接口依次激活不同的线程或进程实例[^2]。下面是一个简单的例子用于说明如何构建两个分别负责LED闪烁控制按键检测的工作单元: ```c #include "os.h" #include "stm32f1xx_hal.h" #define LED_TASK_PRIO 5 #define BUTTON_TASK_PRIO 6 // 定义任务堆栈大小 static CPU_STK LedTaskStk[128]; static CPU_STK ButtonTaskStk[128]; // LED翻转任务 void LedBlinkingTask(void *p_arg){ while(TRUE){ HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); OSTimeDlyHMSM(0, 0, 1, 0); // 延迟一秒 } } // 按键扫描任务 void ButtonScanTask(void *p_arg){ while(TRUE){ if(HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_0)==RESET){ // 执行某些动作... } OSTimeDlyHMSM(0, 0, 0, 100); // 轮询间隔时间短些即可 } } int main(){ HAL_Init(); SystemClock_Config(); BSP_LED_Init(LED_GREEN); OSSafetyCriticalInit(); OSTaskCreateExt((FUNCT)LedBlinkingTask, NULL, (void *)&LedTaskStk[sizeof(LedTaskStk)/sizeof(CPU_STK)-1], LED_TASK_PRIO, 0, sizeof(LedTaskStk), (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR ); OSTaskCreateExt((FUNCT)ButtonScanTask, NULL, (void *)&ButtonTaskStk[sizeof(ButtonTaskStk)/sizeof(CPU_STK)-1], BUTTON_TASK_PRIO, 0, sizeof(ButtonTaskStk), (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR ); StartOS(); // 启动多任务机制 } ``` 以上代码片段展示了如何结合HAL驱动与UCOS-II框架共同工作的方法论之一。值得注意的是这里假设已经完成了基本外设配置如时钟树设定等工作项。 #### Flash存储区规划注意事项 如果应用程序需要用到内部闪存保存动态数据,则同样需要考虑合理划分区域边界条件等问题[^3]。这一步骤尤其重要因为不当的操作可能会覆盖掉引导加载程序或者其他关键部分从而引发不可预测的行为表现出来。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值