一、说明
本文学习内容来自普中开发板官方学习文档。 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"
#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))
#define GPIOA_ODR_Addr (GPIOA_BASE+12)
#define GPIOB_ODR_Addr (GPIOB_BASE+12)
#define GPIOC_ODR_Addr (GPIOC_BASE+12)
#define GPIOD_ODR_Addr (GPIOD_BASE+12)
#define GPIOE_ODR_Addr (GPIOE_BASE+12)
#define GPIOF_ODR_Addr (GPIOF_BASE+12)
#define GPIOG_ODR_Addr (GPIOG_BASE+12)
#define GPIOA_IDR_Addr (GPIOA_BASE+8)
#define GPIOB_IDR_Addr (GPIOB_BASE+8)
#define GPIOC_IDR_Addr (GPIOC_BASE+8)
#define GPIOD_IDR_Addr (GPIOD_BASE+8)
#define GPIOE_IDR_Addr (GPIOE_BASE+8)
#define GPIOF_IDR_Addr (GPIOF_BASE+8)
#define GPIOG_IDR_Addr (GPIOG_BASE+8)
#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"
#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"
void LED_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(LED_PORT_RCC,ENABLE);
GPIO_InitStructure.GPIO_Pin=LED_PIN;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(LED_PORT,&GPIO_InitStructure);
GPIO_SetBits(LED_PORT,LED_PIN);
}
key.h
#ifndef _key_H
#define _key_H
#include "system.h"
#define KEY_LEFT_Pin GPIO_Pin_2
#define KEY_DOWN_Pin GPIO_Pin_3
#define KEY_RIGHT_Pin GPIO_Pin_4
#define KEY_UP_Pin GPIO_Pin_0
#define KEY_Port (GPIOE)
#define KEY_UP_Port (GPIOA)
#define K_UP PAin(0)
#define K_DOWN PEin(3)
#define K_LEFT PEin(2)
#define K_RIGHT PEin(4)
#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"
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Pin=KEY_UP_Pin;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(KEY_UP_Port,&GPIO_InitStructure);
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);
}
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;
case KEY_DOWN: led2=1;break;
case KEY_LEFT: led3=1;break;
case KEY_RIGHT: led3=0;break;
}
i++;
if(i%20==0)
{
led1=!led1;
}
delay_ms(10);
}
}
三、执行效果
按下按键,看到LED显示有相应变化。
|