物联网|按键实验---学习I/O的输入及中断的编程|读取I/O的输入信号|中断的编程方法|轮询实现按键捕获实验-学习笔记(13)

实验目的

了解擒键的工作原理及电原理图

1按键功能及用途,常见按键举例
2按键的工作原理
在这里插入图片描述
在这里插入图片描述
3按键的电路表示

课后小作业:
请大家课后百度现在流行的触摸式按键的相关信息,并考虑如何使用我们开发板的CPU如何操作触摸按键。

了解STM32F407中IO输入信号读取的原理.
了解STM32F407中外部中断的原理
.学习利用CMSIS实现I/O输入信号读取的编程
.学习利用CMSIS实现外部中断的编程
简单学习工程的移植

STM32F407中如何读取I/O的输入信号

1 STM32F407如何配置I/O为输入
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2 STM32F407如何读取输入信号

8.3.9输入配置
当I/O端口被编程为输入时:
•输出缓冲区被禁用
•施密特触发输入被激活
•上拉和下拉电阻被激活取决于在GPIOx_PUPDR寄存器的配置
•I/O引脚上的数据在每个AHB1时钟周期的输入数据寄存器中采样
•对输入数据寄存器的读访问提供I/O状态
图28显示了I/O端口位的输入配置。

STM32F407对中断的编程方法

12中断和事件
除非另有规定,本节适用于整个STM32F4xx系列。
12.1嵌套矢量中断控制器(NVIC)
12.1.1 NVIC特性
嵌套的矢量中断控制器NVIC包括以下特性:
•STM32F405xx/07xx和STM32F415xx/17xx的82个可屏蔽中断通道
STM32F42xxx和STM32F43xxx的最多91个可屏蔽中断通道
包括带FPU的Cortex™-M4的16条中断线)
•16个可编程优先级(使用4位中断优先级)
•低延迟异常和中断处理
•电源管理控制
•系统控制寄存器的实现
NVIC和处理器核心接口紧密耦合,从而实现低延迟
中断处理和延迟到达的中断的有效处理。
包括核心异常在内的所有中断都由NVIC管理。了解更多信息
关于异常和NVIC编程,请参见编程手册PM0214。
12.1.2 SysTick校准值寄存器
SysTick校准值固定为18750,它给出了1毫秒的参考时间基础
与SysTick时钟设置为18.75 MHz (HCLK/8,与HCLK设置为150 MHz)。
12.1.3中断和异常向量
STM32F405xx/07xx的矢量表见表62和表62
STM32F415xx/17xx和STM32F42xxx和STM32F43xxx设备。
12.2外部中断/事件控制器(EXTI)
外部中断/事件控制器由多达23个边缘检测器组成,用于生成
事件/中断请求。每条输入线都可以独立配置选择类型
(中断或事件)和相应的触发事件(上升或下降或两者)。每一行也可以独立遮罩。暂挂寄存器维护中断的状态行请求

12.2.1 EXTI的主要特性
EXTI控制器的主要特性如下:
•在每个中断/事件线上独立触发和掩码
•每个中断线的专用状态位
•生成多达23个软件事件/中断请求
•检测脉冲宽度低于APB2时钟周期的外部信号。请参考有关这方面的详细信息,请参阅STM32F4xx数据表的电气特性部分参数。
12.2.3唤醒事件管理
STM32F4xx能够处理外部或内部事件,以唤醒核心(WFE)。
唤醒事件可以通过以下方式生成:
在外设控制寄存器中使能中断,但不在NVIC中使能Cortex™-M4具有FPU系统控制寄存器的SEVONPEND位。当MCU从WFE、外设中断暂挂位和外设NVIC恢复
IRQ通道挂起位(在NVIC中断中清除挂起寄存器)必须是清除。
或在事件模式下配置外部或内部EXTI线路。CPU恢复时从WFE,不需要清除外设中断挂起位或NVIC IRQ通道挂起位作为挂起位对应的事件行未设置。
要使用外接线路作为唤醒事件,请参阅章节12.2.4:功能描述。
12.2.4功能介绍
为了生成中断,应该配置并启用中断线。完成了通过编程的两个触发寄存器与所需的边缘检测和使能
通过在中断掩码寄存器的相应位上写一个“1”来中断请求。
当选择的边缘出现在外部中断线上时,中断请求是生成的。与中断线对应的挂起位也被设置。这个请求是
通过在挂起寄存器中写入' 1 '来重置。
要生成事件,应该配置并启用事件行。这是由编程两个触发寄存器与所需的边缘检测和启用
通过向事件掩码寄存器中相应的位写入' 1 '来发送事件请求。当所选边缘发生在事件线上,则产生事件脉冲。挂起位
没有设置对应的事件行。
中断/事件请求也可以由软件通过在软件中写入' 1 '来生成中断/事件寄存器。
12.2.5外部中断/事件行映射
多达140个gpio (STM32F405xx/07xx和STM32F415xx/17xx), 168个gpio
(STM32F42xxx和STM32F43xxx)连接到16外部中断/事件线
以下方式:
图42 外部中断/事件GPIO映射(STM32F405xx/07xx)和STM32F415xx/17xx)

在这里插入图片描述
在这里插入图片描述

  • 初始化中断源
  • 使能中断源
  • 中断服务程序的实现(interrupt handler) 例程中是Weak声明,可以进行重写或实现

通过轮询实现按键捕获实验

如何利用已有内工程创建新工程

将led工程下的所有文件拷贝至试验2.1通过轮询实现按键的检测目录中。

修改工程名称为:key_pull_test,并打开:
在这里插入图片描述

修改工程树上的根目录名称为:key_pull_test

新建F:\IOT\PRJ\按键试验2.1通过轮询\code\drivers\key目录,复制led.c和led.h,并改名为key.c和key.h:
在这里插入图片描述
查看已定义常量的定义可跳转:
在这里插入图片描述
在这里插入图片描述
keil的drivers目录中添加led.c和key.c,后期都要使用,并在option中增加头文件的路径:

接下来修改源代码。

通过轮询实现按键捕获代码实现及分析

1 代码的流程分析

编写代码框架:

//创建及修改说明
//V1.o创建第一个按键检测实验主程序代码﹑通过轮询的方式实现按键的检测


#include "systick.h"
#include "stm32f4xx.h"
#include "led.h"

#define SYS_MAX_CLK 12
#define DELAY_1S    1000

int main(void)
{
	uint16_t key0_press = KEY_UP;
	LED0_Init();//初始化LEDO
    delay_init(SYS_MAX_CLK);//初始化系统时钟
	Key_Init();

	while(1)
	{

		if(KEY_PRESS==Detect_key(KEY0_PIN))//查询按键key0(PE4)的状态
		{
			Led_Ctrl(LED0_PIN_ROW,LED0_PIN,LED_ON); //如果按键按下,点灯
			key0_press = KEY_PRESS;

		}
		delay_ms(200); 	//在延时(200ms)后,如果按键按下标志有效,关灯

		if(key0_press == KEY_PRESS)
		{
			Led_Ctrl(LED0_PIN_ROW,LED0_PIN,LED_OFF);
		}


	}
}

在这里插入图片描述

2 代码的实现

在key.h中实现有关定义:

#ifndef __KEY_H
#define __KEY_H

#include "stm32f4xx.h"
#include "systick.h"
#include "stm32f4xx_hal_rcc.h"
#include "stm32f4xx_hal_gpio.h"

#define KEY0_PIN	 GPIO_PIN_4
#define KEY1_PIN	 GPIO_PIN_3
#define KEY2_PIN	 GPIO_PIN_2


#define KEY_PRESS  GPIO_PIN_RESET  //枚举变量,0,低电平
#define KEY_UP 		 GPIO_PIN_SET    //枚举变量,弹起时弱上拉,高电平

void 	   Key_Init(void);//初始化
uint16_t Detect_key(uint16_t key_pin);

#endif

在stm32f4xx_hal_gpio.h中定义了枚举变量:

#define KEY_PRESS  GPIO_PIN_RESET  //枚举变量,0,低电平
#define KEY_UP 		 GPIO_PIN_SET    //枚举变量,弹起时弱上拉,高电平

key.C的代码:

#include <stdlib.h>
#include "key.h"


void Key_Init(void)
{

	GPIO_InitTypeDef  gpio_info;




	gpio_info.Pin = KEY0_PIN | KEY1_PIN; //KEY0_PIN,KEY1_PIN同时初始化
	gpio_info.Mode = GPIO_MODE_INPUT;    //由定义跳转,改成输入状态
	gpio_info.Speed = GPIO_SPEED_FREQ_MEDIUM; //其他参数采用复位值即可
	gpio_info.Pull =  GPIO_PULLUP;

	__GPIOE_CLK_ENABLE(); //stm32_hal_legacy.h中有:#define __GPIOE_CLK_ENABLE __HAL_RCC_GPIOE_CLK_ENABLE

	HAL_GPIO_Init(GPIOE, &gpio_info);


}

uint16_t Detect_key(uint16_t key_pin)
{
	uint16_t ret = KEY_UP;
	if(KEY_PRESS==HAL_GPIO_ReadPin(GPIOE,key_pin))  //GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
		{
			delay_ms(10);//延时10mS去抖动
			if(KEY_PRESS==HAL_GPIO_ReadPin(GPIOE,key_pin))
				{
					ret = KEY_PRESS;
				}
	  }

		return ret;

}

test.C的代码:

//创建及修改说明
//V1.o创建第一个按键检测实验主程序代码﹑通过轮询的方式实现按键的检测
#include "systick.h"
#include "stm32f4xx.h"
#include "key.h"
#include "led.h"

#define SYS_MAX_CLK 12
#define DELAY_1S    1000

int main(void)
{
	uint16_t key0_press = KEY_UP;
	LED0_Init();//初始化LEDO
  delay_init(SYS_MAX_CLK);//初始化系统时钟
	Key_Init();

	while(1)
	{

		if(KEY_PRESS==Detect_key(KEY0_PIN))//查询按键key0(PE4)的状态
		{
			Led_Ctrl(LED0_PIN_ROW,LED0_PIN,LED_ON); //如果按键按下,点灯
			key0_press = KEY_PRESS;

		}
		delay_ms(200); 	//在延时(200ms)后,如果按键按下标志有效,关灯

		if(key0_press == KEY_PRESS)
		{
			Led_Ctrl(LED0_PIN_ROW,LED0_PIN,LED_OFF);
		}


	}
}

Tips:下载错误的解决

当默认设置内存大小不足时,会出现如下错误:
在这里插入图片描述
解决方法:调整配置内存大小:
在这里插入图片描述
实验现象:按下亮灯,松手关灯。

猜你喜欢

转载自blog.csdn.net/Medlar_CN/article/details/132082791