试验介绍,按下WK_up按键蜂鸣器响,在按下蜂鸣器停,按下KEY2按键LED0反转,按下KEY1按键LED1反转,按下KEY0按键LED0 LED1同时反转。
硬件连接:
Key原理图:
由原理图可以看出KEY0 KEY1 KEY2一端是连接芯片引脚PE4 PE3 PE2按键按下是低电平
KEY_UP一端连接芯片引脚PA0,另一端连接的是3.3v按键按下会是高电平
按键扫描思路:
支持连按:
假设高电平是没有按下的,低电平是按键按下,100ms扫描一次,如果是按了1s我们会检测到10次都是低电平,如果是支持连按模式我们认为它是连续按了10次,可以写连续按下10次按键的逻辑代码。
不支持连按:
假设高电平是没有按下的,低电平是按键按下,,100ms扫描一次,我们会以上一次状态来判断,上一次状态是高的时候,这次还是高我们认为没有按下,当下一次扫描的时候是低我们认为它是按下按键的,在下一次扫描时,如果还是低我们认为他一直在按下,程序处理为只按下一次,只有当程序检测到是从高电平到低电平的时候认为是按下一次,一直保持低电平认为是按下没松开,作一次按下处理。
蜂鸣器原理图:
当我们给BEEP引脚为高时三级管导通,G端会接地,蜂鸣器会响
LED原理图:
由原理图可以看出LED0连接在芯片上的PB5引脚上,ED1连接在芯片上的PE5引脚上,又由2个LED一端连接的是VCC3.3伏,要想LED灯亮的话需要把所连的引脚拉低。
代码实现:
#define LED0(mode) GPIO_WriteBit(GPIOB,GPIO_Pin_5,mode)
#define LED1(mode) GPIO_WriteBit(GPIOE,GPIO_Pin_5,mode)
#define BEEP(mode) GPIO_WriteBit(GPIOB,GPIO_Pin_8,mode)
/*!
\brief GPIO初始化函数
\param[in] none
\param[out] none
\retval none
*/
void Gpio_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //GPIO结构体
//GPIOE、GPIOB、GPIOA是挂在APB2上
//使能GPIOA、GPIOE时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|
RCC_APB2Periph_GPIOB|
RCC_APB2Periph_GPIOE,ENABLE);
//KEY0 1 2 结构体配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入 没按下默认是高电平
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //引脚选择
//初始化GPIOE Pin2 3 4
GPIO_Init(GPIOB,&GPIO_InitStructure);
//KEY_UP结构体配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //下拉输入 没按下默认是低电平
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //引脚选择
//初始化GPIOE Pin0
GPIO_Init(GPIOA, &GPIO_InitStructure);
//蜂鸣器结构体配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //pin8
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度为50MHz
//初始化GPIOB Pin8
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据参数初始化GPIOB.8
GPIO_ResetBits(GPIOB,GPIO_Pin_8); //输出0,关闭蜂鸣器输出
//LED0结构体配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
//初始化GPIOB Pin5
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高
//LED1结构体配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
//初始化GPIOE Pin5
GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz
GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高
}
/*!
\brief 按键处理函数
\param[in] mode: 0不支持连续按,1支持连续按
\param[out] none
\retval 返回按键按键值 1 KEY0按下 2 KEY1按下 KEY2_PRES 3 KEY2按下 4 KEY_UP按下
*/
uint8_t Key_Scan(uint8_t 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;// 无按键按下
}
int main(void)
{
uint8_t key=0;
delay_init(); //延时函数初始化
Gpio_Init(); //GPIO初始化函数
while(1){
key=Key_Scan(0); //得到键值不支持连续按
if(key){
switch(key){
case WKUP_PRES: //控制蜂鸣器
BEEP(!GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_8));
break;
case KEY2_PRES: //控制LED0翻转
LED0(!GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5));
break;
case KEY1_PRES: //控制LED1翻转
LED1(!GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_5));
break;
case KEY0_PRES: //同时控制LED0,LED1翻转
LED0(!GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5));
LED1(!GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_5));
break;
}
}
}
}