1.开发板原理图
从原理图中我们可以看出,上键是默认低电平,与GPIOA相连,而其余三个按键都是于GPIOE相连,默认高电平。所以在初始化按键的时候要分开。上键单独初始化,另外三个可以一起初始化。初始化时GPIOA和GPIOE都要进行初始化操作。因为两个I/O口都包含了按键。
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文件夹,将按键相关的文件都放到该文件夹下。(记得在魔术棒中配置相关的编译路径)。
通过宏定义,改善代码的可移植性和可维护性。
#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) //定义端口
//使用位操作定义
#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
为每个按键宏定义一个值用于扫描函数返回,用于判断是哪个按键按下。
2.扫描按键。
对于上键,按下的时候它会和一个电源相连,从默认的低电平变为高电平,从而产生一个上升沿信号。另外三个按键则是从高电平,产生一个低电平,产生一个下降沿信号。
所以我们的程序就应该如下编写。
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;
}
/************************************************************/
/****************下面是完整工程**************************/
/************************************************************/
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);
}
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;
}
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) //定义端口
//使用位操作定义
#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
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指示灯
}
i++;
if(i%20==0)
{
led1=!led1; //LED1状态取反
}
delay_ms(10);
}
}
用按键实现灯的有序亮\灭,则将main.c替换为下面的代码
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "smg.h"
#include "key.h"
unsigned int Number[]=
{
0x3f,//0 --- 0011 1111
0x06,//1 --- 0000 0110
0x5b,//2 --- 0101 1011
0x4f,//3 --- 0100 1111
0x66,//4 --- 0110 0110
0x6d,//5 --- 0110 1101
0x7d,//6 --- 0111 1101
0x07,//7 --- 0000 0111
0x7f,//8 --- 0111 1111
0x6f,//9 --- 0110 1111
0x77,//a --- 0111 0111
0x7c,//b --- 0111 1100
0x39,//c --- 0011 1001
0x5e,//d --- 0101 1110
0x79,//e --- 0111 1001
0x71 //f --- 0111 0001
};
int main()
{
u8 i=0,key;
u16 light = 0xffff;
SysTick_Init(72);
LED_Init();
SMG_Init();
KEY_init();
while(1)
{
key=KEY_Scan(1);
switch(key)
{
case KEY_UP:
i++;
break; //每次按下K_UP按键 多点亮一个指示灯
case KEY_DOWN:
i--;
break; //按下K_DOWN按键 熄灭一个指示灯
case KEY_LEFT:
i+=2;
break; //按下K_LEFT按键 点亮两个指示灯
case KEY_RIGHT:
i-=2;
break; //按下K_RIGHT按键 熄灭两个指示灯
}
if(i>8)
i=7;
if(i<=0)
i=0;
GPIO_Write(GPIOC,light<