按键检测的硬件电路连接如下:
KEY0,KEY1,KEY2 ,
KEY_UP 都要设置成输入模式。
KEY0,KEY1,KEY2按下,单片机输入检测到0( KEY0=0;KEY1=0;KEY2=0; ),则按键被按下,所以没有按下时,IO口要设置成上拉模式。
KEY_UP按下,单片机检测到高电平1( KEY_UP =1;),则按键被按下,所以没有按下时,IO口要设置成下拉模式。
读取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
#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) //输入
然后要把IO口对应的时钟初始化:
上面用到了PA0和PE2 PE3 PE4总线口,调用
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//使能GPIOA和GPIOE
初始化IO模式:上拉/下拉输入。调用函数:
//GPIO_Init();
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //KEY2-KEY4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉模式
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成下拉模式
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0
按键扫描函数如下:
输入参数-- u8 mode是否支持连续按
返回值--返回被按下的按键
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1;//按键松开标志位
if(mode)key_up=1; //支持连按
if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
{
delay_ms(10);//消抖
key_up=0;
if(KEY0==0)return KEY0_PRES;
else if(KEY1==0)return KEY1_PRES;
else if(KEY2==0)return KEY2_PRES;
else if(WK_UP==1)return WKUP_PRES;
}else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;
return 0;// 无按键按下
}
在主函数调用如下:
死循坏
while(1)
{
key=KEY_Scan(0); //
if(key)
{
switch(key)
{
case WKUP_PRES: //
BEEP=!BEEP;
break;
case KEY2_PRES: //
LED0=!LED0;
break;
case KEY1_PRES: //
LED1=!LED1;
break;
case KEY0_PRES: //
LED0=!LED0;
LED1=!LED1;
break;
}
}else delay_ms(10);
}
网友评论