原理:

 

微信图片_20210105120112

 

微信图片_20210105120115

 

微信图片_20210105120117

  由图可得:  
  • KEY0的IO口为PC5,按下后低电平,所以配置为上拉输入
  • KEY1的IO口为PA15,按下后低电平,所以配置为上拉输入
  • WK_UP的IO口为PA0,按下后高电平,所以配置为下拉输入
 

原因:

 
由于按键在没有外界输入的情况下输入端是悬空的,它的电平是未知的
所以上拉电阻就是为了保证无信号输入时输入端的电平为高电平,
同样还有下拉电阻它是为了保证无信号输入时输入端的电平为低电平。
  GPIO口配置完成后,剩下读取函数:  
unsigned char KeyScan()
{
		static unsigned char key_up = 1;   //按键按下标记按钮
		
		if((key_up == 1)&&(KEY0 == 0||KEY1 == 0||KEY_UP == 1))
		{
				delay_ms(10);//消抖延时
				key_up = 0;//按下确实按下,标记为0
				if(KEY0 == 0) return KEY0_PRESS;
				else if(KEY1 == 0) return KEY1_PRESS;
				else if(KEY_UP == 1) return KEY_UP_PRESS;
		}
		else if(KEY0 == 1&&KEY1 == 1&&KEY_UP == 0) //按键抬起
		{
				key_up = 1;//按键抬起标记为1
		}		
		return 0;
}
 

注意点:

  1.使能时钟函数是APB2!!!!  
 void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
  2.多多使用宏定义,很方便,很简洁,例如:  
 #define KEY_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)   //直接读取KEY_UP
 #define LED1 PAout(8)    //直接操作LED1
 

主要代码:

  main.c  
******************************************************************************
* 文件名:按键实验
* 描  述: 按下KEY0,DS0变化,按下KEY1,DS1变化,按下WK_UP两个灯都变化
* 作  者:思索与猫
* 日  期: 19/4/4
* 备  注: 
*         
******************************************************************************
#include "stm32f10x.h"                  // Device header
#include<sys.h>
#include<led.h>
#include<key.h>
#include<delay.h>

int main()
{
		unsigned char key_value = 0;
		delay_init();
		LED_init();
		KEY_Init();
		while(1)
		{
				key_value = KeyScan();
				switch(key_value)
				{
					case KEY0_PRESS:LED0 = !LED0;break;       
					case KEY1_PRESS:LED1 = !LED1;break;
					case KEY_UP_PRESS:LED0 = !LED0;LED1 = !LED1;break;
					default:delay_ms(10);
				}
		}				
}
  key.h  
#ifndef __KEY_H
#define __KEY_H
#include<sys.h>

#define KEY0 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)
#define KEY1 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)
#define KEY_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)

#define KEY0_PRESS 1
#define KEY1_PRESS 2
#define KEY_UP_PRESS 3


void KEY_Init(void);
unsigned char KeyScan(void);

#endif 
  key.c  
#include "stm32f10x.h"                  // Device header
#include<key.h>
#include<delay.h>

void KEY_Init()
{
		GPIO_InitTypeDef GPIO_InitStructure;
		
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);
	
		//KEY_UP
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;   //D就是DOWN,下拉输入
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
		GPIO_Init(GPIOA,&GPIO_InitStructure);
	
		//KEY_1
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   //U就是UP,上拉输入
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
		GPIO_Init(GPIOC,&GPIO_InitStructure);
	
		//KEY_0
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   //U就是UP,上拉输入
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
		GPIO_Init(GPIOA,&GPIO_InitStructure);
}

unsigned char KeyScan()
{
		static unsigned char key_up = 1;
		
		if((key_up == 1)&&(KEY0 == 0||KEY1 == 0||KEY_UP == 1))
		{
				delay_ms(10);
				key_up = 0;
				if(KEY0 == 0) return KEY0_PRESS;
				else if(KEY1 == 0) return KEY1_PRESS;
				else if(KEY_UP == 1) return KEY_UP_PRESS;
		}
		else if(KEY0 == 1&&KEY1 == 1&&KEY_UP == 0)
		{
				key_up = 1;
		}
		
		return 0;
}
  led.h  
#ifndef __LED_H
#define __LED_H
#include<sys.h>

#define LED1 PAout(8)
#define LED0 PDout(2)

void LED_init(void);

#endif
  led.c  
#include<led.h>
#include "stm32f10x.h"                  // Device header

void LED_init()
{
		GPIO_InitTypeDef GPIO_InitStructure;
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD,ENABLE);
		
		//ST_LINK使用SW,不使用JTAG,可以省出IO口
		//GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
		GPIO_Init(GPIOA,&GPIO_InitStructure);
		GPIO_SetBits(GPIOA,GPIO_Pin_8);
		 
			
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
		GPIO_Init(GPIOD,&GPIO_InitStructure);
		GPIO_SetBits(GPIOD,GPIO_Pin_2);
}