main.c
/*********************************************************
** FileName: 按键检测
** Description:
按键检测的方法主要有延时和中断扫描,各有优缺点
该方法能保证CPU效率和减少外部中断的消耗
** Author: 老猫
** Date: 2019/9/30
** Others:
*********************************************************/
#include "stm32f10x.h" //STM32头文件
#include "stm32f10x_gpio.h"
#include "sys.h"
#define KEYPORT GPIOA
#define KEY1 GPIO_Pin_0
#define KEY2 GPIO_Pin_1
typedef enum {
KeyScanState_0=0x00,
KeyScanState_1=0x01,
KeyScanState_2=0x02,
}KeyScanState_Typedef;
KeyScanState_Typedef KeyScanState=KeyScanState_0;
vu32 flag=0;
void GPIO_Configuration(void);
void Systick_Configuration(void);
void keyscan(void);
int main (void){//主程序
RCC_Configuration(); //时钟设置
GPIO_Configuration();//设置GPIO端口
Systick_Configuration();
while(1)
{
keyscan();
}
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=KEY1|KEY2;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(KEYPORT,&GPIO_InitStructure);
}
void Systick_Configuration(void)
{
SysTick_Config(9000000/1000*20);//设置20ms所需要的时间间隔
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
}
void keyscan()
{
vu16 KeyPortStatus=0;
if(flag==1)
{
flag=0;
KeyPortStatus=GPIO_ReadInputData(KEYPORT)&0x0003;
switch(KeyScanState)
{
case KeyScanState_0:
{
if(KeyPortStatus!=0x0003)//按键按下
{
KeyScanState=KeyScanState_1;
}
break;
}
case KeyScanState_1:
{
if(KeyPortStatus!=0x0003)//按键按下
{
if(GPIO_ReadInputDataBit(KEYPORT,KEY1)==0)//按键1被按下
{
GPIO_WriteBit(GPIOB,GPIO_Pin_0,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_0)));
}
else if(GPIO_ReadInputDataBit(KEYPORT,KEY2)==0)//按键2被按下
{
GPIO_WriteBit(GPIOB,GPIO_Pin_1,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_1)));
}
KeyScanState=KeyScanState_2;
}
else
{
KeyScanState=KeyScanState_0;
}
break;
}
case KeyScanState_2:
{
if(KeyPortStatus==0x0003)//按键松开
{
KeyScanState=KeyScanState_0;
}
break;
}
}
}
}
在中断里面设置每20ms,赋值一次flag即可