STM32F4学习笔记—GPIO_按键扫描(基于寄存器)
一、硬件原理
1.1原理图分析
通过上面的原理图分析可知,KEY0、1、2连接方式为共阴极,也就是说当GPIO引脚检测到低电平时,说明按键按下;KEY_UP连接为共阳极,同理,当检测到GPIO引脚为高电平时,说明按键按下。
1.2思路分析
1.2.1使能GPIOE和GPIOA的时钟
位 5 GPIOFEN: IO 端口 F 时钟使能 (IO port F clock enable)
由软件置 1 和清零。
0:禁止 IO 端口 F 时钟
1:使能 IO 端口 F 时钟
在手册中可以看到,往这个寄存器写1就是使能,代码就这么写:
// 1.使能GPIO时钟
RCC->AHB1ENR |= 1 << 4; // 使能GPIOE时钟
RCC->AHB1ENR |= 1 << 0; // 使能GPIOA时钟
2.2.2初始化GPIOE和GPIOA
在这个环节里主要注意这几个参数就可以了
1.端口模式寄存器
2.端口上拉/下拉寄存器
代码如下:
// 2.2端口上拉/下拉(00:不拉 01:上拉 10:下拉 11:保留)
GPIOE->PUPDR |= 1 << 8;
GPIOE->PUPDR |= 1 << 6;
GPIOE->PUPDR |= 1 << 4;
GPIOA->PUPDR |= 1 << 1; // 设置为上拉模式(2y+1:2y)->PA0
3.端口输出速度寄存器
代码如下:
// 2.3速度设置
GPIOE->OSPEEDR |= 1 << 9;
GPIOE->OSPEEDR |= 1 << 7;
GPIOE->OSPEEDR |= 1 << 5;
GPIOA->OSPEEDR |= 1 << 1;
二、软件设计
2.1key.c
#include "key.h"
static void gpio_init(void)
{
// 1.使能GPIO时钟
RCC->AHB1ENR |= 1 << 4; // 使能GPIOE时钟
RCC->AHB1ENR |= 1 << 0; // 使能GPIOA时钟
// 2.初始化GPIO
// 2.1端口模式(00:输入 01:通用输出 10:复用功能 11:模拟模式)
GPIOE->MODER &= ~(3 << 8); // 设置为输入模式(2y+1:2y)->PE4
GPIOE->MODER &= ~(3 << 6); // 设置为输入模式(2y+1:2y)->PE3
GPIOE->MODER &= ~(3 << 4); // 设置为输入模式(2y+1:2y)->PE2
GPIOA->MODER &= ~(3 << 0); // 设置为输入模式(2y+1:2y)->PA0
// 2.2端口上拉/下拉(00:不拉 01:上拉 10:下拉 11:保留)
GPIOE->PUPDR |= 1 << 8;
GPIOE->PUPDR |= 1 << 6;
GPIOE->PUPDR |= 1 << 4;
GPIOA->PUPDR |= 1 << 1; // 设置为上拉模式(2y+1:2y)->PA0
// 2.3速度设置
GPIOE->OSPEEDR |= 1 << 9;
GPIOE->OSPEEDR |= 1 << 7;
GPIOE->OSPEEDR |= 1 << 5;
GPIOA->OSPEEDR |= 1 << 1;
}
uint8_t get_keynum(void)
{
uint8_t key_num = 0;
//1.判断PE2
if (!(GPIOE->IDR &= 1 << 2))
{
HAL_Delay(20);
if (!(GPIOE->IDR &= 1 << 2))
key_num = 2;
}
//2.判断PE3
else if (!(GPIOE->IDR &= 1 << 3)){
HAL_Delay(20);
if (!(GPIOE->IDR &= 1 << 3))
key_num = 3;
}
//3.判断PE4
else if (!(GPIOE->IDR &= 1 << 4)){
HAL_Delay(20);
if (!(GPIOE->IDR &= 1 << 4))
key_num = 4;
}
//4.判断PA0
else if(GPIOA->IDR &= 1<<0)
{
HAL_Delay(20);
if(GPIOA->IDR &= 1<<0)
key_num = 1;
}
else
key_num = 0;
return key_num;
}
void key_test()
{
// 1.初始化GPIO
gpio_init();
while(1)
{
// 2.读取按键
if(get_keynum() == 2)
//ds0亮
GPIOF->ODR &= ~(1<<9);
if(get_keynum() == 3)
//ds0灭
GPIOF->ODR |= 1<<9;
}
}
2.2key.h
#ifndef __KEY_H
#define __KEY_H
#include "main.h"
#include "led.h"
void key_test(void);
#endif
2.3main.c
#include "main.h"
#include "key.h"
void SystemClock_Config(void);
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
HAL_Init();
SystemClock_Config();
led_test();
key_test();
while (1)
{
}
}
三、下载验证
代码没问题的话,现象如下: