四、GPIO中断实现按键功能

4.1 GPIO简介

        输入输出(I/O)是一个非常重要的概念。I/O泛指所有类型的输入输出端口,包括单向的端口如逻辑门电路的输入输出管脚和双向的GPIO端口。而GPIO(General-Purpose Input/Output)则是一个常见的术语,指的是通用输入输出接口。

        下面有请DeepSeek发言

LPC1110系列Cortex-M0微控制器的GPIO口的结构特点:

1端口可由软件配置为输入输出
2引脚默认为输入(所以点灯时需要改下方向)
3端口引脚的读写操作可屏蔽
4每个单独引脚可被用作外部中断输入引脚
5每个GPIO中断可配置为 高、低电平、下降、上升沿或双边沿触发
6可对单独端口的中断级别进行配置

4.2 GPIO口的寄存器

        所有GPIO寄存器都为32位 

        GPIO端口基址为

端口0  0x5000 0000
端口1  0x5001 0000

端口2

 0x5002 0000
端口3 0x5003 0000

4.2.1 数据寄存器  GPIOnDATA

        用于读取输入引脚的状态数据或者配置输出引脚的输出状态

        对应端口位置后四位范围为 0000 ~ 3FFC

11:0PIOn_0 ~ PIOn_11的输入/输出数据
31:12保留

4.2.2 方向寄存器 GPIOnDIR

11:0PIOn_0 ~ PIOn_11的输入/输出方向   0为输入, 1为输出  位数0-11与0-11引脚一一对应
31:12保留

4.2.3 中断触发寄存器 GPIOnIS

        相较于基地址偏移量0x8004 即0x500n 8004

11:0PIOn_x    0为边沿触发,1为电平触发
31:12保留

4.2.4 中断双边沿触发寄存器 GPIOnIBE

        相较于基地址偏移量0x8008 即0x500n 8008

11:0

0为通过4.2.5中寄存器GPIOnIEV控制PIOn_x的中断

1为通过PIOn_x上双边沿触发中断

31:12保留

4.2.5 中断事件寄存器 GPIOnIEV

        相较于基地址偏移量0x800C 即0x500n 800C

11:0

0为上升沿或者高电平触发中断

1为下降沿或者低电平触发中断

具体边沿还是电平 看4.2.3中GPIOnIS的设置

31:12保留

4.2.6 中断屏蔽寄存器 GPIOnIE

        相较于基地址偏移量0x8010 即0x500n 8010

11:0

0为中断被屏蔽

1为中断不被屏蔽

31:12保留

4.2.7 原始中断状态寄存器 GPIOnIRS

        相较于基地址偏移量0x8014 即0x500n 8014

        屏蔽之前的中断状态

11:0

0为无中断

1为满足中断要求

31:12保留

4.2.8 屏蔽中断状态寄存器 GPIOnMIS

        相较于基地址偏移量0x8018 即0x500n 8018

        考虑了屏蔽操作之后是否有中断

11:0

0为无中断,或者中断被屏蔽

1为满足中断要求

31:12保留

4.2.9 中断清除寄存器 GPIOnIC

        相较于基地址偏移量0x801C 即0x500n 801C

11:0

0无操作

1为清除PIOn_x上的边沿检测逻辑

31:12保留

4.3 LPC上的GPIO按键

        按键按下引脚低电平,不按是高电平

4.4 按键控制LED闪烁频率

任务:

1. BUTTON(PIO3_5)按键按下,闪烁频率为1Hz,再次按下,恢复闪烁频率为0.5Hz;

2. WEAKUP(PIO1_4)按键按下,闪烁频率为2Hz,再次按下,恢复闪烁频率为0.5Hz;

3. 适当考虑按键防抖功能。            

思路:

        对于闪烁频率的修改,首先考虑用什么控制LED闪烁,结合上章可以用SysTick,然后按键按下改变SysTick周期即可

        对于按键防抖,由于按键固有的物理结构,按下后弹簧一上一下会影响中断,需要用延时函数过滤抖动。

抖动时间大概10ms这样, 我们可以用个延时函数过滤掉这个抖动过程,延时20ms就足够了

代码:

利用之前写过的函数即可,复制个新工程,然后main文件里代码如下

#include <LPC11xx.h>
#include "LED.h"//延时ms函数 // 太粗糙了,而且要根据机器指令与时钟周期关系调整,也就防抖延时用一下
__inline void delay_ms(uint32_t a)    //约1ms延时函数 
{                           uint32_t i;while( a -- != 0){for(i = 0; i<5500; i++);}             
}int flag1 = 0, flag2 = 0; // 判断botton 和 wakeup 按键上一次状态
int main()
{LED_Init(); // PIO1_4LPC_IOCON->PIO1_4 &= ~(0x1F);  // 清除之前的配置LPC_IOCON->PIO1_4 |= 0x00;     // 配置为GPIO功能LPC_GPIO1->DIR &= ~(1UL << 4);// 设置GPIO方向为输入LPC_GPIO1->IS &= ~(0x1 << 4); // 清除第 4 位,设置为边沿触发LPC_GPIO1->IBE &= ~(0x1 << 4); // 清除第 4 位,设置为单边沿触发LPC_GPIO1->IEV &= ~(0x1 << 4); // 清除第 4 位,设置为低电平触发LPC_GPIO1 -> IE |= (0x1<<4); // 使能端口中断LPC_IOCON->PIO1_4 |= (1UL << 5);          // 使能滞后模式LPC_GPIO1->IC |= (1UL << 4); // 清除中断标志位NVIC_EnableIRQ(EINT1_IRQn); // 使能GPIO1中断// PIO3_5LPC_IOCON->PIO3_5 &= ~(0x1F);   // 清除之前的配置LPC_IOCON->PIO3_5 |= 0x00;      // 配置为GPIO功能LPC_GPIO3->DIR &= ~(1UL << 5);// 设置GPIO方向为输入LPC_GPIO3->IS &= ~(0x1 << 5); // 清除第 5 位,设置为边沿触发LPC_GPIO3->IBE &= ~(0x1 << 5); // 清除第 5 位,设置为单边沿触发LPC_GPIO3->IEV &= ~(0x1 << 5); // 清除第 5 位,设置为低电平触发LPC_GPIO3 -> IE |= (0x1<<5); // 使能端口中断LPC_IOCON->PIO3_5 |= (1UL << 5);  // 使能滞后模式LPC_GPIO3->IC |= (1UL << 5); //清除中断标志NVIC_EnableIRQ(EINT3_IRQn);SysTick_Config(SystemCoreClock/100); // 0.01s进一次中断 1s翻转一次 0.5 Hzwhile(1){}
}void SysTick_Handler() /// 系统节拍定时器中断函数
{static unsigned long ticks;if(ticks++ >= 99){ticks = 0;LED_Toggle();}
}// GPIO3_5的中断服务函数,处理BUTTON按键按下事件
void PIOINT3_IRQHandler(void)
{if((LPC_GPIO3->MIS & (1UL << 5)) == (1UL << 5))// 检查是否是PIO3_5的中断{ delay_ms(20); // 消抖while((LPC_GPIO3->DATA & (1UL << 5)) == 0);delay_ms(20);if(flag1)SysTick_Config(SystemCoreClock/100); // 0.01s进一次中断 1s翻转一次 0.5 Hzelse SysTick_Config(SystemCoreClock/200); // 0.005s进一次中断 0.5s翻转一次 1 Hzflag1 = !flag1;LPC_GPIO3->IC |= (1UL << 5);          // 清除中断标志}
}
// GPIO1_4的中断服务函数,处理WAKEUP按键按下事件
void PIOINT1_IRQHandler(void)
{if((LPC_GPIO1->MIS & (1UL << 4)) == (1UL << 4)) // 检查是否是PIO1_4的中断{delay_ms(20);while((LPC_GPIO1->DATA & (1UL << 4)) == 0);delay_ms(20);if(flag2)SysTick_Config(SystemCoreClock/100); // 0.01s进一次中断 1s翻转一次 0.5 Hzelse SysTick_Config(SystemCoreClock/400); // 0.0025s进一次中断 0.2s翻转一次 2 Hz flag2 = !flag2;LPC_GPIO1->IC |= (1UL << 4);           // 清除中断标志}
}

模块化一下,新建Button.c Button.h文件,便于之后移植工程

main.c

#include <LPC11xx.h>
#include "LED.h"
#include "Button.h"int main()
{LED_Init(); WAKEUP_Init();Button_Init();while(1){}
}void SysTick_Handler() /// 系统节拍定时器中断函数
{static unsigned long ticks;if(ticks++ >= 99){ticks = 0;LED_Toggle();}
}

Button.c

#include "Button.h"
int flag1 = 0, flag2 = 0; // 判断botton 和 wakeup 按键上一次状态//延时ms函数 // 太粗糙了,而且要根据机器指令与时钟周期关系调整,也就防抖延时用一下
__inline void delay_ms(uint32_t a)    //约1ms延时函数 
{                           uint32_t i;while( a -- != 0){for(i = 0; i<5500; i++);}             
}void WAKEUP_Init(void)
{LPC_SYSCON -> SYSAHBCLKCTRL |= (1UL << 6) | (1UL << 16); // 使能GPIO时钟和IO时钟// PIO1_4LPC_IOCON->PIO1_4 &= ~(0x1F);  // 清除之前的配置LPC_IOCON->PIO1_4 |= 0x00;     // 配置为GPIO功能LPC_GPIO1->DIR &= ~(1UL << 4);// 设置GPIO方向为输入LPC_GPIO1->IS &= ~(0x1 << 4); // 清除第 4 位,设置为边沿触发LPC_GPIO1->IBE &= ~(0x1 << 4); // 清除第 4 位,设置为单边沿触发LPC_GPIO1->IEV &= ~(0x1 << 4); // 清除第 4 位,设置为低电平触发LPC_GPIO1 -> IE |= (0x1<<4); // 使能端口中断LPC_IOCON->PIO1_4 |= (1UL << 5);          // 使能滞后模式LPC_GPIO1->IC |= (1UL << 4); // 清除中断标志位NVIC_EnableIRQ(EINT1_IRQn); // 使能GPIO1中断
}void Button_Init(void)
{LPC_SYSCON -> SYSAHBCLKCTRL |= (1UL << 6) | (1UL << 16); // 使能GPIO时钟和IO时钟// PIO3_5LPC_IOCON->PIO3_5 &= ~(0x1F);   // 清除之前的配置LPC_IOCON->PIO3_5 |= 0x00;      // 配置为GPIO功能LPC_GPIO3->DIR &= ~(1UL << 5);// 设置GPIO方向为输入LPC_GPIO3->IS &= ~(0x1 << 5); // 清除第 5 位,设置为边沿触发LPC_GPIO3->IBE &= ~(0x1 << 5); // 清除第 5 位,设置为单边沿触发LPC_GPIO3->IEV &= ~(0x1 << 5); // 清除第 5 位,设置为低电平触发LPC_GPIO3 -> IE |= (0x1<<5); // 使能端口中断LPC_IOCON->PIO3_5 |= (1UL << 5);  // 使能滞后模式LPC_GPIO3->IC |= (1UL << 5); //清除中断标志NVIC_EnableIRQ(EINT3_IRQn);
}// GPIO3_5的中断服务函数,处理BUTTON按键按下事件
void PIOINT3_IRQHandler(void)
{if((LPC_GPIO3->MIS & (1UL << 5)) == (1UL << 5))// 检查是否是PIO3_5的中断{ delay_ms(20); // 消抖while((LPC_GPIO3->DATA & (1UL << 5)) == 0);delay_ms(20);if(flag1)SysTick_Config(SystemCoreClock/100); // 0.01s进一次中断 1s翻转一次 0.5 Hzelse SysTick_Config(SystemCoreClock/200); // 0.005s进一次中断 0.5s翻转一次 1 Hzflag1 = !flag1;LPC_GPIO3->IC |= (1UL << 5);          // 清除中断标志}
}
// GPIO1_4的中断服务函数,处理WAKEUP按键按下事件
void PIOINT1_IRQHandler(void)
{if((LPC_GPIO1->MIS & (1UL << 4)) == (1UL << 4)) // 检查是否是PIO1_4的中断{delay_ms(20);while((LPC_GPIO1->DATA & (1UL << 4)) == 0);delay_ms(20);if(flag2)SysTick_Config(SystemCoreClock/100); // 0.01s进一次中断 1s翻转一次 0.5 Hzelse SysTick_Config(SystemCoreClock/400); // 0.0025s进一次中断 0.2s翻转一次 2 Hz flag2 = !flag2;LPC_GPIO1->IC |= (1UL << 4);           // 清除中断标志}
}

Button.h

#ifndef _BUTTON_H_
#define _BUTTON_H_#include <LPC11xx.h>void WAKEUP_Init(void);
void Button_Init(void);#endif

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

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

相关文章

【Elasticsearch】post_filter

post_filter是 Elasticsearch 中的一种后置过滤机制&#xff0c;用于在查询执行完成后对结果进行过滤。以下是关于post_filter的详细介绍&#xff1a; 工作原理 • 查询后过滤&#xff1a;post_filter在查询执行完毕后对返回的文档集进行过滤。这意味着所有与查询匹配的文档都…

从零开始:用Qt开发一个功能强大的文本编辑器——WPS项目全解析

文章目录 引言项目功能介绍1. **文件操作**2. **文本编辑功能**3. **撤销与重做**4. **剪切、复制与粘贴**5. **文本查找与替换**6. **打印功能**7. **打印预览**8. **设置字体颜色**9. **设置字号**10. **设置字体**11. **左对齐**12. **右对齐**13. **居中对齐**14. **两侧对…

【IoCDI】_Spring的基本扫描机制

目录 1. 创建测试项目 2. 改变启动类所属包 3. 使用ComponentScan 4. Spring基本扫描机制 程序通过注解告诉Spring希望哪些bean被管理&#xff0c;但在仅使用Bean时已经发现&#xff0c;Spring需要根据五大类注解才能进一步扫描方法注解。 由此可见&#xff0c;Spring对注…

通向AGI之路:人工通用智能的技术演进与人类未来

文章目录 引言:当机器开始思考一、AGI的本质定义与技术演进1.1 从专用到通用:智能形态的范式转移1.2 AGI发展路线图二、突破AGI的五大技术路径2.1 神经符号整合(Neuro-Symbolic AI)2.2 世界模型架构(World Models)2.3 具身认知理论(Embodied Cognition)三、AGI安全:价…

【工具变量】中国省级八批自由贸易试验区设立及自贸区设立数据(2024-2009年)

一、测算方式&#xff1a;参考C刊《中国软科学》任晓怡老师&#xff08;2022&#xff09;的做法&#xff0c;使用自由贸易试验区(Treat Post) 表征&#xff0c;Treat为个体不随时间变化的虚拟变量&#xff0c;如果该城市设立自由贸易试验区则赋值为1&#xff0c;反之赋值为0&am…

Java进阶总结——集合

Java进阶总结——集合 说明&#xff1a;对于以上的框架图有如下几点说明 1.所有集合类都位于java.util包下。Java的集合类主要由两个接口派生而出&#xff1a;Collection和Map&#xff0c;Collection和Map是Java集合框架的根接口&#xff0c;这两个接口又包含了一些子接口或实…

计算机视觉和图像处理

计算机视觉与图像处理的最新进展 随着人工智能技术的飞速发展&#xff0c;计算机视觉和图像处理作为其中的重要分支&#xff0c;正逐步成为推动科技进步和产业升级的关键力量。 一、计算机视觉的最新进展 计算机视觉&#xff0c;作为人工智能的重要分支&#xff0c;主要研究如…

3.PPT:华老师-计算机基础课程【3】

目录 NO12​ NO34​ NO56​ NO789​ NO12 根据考生文件夹下的Word文档“PPT素材.docx”中提供的内容在PPT.pptx中生成初始的6张幻灯片 新建幻灯片6张→ctrlc复制→ctrlv粘贴开始→新建幻灯片→幻灯片(从大纲)→Word文档注❗前提是&#xff1a;Word文档必须应用标题1、标题2…

(三)QT——信号与槽机制——计数器程序

目录 前言 信号&#xff08;Signal&#xff09;与槽&#xff08;Slot&#xff09;的定义 一、系统自带的信号和槽 二、自定义信号和槽 三、信号和槽的扩展 四、Lambda 表达式 总结 前言 信号与槽机制是 Qt 中的一种重要的通信机制&#xff0c;用于不同对象之间的事件响…

基于多智能体强化学习的医疗AI中RAG系统程序架构优化研究

一、引言 1.1 研究背景与意义 在数智化医疗飞速发展的当下,医疗人工智能(AI)已成为提升医疗服务质量、优化医疗流程以及推动医学研究进步的关键力量。医疗 AI 借助机器学习、深度学习等先进技术,能够处理和分析海量的医疗数据,从而辅助医生进行疾病诊断、制定治疗方案以…

Redis --- 秒杀优化方案(阻塞队列+基于Stream流的消息队列)

下面是我们的秒杀流程&#xff1a; 对于正常的秒杀处理&#xff0c;我们需要多次查询数据库&#xff0c;会给数据库造成相当大的压力&#xff0c;这个时候我们需要加入缓存&#xff0c;进而缓解数据库压力。 在上面的图示中&#xff0c;我们可以将一条流水线的任务拆成两条流水…

使用 Ollama 和 Kibana 在本地为 RAG 测试 DeepSeek R1

作者&#xff1a;来自 Elastic Dave Erickson 及 Jakob Reiter 每个人都在谈论 DeepSeek R1&#xff0c;这是中国对冲基金 High-Flyer 的新大型语言模型。现在他们推出了一款功能强大、具有开放权重的思想链推理 LLM&#xff0c;这则新闻充满了对行业意味着什么的猜测。对于那些…

2025年大年初一篇,C#调用GPU并行计算推荐

C#调用GPU库的主要目的是利用GPU的并行计算能力&#xff0c;加速计算密集型任务&#xff0c;提高程序性能&#xff0c;支持大规模数据处理&#xff0c;优化资源利用&#xff0c;满足特定应用场景的需求&#xff0c;并提升用户体验。在需要处理大量并行数据或进行复杂计算的场景…

Unity 2D实战小游戏开发跳跳鸟 - 计分逻辑开发

上文对障碍物的碰撞逻辑进行了开发,接下来就是进行跳跳鸟成功穿越过障碍物进行计分的逻辑开发,同时将对应的分数以UI的形式显示告诉玩家。 计分逻辑 在跳跳鸟通过障碍物的一瞬间就进行一次计分,计分后会同步更新分数的UI显示来告知玩家当前获得的分数。 首先我们创建一个用…

langchain基础(二)

一、输出解析器&#xff08;Output Parser&#xff09; 作用&#xff1a;&#xff08;1&#xff09;让模型按照指定的格式输出&#xff1b; &#xff08;2&#xff09;解析模型输出&#xff0c;提取所需的信息 1、逗号分隔列表 CommaSeparatedListOutputParser&#xff1a;…

游戏AI,让AI 玩游戏有什么作用?

让 AI 玩游戏这件事远比我们想象的要早得多。追溯到 1948 年&#xff0c;图灵和同事钱伯恩共同设计了国际象棋程序 Turochamp。之所以设计这么个程序&#xff0c;图灵是想说明&#xff0c;机器理论上能模拟人脑能做的任何事情&#xff0c;包括下棋这样复杂的智力活动。 可惜的是…

鸿蒙物流项目之基础结构

目录&#xff1a; 1、项目结构2、三种包的区别和使用场景3、静态资源的导入4、颜色样式设置5、修改项目名称和图标6、静态包基础目录7、组件的抽离8、在功能模块包里面引用静态资源包的组件 1、项目结构 2、三种包的区别和使用场景 3、静态资源的导入 放在har包中&#xff0c;那…

51c视觉~CV~合集10

我自己的原文哦~ https://blog.51cto.com/whaosoft/13241694 一、CV创建自定义图像滤镜 热图滤镜 这组滤镜提供了各种不同的艺术和风格化光学图像捕捉方法。例如&#xff0c;热滤镜会将图像转换为“热图”&#xff0c;而卡通滤镜则提供生动的图像&#xff0c;这些图像看起来…

全栈开发:使用.NET Core WebAPI构建前后端分离的核心技巧(二)

目录 配置系统集成 分层项目使用 筛选器的使用 中间件的使用 配置系统集成 在.net core WebAPI前后端分离开发中&#xff0c;配置系统的设计和集成是至关重要的一部分&#xff0c;尤其是在管理不同环境下的配置数据时&#xff0c;配置系统需要能够灵活、可扩展&#xff0c…

Rust HashMap :当储物袋遇上物品清单

开场白&#xff1a;哈希映射的魔法本质 在Rust的奇幻世界里&#xff0c;HashMap就像魔法师的储物袋&#xff1a; 键值对存储 → 每个物品都有专属咒语&#xff08;键&#xff09;和实体&#xff08;值&#xff09;快速查找 → 念咒瞬间召唤物品动态扩容 → 自动伸展的魔法空间…