基于外部中中断机制,实现以下功能: 1.按键1,按下和释放后,点亮LED 2.按键2,按下和释放后,熄灭LED 3.按键3,按下和释放后,使得LED闪烁

题目:

参照外部中断的原理和代码示例,再结合之前已经实现的按键切换LED状态的实验,用外部中断改进其实现。

请自行参考文档《中断》当中,有关按键切换LED状态的内容, 自行连接电路图,基于外部中断机制,实现以下功能:

1.按键1,按下和释放后,点亮LED

2.按键2,按下和释放后,熄灭LED

3.按键3,按下和释放后,使得LED闪烁

具体按键的电路接法,可以直接参考文档的内容去实现。


关键点


分析:

按键外部中断实验
在这里插入图片描述


代码

// 完成实验代码
#include "stm32f10x.h"
#include "Delay.h"#define LED_NORMAL 0   // LED 正常状态
#define LED_BLINK 1   // LED 闪烁状态uint8_t LED_State = LED_NORMAL;  // LED 默认正常状态
void KEY_GPIO_Init(void);//初始化GPIO引脚
void KEY_AFIO_Map(void);//AFIO映射PA11到EXTI_Line11
void KEY_EXTI_Init(void);//初始化 EXTI 配置(EXTI_Line11)
void KEY_NVIC_Init(void);//初始化NVIC,开启EXTI9_5_IRQn外部中断
void EXTI9_5_IRQHandler(void);//中断服务程序
void EXTI0_IRQHandler(void);
int main(void) {KEY_GPIO_Init();KEY_AFIO_Map();KEY_EXTI_Init();KEY_NVIC_Init();GPIO_SetBits(GPIOA, GPIO_Pin_5);while (1) {if (LED_State == LED_BLINK) {GPIO_SetBits(GPIOA, GPIO_Pin_5);Delay_Ms(100);//当LED闪烁时如果不加入这行代码,//可能会引发按键操作点亮时,LED表现为熄灭状态//这是因为当GPIO_Pin_6引发中断时正好处在延迟时候,while循环没结束//当GPIO_Pin_6中断执行后,可能会执行GPIO_ResetBits(GPIOA,GPIO_Pin_5);if (LED_State == LED_NORMAL) {continue;}GPIO_ResetBits(GPIOA, GPIO_Pin_5);Delay_Ms(100);}}
}void KEY_GPIO_Init(void) {//开启GPIO外设时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);//初始化P0引脚GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//上拉输入模式GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化P6和P8引脚GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_8;//下拉输入模式GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//推免输出模式GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);
}void KEY_AFIO_Map(void) {//开启AFIO外设时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);// 映射 PA0 到 EXTI_Line0GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);// 映射 PB6 到 EXTI_Line6GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource6);// 映射 PB8 到 EXTI_Line8GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource8);}void KEY_EXTI_Init(void) {EXTI_InitTypeDef EXTI_InitStructure;EXTI_InitStructure.EXTI_Line = EXTI_Line0 ;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //采用下降沿触发EXTI_Init(&EXTI_InitStructure);EXTI_InitStructure.EXTI_Line = EXTI_Line6 | EXTI_Line8 ;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //采用上升沿触发EXTI_Init(&EXTI_InitStructure);}void EXTI9_5_IRQHandler(void) {if (EXTI_GetITStatus(EXTI_Line6) == SET) {// 清除中断标志EXTI_ClearITPendingBit(EXTI_Line6);//检查引脚输入,如果是高电平说明按下还没有松开。while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6) == Bit_SET);
LED_State = LED_NORMAL;//低电平点亮LEDGPIO_ResetBits(GPIOA, GPIO_Pin_5);}if (EXTI_GetITStatus(EXTI_Line8) == SET) {// 清除中断标志EXTI_ClearITPendingBit(EXTI_Line8);//检查引脚输入,如果是高电平说明按下还没有松开。while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_8) == Bit_SET);
LED_State = LED_NORMAL;//高电平熄灭LEDGPIO_SetBits(GPIOA, GPIO_Pin_5);}}void EXTI0_IRQHandler(void) {if (EXTI_GetITStatus(EXTI_Line0) == SET) {// 清除中断标志EXTI_ClearITPendingBit(EXTI_Line0);Delay_Ms(20);  // 简单消抖while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET);LED_State = LED_BLINK;}}//  初始化NVIC外设
void KEY_NVIC_Init(void) {//将优先级进行分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//初始化NVIC外设NVIC_InitTypeDef NVIC_InitStruct;//设置中断号NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;//开启中断NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//初始化抢占优先级NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;//初始化子优先级NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;NVIC_Init(&NVIC_InitStruct);NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;//开启中断NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//初始化抢占优先级NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;//初始化子优先级NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;NVIC_Init(&NVIC_InitStruct);}
#include "stm32f10x.h"
#include "Delay.h"#define LED_NORMAL 0   // LED 正常状态(熄灭或者点亮)
#define LED_BLINK 1   // LED 闪烁状态uint8_t LED_State = LED_NORMAL;  // LED 默认正常状态/**
* @brief  按键初始化,配置 PB6, PB8 和 PA0 为外部中断
* @param  无
* @retval 无
* 按键1控制LED点亮,它的两脚接入电源正极和PB6引脚,
* 按键2控制LED熄灭,它的两脚接入电源正极和PB8引脚,
* 按键3控制LED闪烁,它的两脚接入电源正极和PA0引脚.
*///按键引脚的的初始化一级配件相关的外部中断
void KEY_Init(void) {// 开启 GPIOB 和 AFIO 时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;// 配置 PB6 和 PB8 为下拉输入模式(因为 按键 接正极,按下时会变为高电平)GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_8;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 下拉输入模式GPIO_Init(GPIOB, &GPIO_InitStructure);// 配置 PA0 为上拉输入模式(因为 按键 接负极,按下时会变为低电平)GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入模式GPIO_Init(GPIOA, &GPIO_InitStructure);// 使用AFIO外设将三个按键引脚映射到对应达到EXTI线GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource6); // PB6GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource8); // PB8GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); // PA0EXTI_InitTypeDef EXTI_InitStructure;// 配置 EXTI6 和 EXTI8(PB6 和 PB8)为上升沿触发EXTI_InitStructure.EXTI_Line = EXTI_Line6 | EXTI_Line8;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  // 上升沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);// 配置 EXTI0(PA0)为下降沿触发EXTI_InitStructure.EXTI_Line = EXTI_Line0; // 选择 PA0 对应的 EXTI0EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发EXTI_Init(&EXTI_InitStructure);// NVIC 配置初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;// 配置 NVIC,处理 EXTI6, EXTI8 和 EXTI0 的中断// 优先级都设置为相同的优先级NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; // 处理 EXTI6 和 EXTI8 的中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; // 处理 EXTI0 的中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}/**
* @brief  LED(PA3)初始化
* @param  无
* @retval 无
*/
void LED_Init(void) {// 开启 GPIOA 时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 配置 PA3 为开漏输出模式GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 设定初始状态为 LED 关闭(PA3 高阻态)GPIO_SetBits(GPIOA, GPIO_Pin_3);
}/**
* @brief  外部中断服务函数(ISR),处理 PB6 和 PB8 按键中断
* @param  无
* @retval 无
*/
void EXTI9_5_IRQHandler(void) {// 检查是否是 PB6 触发的中断if (EXTI_GetITStatus(EXTI_Line6) == SET) {// 清除 EXTI6 中断标志EXTI_ClearITPendingBit(EXTI_Line6);// 按键持续按下,等待弹起while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6) == Bit_SET);// 点亮 LED,设置LED为正常模式LED_State = LED_NORMAL;GPIO_ResetBits(GPIOA, GPIO_Pin_3);  // 低电平,点亮 LED}// 检查是否是 PB8 触发的中断if (EXTI_GetITStatus(EXTI_Line8) == SET) {// 清除 EXTI8 中断标志EXTI_ClearITPendingBit(EXTI_Line8);// 按键持续按下,等待弹起while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_8) == Bit_SET);// 点亮 LED,设置LED为正常模式LED_State = LED_NORMAL;GPIO_SetBits(GPIOA, GPIO_Pin_3);  // 高电平,熄灭 LED}
}/**
* @brief  外部中断服务函数(ISR),处理 PA0 按键中断,LED闪烁
* @param  无
* @retval 无
*/
void EXTI0_IRQHandler(void) {if (EXTI_GetITStatus(EXTI_Line0) == SET) {// 清除 EXTI0 中断标志EXTI_ClearITPendingBit(EXTI_Line0);while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET);LED_State = LED_BLINK;}
}int main(void) {LED_Init();       // 初始化 LEDKEY_Init();       // 初始化 PB6, PB8 和 PA0 按键while (1) {if (LED_State == LED_BLINK) {// LED 进入闪烁状态GPIO_ResetBits(GPIOA, GPIO_Pin_3);  // 点亮 LEDDelay_Ms(100);  // 延时 100ms/*Delay_Ms函数是使用中断来实现的若LED在闪烁状态下,按压点亮LED按键恰好进入了上一个Delay_Ms函数等它中断延时结束就会执行LED熄灭操作这样点亮LED按键的功能就会失效,所以这里要加一个判断然后跳过后面的熄灯逻辑*/if (LED_State == LED_NORMAL) {continue;}GPIO_SetBits(GPIOA, GPIO_Pin_3);    // 熄灭 LEDDelay_Ms(100);  // 延时 100ms}}
}

在这里插入图片描述
闪烁这里线没接对,竖着才行,竖着才是联通的.
在这里插入图片描述
在这里插入图片描述
修正图片
在这里插入图片描述


解决方案总结:

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

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

相关文章

在SQL中,FROM子句中的子查询必须指定别名,即使后续未引用该别名

FROM子句中的子查询必须指定别名 示例错误示例及原因:总结: 在SQL中, FROM子句中的子查询必须指定别名, 即使后续未引用该别名 示例 查询馆藏图书最多的作者姓名及馆藏数量 SELECT 作者, COUNT(图书编号) AS 馆藏数量 FROM 图…

问道数码兽 怀旧剧情回合手游源码搭建教程(反查重优化版)

本文将对"问道数码兽"这一经典卡通风格回合制手游的服务端部署与客户端调整流程进行详细拆解,适用于具备基础 Windows 运维和手游源码调试经验的开发者参考使用。教程以实战为导向,基于原始说明内容重构优化,具备较高的内容查重避重…

Shell脚本-for循环应用案例

在Shell脚本编程中,for循环是一种强大的工具,用于处理重复性任务。无论是批量处理文件、遍历目录内容还是简单的计数任务,for循环都能提供简洁而有效的解决方案。本文将通过几个实际的应用案例来展示如何使用for循环解决具体的编程问题。 案…

Chrmo手动同步数据

地址栏输入 chrome://sync-internals分别点击这2个按钮即可触发手动同步

为什么圆形在GeoJSON中被表示为多边形(Polygon)而不是圆形类型

GeoJSON规范中没有"圆形"类型 GeoJSON是一种用于表示地理空间数据的标准格式,它的规范中只定义了以下几种基本几何类型: Point (点) LineString (线) Polygon (多边形) MultiPoint (多点) MultiLineString (多线) MultiPolygon (多多边形) GeometryCollection (几…

大数据组件学习之--Kafka 安装搭建

一、前置环境 在搭建kafka之前,请确认自己的hadoop、zookeeper是否搭建完成且可正常运行 二、下载并上传安装包(链接为百度网盘) kafka安装包 tar -zxvf /opt/software/kafka_2.12-2.4.1.tgz -C /opt/module/ 进入解压后的目录更改文件名…

PyQt6基础_pyqtgraph_折线图with缩放调节

目录 字符型横坐标代码 折线图代码 运行 创建新类,继承pg.PlotWidget,在新类中实现业务内容,重写pg.PlotWidget中的wheelEvent方法并使用业务数据实现比较理想的缩放状态。 字符型横坐标代码 class StrAxisItem(pg.AxisItem):def __init…

联邦元学习实现个性化物联网的框架

随着数据安全和隐私保护相关法律法规的出台,需要直接在中央服务器上收集和处理数据的集中式解决方案,对于个性化物联网而言,训练各种特定领域场景的人工智能模型已变得不切实际。基于此,中山大学,南洋理工大学&#xf…

audio 核心服务AudioPolicyService 和AudioFlinger启动流程

目录 1、audioserver启动 2、AudioPolicyService启动 3、AudioFlinger启动 audio的核心服务有两个,AudioPolicyService 和AudioFlinger他们到在audioserver一个进程中 1、audioserver启动 设备开机,系统启动时将执行 /system/etc/init/audioserver.rc…

反爬虫机制中的验证码识别:类型、技术难点与应对策略

在互联网数据抓取领域,验证码识别是爬虫过程中的关键环节之一。下面对常见验证码类型、技术难点及应对策略进行详细解析,并提供多种场景下的代码实现示例。 一、验证码类型与技术难点 (一)图形验证码 1. 字符验证码 特征&#…

vue element使用el-table时,切换tab,table表格列项发生错位问题

展示问题 问题描述:使用el-table的fixed"right"属性后,如果切换tab时,回出现最后一列错误的问题 官网提供解决方法:doLayout 需要注意的事项:我这里是通过组件使用的table组件,涉及多层组件封装…

示例:Spring JDBC 声明式事务(xml配置形式)

声明式事务是指在不修改源代码的情况下通过配置applicationContext.xml自动实现事务控制,其本质是AOP环绕通知。它的触发时机为:1、当目标方法执行成功时自动提交事务,2、当目标方法抛出运行时异常时,自动事务回滚 核心步骤示例&a…

在vmware中ubuntu系统因为安装了docker查不到ip地址

问题截图: 根据提供的截图信息,可以明确看到ens33网卡处于**物理连接断开(NO-CARRIER)且接口关闭(DOWN)**的状态,这是导致无法获取IP地址的直接原因。以下是针对VMware虚拟机的具体解决方案&am…

51c大模型~合集121

我自己的原文哦~ https://blog.51cto.com/whaosoft/13869815 #大模型何以擅长小样本学习? 这项研究给出详细分析 近年来,大语言模型(LLM)在人工智能领域取得了突破性进展,成为推动自然语言处理技术发展与通用人…

Babylon.js 材质统一转换指南:将 AssetContainer 中的所有材质转换为 PBRMetallicRoughnessMaterial

在现代 3D 开发中,基于物理的渲染(PBR)已成为行业标准。本文将详细介绍如何在 Babylon.js 中将 AssetContainer 加载的各种材质统一转换为 PBRMetallicRoughnessMaterial,实现项目材质的标准化。 为什么需要材质转换? PBRMetallicRoughness…

Go slice切片使用教程,一次通关!

简介 Go 中的 切片(slice) 是 Go 最强大、最常用的数据结构之一。它是对数组的轻量封装,比数组更灵活,几乎所有的集合处理都用切片来完成。 什么是切片(slice) 切片是一个拥有 长度(len&…

nodejs的包管理工具介绍,npm的介绍和安装,npm的初始化包 ,搜索包,下载安装包

nodejs的包管理工具介绍,npm的介绍和安装,npm的初始化包 ,搜索包,下载安装包 🧰 一、Node.js 的包管理工具有哪些? 工具简介是否默认特点npmNode.js 官方的包管理工具(Node Package Manager&am…

FPGA设计 时空变换

1、时空变换基本概念 1.1、时空概念简介 时钟速度决定完成任务需要的时间,规模的大小决定完成任务所需要的空间(资源),因此速度和规模就是FPGA中时间和空间的体现。 如果要提高FPGA的时钟,每个clk内组合逻辑所能做的事…

增加首屏图片

增加首屏图片&#xff08;bg.jpg&#xff09; web-mobile类型打包 //index.html脚本 <div id"myDiv_1111"style"background: url(./bg.jpg) 50% 50%/ 100% auto no-repeat ; width:100%;height:100%;position:absolute;"></div> //游戏内脚本…

贪心算法~~

目录 一、理论基础 二、题目练习 &#xff08;1&#xff09;455. 分发饼干 &#xff08;2&#xff09;53. 最大子数组和 - 力扣 &#xff08;3&#xff09;122. 买卖股票的最佳时机 II - 力扣&#xff08;LeetCode&#xff09; &#xff08;4&#xff09;860. 柠檬水找零…