STM32_hal库学习(2)-按键(中断/非中断)控制LED

news2024/11/26 9:32:51

在这篇文章我将使用两种方法实现按键控制,分别使用非中断控制和中断控制LED

非中断按键控制LED:

对于非中断实现按键控制led,我将直接从上一个工程led闪烁进行修改

STM32F103—Hal库的学习(1)LED灯闪烁-CSDN博客

非中断实现按键控制LED,首先需要配置GPIO的控制引脚,我这里选择PA5作为按键输入,GPIO配置为:

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);

  /*Configure GPIO pin : PC13 */
  GPIO_InitStruct.Pin = GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
	
	GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

其中PC13是stm32f103c8t6的LED灯,其中将gpio5设置为输入模式,按键另外一端接地,关于不了解该设置上拉、下拉或者无上下拉输入的,可以看我另外一篇文章:

关于GPIO的上拉、下拉,无上下拉-CSDN博客

我这里设置为上拉输入,未接外部电路时,其内部与vcc接一个上拉电阻,呈现高电平。

之后开始编写按键函数,

uint8_t Key_GetNum(void)
{
	uint8_t KeyNum = 0;		//定义变量,默认键码值为0
	
	if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == 0)			//读PB1输入寄存器的状态,如果为0,则代表按键1按下
	{
		HAL_Delay(20);											//延时消抖
		while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == 0);	//等待按键松手
		HAL_Delay(20);											//延时消抖
		KeyNum = 1;												//置键码为1
	}
	
	return KeyNum;			//返回键码值,如果没有按键按下,所有if都不成立,则键码为默认值0
}

当pa5按下时,a5呈低电平。并且返回1,若未按按键,因为上拉电阻,所以其呈现高电平,返回0。

首先再main外面对函数进行声明:

uint8_t Key_GetNum(void);

然后对while(1)内编写程序

if(Key_GetNum()==1)
{
	
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
}

若按键返回1,则电平翻转。

下载测试:测试成功!

中断按键控制LED:

既然要用到中断,那么我们自然要重新配置Stm32Cubemx了。

1.新建工程->选择自己的芯片,我的是stm32f103c8t6,双击2号框。

2.既然要加入中断,自然时钟不可少,所以我们先设置RCC,开启外部时钟晶振,开启高速时钟(HSE)选择外部晶振。

3.引脚设置我们根据原理图可知,stm32f103c8t6最小系统的led灯引脚是PC13,当然你们也可以自己选择一个其他引脚,做相同设置后外接一个led。

选择pc13后设置输出,我们设置PA5为中断按键输入,如下图;

如果你是用4脚stlink下载,还得设置debug,如下图:

之后我们对gpio的引脚进行设置,

可见这有两个引脚可以设置,点击PA5和PC13。首先点击PA5

        可见PA5的GPIO中断模式有框内6种,从上往下分别为:上升沿触发外部中断、下降沿触发中断、上升/下降沿触发中断、上升沿触发外部事件、下降沿触发事件、上升/下降沿触发事件

        这六种模式到底是什么意思?有什么应用场景呢?具体可以见我另外一篇文章:

GPIO的中断和事件触发模式:上升、下降沿触发.......-CSDN博客

        根据原理,本文按键是接地,所以我们选择下降沿触发外部中断(有很多人容易搞混,因为按键另外一端接地,所以我们需要按键按下后,引脚变为低电平是触发,所以非中断选用的是上拉模式:平常为1,按下后变0;中断则是下降沿触发:当gpio从1变成0,“下降后”才实现触发)。

        关于PC13,将其设为上拉。

4.有了中断,自然要配置NVIC,其允许中断的嵌套和中断优先级。选择NVIC,点击2框,后面可以设置优先级,前面是抢占优先级,后面是响应优先级,注意3框,这是系统时钟,可以设置成0(之前是15,然后nvic生成失败,有知道原因的大佬,希望可以在评论区教教~)。

抢占优先级

抢占优先级决定了一个中断能否打断当前正在执行的中断。抢占优先级数值越低,优先级越高。当多个中断发生时,具有更高抢占优先级的中断会打断具有更低抢占优先级的中断。

响应优先级

响应优先级用于决定在抢占优先级相同时,中断的响应顺序。响应优先级数值越低,优先级越高。当两个中断具有相同的抢占优先级时,响应优先级较高的中断会先被处理。

当然,你也可以直接在GPIO设置,如下图:

5.最后,别忘了配置时钟树,我这儿配置了72MHz,可以根据自己需要配置,注意看线上有最高频率,因为APB1那根线最高为36MHz,所以需要对其分频。高频率的处理速度更快,但是功耗会更高,低频率,功耗则会更低。

6.工程配置:2框是工程名字,3是储存路径,最后不要出现中文。4是选择你的ide,我用的是mdk

然后,

如下图,点击1框,注意2框的那三条选项,第一条的意思是:将库的.c和.h全部复制到工程中,优点是日后直接工程移植会方便些,缺点是体积大,编译时间长;第二条是只复制需要的c和h,一般是最优选;第三条是不复制文件,直接从软件包存放位置导入.C和.H ,体积最小。3框保持默认就行,也可以根据自己需要修改。

最后点击4框生成程序。

生成程序后,可以看到时钟和gpio均有更新。

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);

  /*Configure GPIO pin : PC13 */
  GPIO_InitStruct.Pin = GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PA5 */
  GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI9_5_IRQn, 1, 2);
  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

点开stm32f1xx_hal_gpio.c(可以在stm32f1xx_it.c的中断函数跳过去)文件,可以看到

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}

        这是外部中断处理函数,if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)如果检测到中断挂起(即返回值不为0),则进入函数,__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin)是清除标志位,HAL_GPIO_EXTI_Callback(GPIO_Pin);是调用回调函数。

        然后打开回调函数

__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_GPIO_EXTI_Callback could be implemented in the user file
   */
}

发现前面有__weak,这代表这个函数是个弱定义函数,代表我们可以在其他地方重新定义这个回调函数。

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_5)
    {
       

        // 简单去抖动处理
        HAL_Delay(20);
        if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == GPIO_PIN_RESET)
        {
            // 持续等待直到按键释放
            while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == GPIO_PIN_RESET) {}

            // 切换LED状态
            HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
        }
    }
		 __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_5);  // 清除中断标志
}

之后测试,发现实验成功:

源码下载:

stm32f103c8t6hal库的按键控制led(中断/非中断两种)资源-CSDN文库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1871887.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

<sa8650>QCX ISP Tuning 使用详解 — Tuning前置条件

<sa8650>QCX ISP Tuning 使用详解 — Tuning前置条件 一 如何安装 Qualcomm Chromatix™ 摄像头校准工具二 如何使用 Qualcomm Chromatix™ tuning工具创建tuning项目2.1 创建工程前提依赖2.2 创建工程2.3 添加场景2.4 编辑区域触发器三 如何创建Tuning 树一 如何安装 Qualco…

TypeScript(笔记版)

简介: nvm安装必须先把自己的node卸了,再去安装nvm TS就是js的超集 对js进行了扩展 浏览器不支持ts,要转换为js才可以。 ts是用来编程人员爽的 js的写法拿到ts也可以,ts代码量更大,但ts代码更加清晰 可以在playg…

C++精解【8】

文章目录 运算,- 加减法* / 乘除法逐元 乘法逐元 除法逐元综合运算矩阵乘法与加减法 转置、共轭、伴随矩阵点乘法,叉积 运算 ,- 加减法 逐元加减法 #include <iostream> #include "e:/eigen/Eigen/Dense" using namespace std;int main() {Eigen::Matrix2d …

并发编程工具集——Lock和Condition(上)(十二)

简述&#xff1a;Java SDK 并发包通过 Lock 和 Condition 两个接口来实现管程&#xff0c;其中 Lock 用于解决互斥问题&#xff0c;Condition 用于解决同步问题。 再造管程的理由和期望 理由&#xff1a;synchronized 没有办法解决“破坏不可抢占条件方案”。 原因是synchroniz…

可燃气体报警器计量校准:重要性与实践指南

在燃气机锅炉房、酒店厨房以及天然气管路等关键场所&#xff0c;可燃气体检测报警器的准确性和可靠性直接关系到人们的生命安全和财产安全。因此&#xff0c;对可燃气体报警器进行定期的计量校准至关重要。 在这篇文章中&#xff0c;佰德将从校准的必要性、方法与步骤、实际案…

【知识学习】阐述Unity3D中动画渲染的概念及使用方法示例

Unity3D中的卡通渲染&#xff08;Cartoon Rendering&#xff09;是一种渲染技术&#xff0c;它模仿传统手绘动画或漫画的视觉效果。这种渲染风格通常具有鲜明的颜色、清晰的轮廓线和简化的光影效果&#xff0c;常用于制作动画、游戏和其他视觉媒体。 卡通渲染的基本概念 轮廓…

Ansible-playbook的逻辑控制 ②

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 在《Ansible-playbook的逻辑控制 ①》中&#xff0c;梳理了逻辑控制when的使用场景&#xff0c;本文则继续梳理学习loop与block块…

python调用nodeJs执行js代码

文章目录 安装环境二、python程序调用js代码示例 安装环境 需要安装nodejs、python python库安装 pip install PyExecJS2 二、python程序调用js代码 示例 js代码&#xff1a; function sum(a,b){return ab; }python代码 import execjsjs_codeopen(dejmo.js).read() js_…

springcloud第4季 分布式事务seata作用服务搭建1

一 seata作用 1.1 seata简介 1.seata是一款解决分布式事务的解决方案&#xff0c;致力于在微服务架构下提供高性能和简单易用的分布式事务服务。 1.2 seata的术语 一个中心&#xff1a;全局事务id&#xff0c;xid&#xff0c;在调用服务链路的上下文中进行传播。TC(Transa…

风机过滤机组介绍

一、定义 FFU英文全称为&#xff08;Fan Filter Unit&#xff09;&#xff0c;中文专业用语为风机过滤机组。FFU广泛应用于洁净室、洁净工作台、洁净生产线、组装式洁净室和局部百级等应用场合。 二、FFU的组成 FFU主要由四部分组成&#xff1a; 1.箱体 其材质常用镀锌铝合…

SpringBoot脚手架MySpringBootAPI(PgSQL+Druid+MyBatisPlus+Lombok)

MySpringBootAPI SpringBoot脚手架&#xff0c;基于SpringBootDruidPgSQLMyBatisPlusFastJSONLombok&#xff0c;其他的请自行添加和配置。 Author powered by Moshow郑锴(大狼狗) , https://zhengkai.blog.csdn.net 如何运行 1.首先确保你是JDK17&#xff0c;推荐微软的MSJDK…

[数据集][目标检测]游泳者溺水检测数据集VOC+YOLO格式8275张4类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;8275 标注数量(xml文件个数)&#xff1a;8275 标注数量(txt文件个数)&#xff1a;8275 标注…

5分钟,从购买域名到HTTPS访问

5分钟&#xff0c;从购买域名到HTTPS访问 架构师手把手教技术 大家好&#xff0c;最近很多小伙伴咨询关于在 安装nginx 和 部署SSL证书 方面的技术&#xff0c;因此我录制了这个视频&#xff0c;希望可以帮助大家更快速地掌握这些关键技能。 首先&#xff0c;让我们从购买域名…

【离散数学·图论】(复习)

一、基本概念 1.一些基本术语&#xff1a; 2.点u&#xff0c;v邻接&#xff08;或相邻&#xff09;: 边e称为关联顶点u和v,or e连接u和v; 3.G(V,E)中&#xff0c;顶点v所有邻居的集合&#xff1a;N(v), 成为v的邻域。 4.度 &#xff1a; deg(v) 5.悬挂点&#xff1a;度为1的…

「C系列」C 经典练习实例

文章目录 1. 基本输入输出2. 字符串操作3. 数组与循环4. 函数与递归5. 逻辑与条件6. 数学问题7. 数字与数学8. 数组与字符串9. 逻辑与条件10. 结构体和联合体11. 指针12. 文件操作13. 动态内存分配相关链接 C语言经典练习实例及详细代码可以涵盖多个方面&#xff0c;从基础输入…

深度学习实验第T1周:实现mnist手写数字识别

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营](https://mp.weixin.qq.com/s/0dvHCaOoFnW8SCp3JpzKxg) 中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊](https://mtyjkh.blog.csdn.net/)** 目录 目录 一、前言 二、我的环境 三、…

《梦醒蝶飞:释放Excel函数与公式的力量》6.3NOW函数

6.3NOW函数 1&#xff09;NOW函数概述 NOW函数是Excel中一个非常实用的内置函数&#xff0c;它返回当前的日期和时间。这个函数可以自动更新&#xff0c;以反映打开工作簿时的确切日期和时间。 2&#xff09;函数语法 NOW函数的语法非常简单&#xff0c;因为它不需要任何参…

轻量级仿 SpringBoot 程序

但凡 Java 程序&#xff0c;想必就是 Spring 程序&#xff1b;但凡 Spring 程序&#xff0c;想必就是 SpringBoot 程序——且慢&#xff0c;当今尚有不是 SpringBoot 即 SpringMVC 的程序不&#xff1f;有——老旧的遗留系统不就是嘛~——不&#xff0c;其实只要稍加“调教”&a…

测评:【AI办公】版本更迭与AI加持下的最新ONLYOFFICE桌面编辑器8.1

你是否还在为没有一款合适的在线桌面编辑器而苦恼&#xff1f;你是否还在因为办公软件的选择过少而只能使用WPS或者office&#xff1f;随着办公需求的不断变化和发展&#xff0c;办公软件也在不断更新和改进。ONLYOFFICE 作为一款全功能办公软件&#xff0c;一直致力于为用户提…

Java使用poi生成word文档的简单实例

Java使用poi生成word文档的简单实例 生成的效果如下&#xff1a; 用到的poi的简单的知识 新建一个word对象 //新建文件 XWPFDocument document new XWPFDocument();新建段落以及文字样式 //创建段落 XWPFParagraph paragraph document.createParagraph(); paragraph.se…