原创 STM32 学习13 库函数实现按键检测
原创 STM32 学习13 库函数实现按键监测
- 一、说明
- 二、实现过程
- 1. 按键接口定义
- system.h
- system.c
- led.h
- led.c
- key.h
- key.c
- 主函数 main.c
- 三、执行效果
一、说明
本文学习内容来自普中开发板官方学习文档。
STM32实现按键检测,可以使用扫描或中断的方式。本文采用扫描的方式来实现。
本文使用的按键电路原理图如下:

- 按键KEY_UP接在GPIOA端口上,其他按键连接在GPIOE上;LED接在GPIOC上。
- 其中KEY_UP通过电阻连接到3.3v,连接到PA0口,其具有一个唤醒的功能,连接高电平有效。要判断是否按下,看其是不是高电平。初始化时设置为下拉输入。
- 而其他按键,判断按下是看其是不是低电平,初始化时设置为上拉输入。
要实现的功能:
- 使能按键端口时钟
- 初始化GPIO口 , 按键是初始化为输入模式。
- 按键检测
- 软件消抖,延迟50ms的软件消抖。
- 相应LED灯亮。
实现要点:
- 通过位操作定义按键、LED灯
- 通过宏定义按键的引脚
- 程序的要点是要扫描按键,扫描
二、实现过程
1. 按键接口定义
system.h
#ifndef _system_H
#define _system_H#include "stm32f10x.h"//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<>第五章(87页~92页).
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C
#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808
#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08
#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08 //IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入 #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入 #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入 #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入 #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入#endif
system.c
#include "system.h"
为了对按键有反应,使用LED来响应。
led.h
#ifndef _led_H
#define _led_H#include "system.h"/* LED时钟端口、引脚定义 */
#define LED_PORT GPIOC
#define LED_PIN (GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7)
#define LED_PORT_RCC RCC_APB2Periph_GPIOC#define led1 PCout(0)
#define led2 PCout(1)
#define led3 PCout(2)void LED_Init(void);#endif
led.c
#include "led.h"/*******************************************************************************
* 函 数 名 : LED_Init
* 函数功能 : LED初始化函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void LED_Init()
{GPIO_InitTypeDef GPIO_InitStructure;//定义结构体变量RCC_APB2PeriphClockCmd(LED_PORT_RCC,ENABLE);GPIO_InitStructure.GPIO_Pin=LED_PIN; //选择你要设置的IO口GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //设置推挽输出模式GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //设置传输速率GPIO_Init(LED_PORT,&GPIO_InitStructure); /* 初始化GPIO */GPIO_SetBits(LED_PORT,LED_PIN); //将LED端口拉高,熄灭所有LED
}
key.h
#ifndef _key_H
#define _key_H#include "system.h"// 下面宏定义主要用在引脚初始化
#define KEY_LEFT_Pin GPIO_Pin_2 //定义K_LEFT管脚
#define KEY_DOWN_Pin GPIO_Pin_3 //定义K_DOWN管脚
#define KEY_RIGHT_Pin GPIO_Pin_4 //定义K_RIGHT管脚
#define KEY_UP_Pin GPIO_Pin_0 //定义KEY_UP管脚#define KEY_Port (GPIOE) //定义其他按键端口
#define KEY_UP_Port (GPIOA) //定义KEY_UP按键端口// 下面使用位操作和库函数 选择其中一种即可。作用是用来读取按键值
//使用位操作定义
#define K_UP PAin(0)
#define K_DOWN PEin(3)
#define K_LEFT PEin(2)
#define K_RIGHT PEin(4)//使用读取管脚状态库函数定义
//#define K_UP GPIO_ReadInputDataBit(KEY_UP_Port,KEY_UP_Pin)
//#define K_DOWN GPIO_ReadInputDataBit(KEY_Port,KEY_DOWN_Pin)
//#define K_LEFT GPIO_ReadInputDataBit(KEY_Port,KEY_LEFT_Pin)
//#define K_RIGHT GPIO_ReadInputDataBit(KEY_Port,KEY_RIGHT_Pin)//定义各个按键值
#define KEY_UP 1
#define KEY_DOWN 2
#define KEY_LEFT 3
#define KEY_RIGHT 4 void KEY_Init(void);
u8 KEY_Scan(u8 mode);
#endif
key.c
#include "key.h"
#include "SysTick.h"/*******************************************************************************
* 函 数 名 : KEY_Init
* 函数功能 : 按键初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void KEY_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);GPIO_InitStructure.GPIO_Pin=KEY_UP_Pin; //选择你要设置的IO口GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;//下拉输入 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //设置传输速率GPIO_Init(KEY_UP_Port,&GPIO_InitStructure); /* 初始化GPIO */GPIO_InitStructure.GPIO_Pin=KEY_DOWN_Pin|KEY_LEFT_Pin|KEY_RIGHT_Pin;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //上拉输入GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(KEY_Port,&GPIO_InitStructure);
}/*******************************************************************************
* 函 数 名 : KEY_Scan
* 函数功能 : 按键扫描检测
* 输 入 : mode=0:单次按下按键mode=1:连续按下按键
* 输 出 : 0:未有按键按下KEY_UP:K_UP键按下KEY_DOWN:K_DOWN键按下KEY_LEFT:K_LEFT键按下KEY_RIGHT:K_RIGHT键按下
*******************************************************************************/
u8 KEY_Scan(u8 mode)
{static u8 key=1;if(key==1&&(K_UP==1||K_DOWN==0||K_LEFT==0||K_RIGHT==0)) //任意一个按键按下{delay_ms(10); //消抖key=0;// 下面判断到底哪个按键被按下if(K_UP==1){return KEY_UP; }else if(K_DOWN==0){return KEY_DOWN; }else if(K_LEFT==0){return KEY_LEFT; }else{return KEY_RIGHT;}}else if(K_UP==0&&K_DOWN==1&&K_LEFT==1&&K_RIGHT==1) //无按键按下{key=1;}if(mode==1) //连续按键按下{key=1;}return 0;
}
主函数 main.c
main.c
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"int main()
{u8 key,i;SysTick_Init(72);LED_Init();KEY_Init();while(1){key=KEY_Scan(0); //扫描按键switch(key){case KEY_UP: led2=0;break; //按下K_UP按键 点亮D2指示灯case KEY_DOWN: led2=1;break; //按下K_DOWN按键 熄灭D2指示灯case KEY_LEFT: led3=1;break; //按下K_LEFT按键 点亮D3指示灯case KEY_RIGHT: led3=0;break; //按下K_RIGHT按键 熄灭D3指示灯}// 200ms闪烁一次led1i++;if(i%20==0){led1=!led1; //LED1状态取反}delay_ms(10); }
}
三、执行效果
按下按键,看到LED显示有相应变化。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
