四、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.rhkb.cn/news/11971.html

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

相关文章

分析哲学:从 语言解剖到 思想澄清的哲学探险

分析哲学&#xff1a;从 语言解剖 到 思想澄清 的哲学探险 第一节&#xff1a;分析哲学的基本概念与公式解释 【通俗讲解&#xff0c;打比方来讲解&#xff01;】 分析哲学&#xff0c;就像一位 “语言侦探”&#xff0c;专注于 “解剖语言”&#xff0c;揭示我们日常使用的语…

XCCL、NCCL、HCCL通信库

XCCL提供的基本能力 XCCL提供的基本能力 不同的XCCL 针对不同的网络拓扑&#xff0c;实现的是不同的优化算法的&#xff08;不同CCL库最大的区别就是这&#xff09; 不同CCL库还会根据自己的硬件、系统&#xff0c;在底层上面对一些相对应的改动&#xff1b; 但是对上的API接口…

【数据结构篇】时间复杂度

一.数据结构前言 1.1 数据结构的概念 数据结构(Data Structure)是计算机存储、组织数据的⽅式&#xff0c;指相互之间存在⼀种或多种特定关系的数 据元素的集合。没有⼀种单⼀的数据结构对所有⽤途都有⽤&#xff0c;所以我们要学各式各样的数据结构&#xff0c; 如&#xff1a…

700. 二叉搜索树中的搜索

二叉搜索树中的搜索 已解答 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和一个整数值 val。 你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在&#xff0c;则返回 null 。 示例 1: 输入&#xff1a;root [4,2,7,1,3], v…

Spring Cloud工程搭建

目录 工程搭建 搭建父子工程 创建父工程 Spring Cloud版本 创建子项目-订单服务 声明项⽬依赖 和 项⽬构建插件 创建子项目-商品服务 声明项⽬依赖 和 项⽬构建插件 工程搭建 因为拆分成了微服务&#xff0c;所以要拆分出多个项目&#xff0c;但是IDEA只能一个窗口有一…

Rust中使用ORM框架diesel报错问题

1 起初环境没有问题&#xff1a;在Rust开发的时候起初使用的是mingw64平台加stable-x86_64-pc-windows-gnu编译链&#xff0c;当使用到diesel时会报错&#xff0c;如下&#xff1a; x86_64-w64-mingw32/bin/ld.exe: cannot find -lmysql具体信息很长这是主要信息是rust找不到链…

【C++】P1765 手机

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;问题描述题目内容示例&#xff1a; 键盘布局 &#x1f4af;我的做法思路问题与优化我的代码实现分析与问题 &#x1f4af;老师的做法思路老师的代码实现分析优点 &#x1f…

本地快速部署DeepSeek-R1模型——2025新年贺岁

一晃年初六了&#xff0c;春节长假余额马上归零了。今天下午在我的电脑上成功部署了DeepSeek-R1模型&#xff0c;抽个时间和大家简单分享一下过程&#xff1a; 概述 DeepSeek模型 是一家由中国知名量化私募巨头幻方量化创立的人工智能公司&#xff0c;致力于开发高效、高性能…

3 卷积神经网络CNN

1 Image Classification (Neuron Version) – 1.1 Observation 1 1.2 Observation 2 如果不同的receptive field需要相同功能的neuron&#xff0c;可以使这些neuron共享参数 1.3 Benefit of Convolutional Layer 2 Image Classification (Filter Version) 不用担心filter大小…

QT交叉编译环境搭建(Cmake和qmake)

介绍一共有两种方法&#xff08;基于qmake和cmake&#xff09;&#xff1a; 1.直接调用虚拟机中的交叉编译工具编译 2.在QT中新建编译套件kits camke和qmake的区别&#xff1a;CMake 和 qmake 都是自动化构建工具&#xff0c;用于简化构建过程&#xff0c;管理编译设置&…

STM32 对射式红外传感器配置

这次用的是STM32F103的开发板&#xff08;这里面的exti.c文件没有how to use this driver 配置说明&#xff09; 对射式红外传感器 由一个红外发光二极管和NPN光电三极管组成&#xff0c;M3固定安装孔&#xff0c;有输出状态指示灯&#xff0c;输出高电平灯灭&#xff0c;输出…

SQL优化

1.插入数据 &#xff08;1&#xff09;insert优化 批量插入&#xff1a;insert into tb_test values(1,tom),(2,cat),(3.jerry); 手动提交事务&#xff1a; start transaction; insert into tb_test values(1,tom),(2,cat),(3.jerry); insert into tb_test values(12,tom),(22…

BFS(广度优先搜索)——搜索算法

BFS&#xff0c;也就是广度&#xff08;宽度&#xff09;优先搜索&#xff0c;二叉树的层序遍历就是一个BFS的过程。而前、中、后序遍历则是DFS&#xff08;深度优先搜索&#xff09;。从字面意思也很好理解&#xff0c;DFS就是一条路走到黑&#xff0c;BFS则是一层一层地展开。…

单调队列 滑动窗口(题目分析+C++完整代码)

滑动窗口/单调队列 原题链接 AcWing 154. 滑动窗口 题目描述 给定一个数组。 有一个大小为 k的滑动窗口&#xff0c;它从数组的最左边移动到最右边。 你只能在窗口中看到 k个数字。 每次滑动窗口向右移动一个位置。 以下是一个例子&#xff1a; 该数组为 [1 3 -1 -3 5 3 6 7…

爬虫基础(四)线程 和 进程 及相关知识点

目录 一、线程和进程 &#xff08;1&#xff09;进程 &#xff08;2&#xff09;线程 &#xff08;3&#xff09;区别 二、串行、并发、并行 &#xff08;1&#xff09;串行 &#xff08;2&#xff09;并行 &#xff08;3&#xff09;并发 三、爬虫中的线程和进程 &am…

【C++】B2120 单词的长度

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述&#x1f4af;我的做法代码实现&#xff1a;思路解析&#xff1a; &#x1f4af;老师的第一种做法代码实现&#xff1a;思路解析&#xff1a; &#x1f4af;老师的…

nvm的安装和使用

打开地址下载 https://github.com/coreybutler/nvm-windows/releases 推荐下载&#xff0c;nvm-setup.zip 这个。可能有的教程会让下载nvm-noinstall.zip 。noinstall确实下载之后不用安装&#xff0c;但是要自己配置setting.txt文件&#xff0c;以及环境变量 。 安装nvm 在电…

嵌入式知识点总结 操作系统 专题提升(四)-上下文

针对于嵌入式软件杂乱的知识点总结起来&#xff0c;提供给读者学习复习对下述内容的强化。 目录 1.上下文有哪些?怎么理解? 2.为什么会有上下文这种概念? 3.什么情况下进行用户态到内核态的切换? 4.中断上下文代码中有哪些注意事项&#xff1f; 5.请问线程需要保存哪些…

Python在线编辑器

from flask import Flask, render_template, request, jsonify import sys from io import StringIO import contextlib import subprocess import importlib import threading import time import ast import reapp Flask(__name__)RESTRICTED_PACKAGES {tkinter: 抱歉&…

web-SQL注入-CTFHub

前言 在众多的CTF平台当中&#xff0c;作者认为CTFHub对于初学者来说&#xff0c;是入门平台的不二之选。CTFHub通过自己独特的技能树模块&#xff0c;可以帮助初学者来快速入门。具体请看官方介绍&#xff1a;CTFHub。 作者更新了CTFHub系列&#xff0c;希望小伙伴们多多支持…