最近我用标准库和stm32写了一个关于,多个按键的长按与短按,伴随蜂鸣器响一下的小实验,和大家分享一下!
按键的思路框架:
这个框架是我从网上找到的,便于大家理解。
void Key_Scan(void)
{static uint8_t cnt = 0;//按键的计时/消抖if(K1==0) //按键按下{cnt++;//开始计数}if(K1==1)//按键释放/没有按下按键/按键消抖{if(cnt>1000) //表示长按{//长按执行内容}else if(cnt>100) //表示短按{//短按执行内容}cnt = 0; //这块我理解为没有按/按键消抖}
}
system.c
我的按键有触摸按键,原理图上给触摸按键提供了VCC,所以用这个函数GPIO_SetBits(GPIOB,GPIO_Pin_14);把提供VCC的引脚设置一下,使按键有电,按键就能正常工作啦!
void RCC_Config(void) //时钟配置
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
}void GPIO_Config(void)//GPIO口配置
{GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_13 | GPIO_Pin_12 //按键GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //蜂鸣器GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOB,GPIO_Pin_14);
} void NVIC_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}void InterruptConfig(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Period = 7199;TIM_TimeBaseStructure.TIM_Prescaler = 99;TIM_TimeBaseStructure.TIM_ClockDivision = 0;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);TIM_Cmd(TIM4, ENABLE);
}
stm32_it.c
void TIM4_IRQHandler(void)//10ms
{ if(TIM_GetITStatus(TIM4, TIM_FLAG_Update) == SET){TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update);RunData.RunCnt++;}
}
key.c
#include "key.h"
#include "delay.h"KEYVALUE Key = {0};//结构体void KEY_Scan(void)
{/********right********/if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==RESET) //记录按键低电平时间{Key.rightcnt++; //计数变量}if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==SET) //按键释放/没有按下按键/按键按下的抖动{if(Key.rightCnt>1000)//说明是长按{//长按执行内容GPIO_WriteBit(GPIOA,GPIO_Pin_6,Bit_SET);delay_ms(50);GPIO_WriteBit(GPIOA,GPIO_Pin_6,Bit_RESET);Key.rightLong = 1; //标志位}else if(Key.rightCnt>100) //短按{//执行短按内容GPIO_WriteBit(GPIOA,GPIO_Pin_6,Bit_SET);delay_ms(50);GPIO_WriteBit(GPIOA,GPIO_Pin_6,Bit_RESET);Key.rightshort = 2;}Key.rightCnt=0;//清除计数变量Key.right = 0;//标志位//关闭按键的状态}/********left********/if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==RESET) //记录按键低电平时间{Key.leftCnt++; //计数变量}if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==SET) //按键释放/没有按下按键/按键按下的抖动{if(Key.leftCnt>1000)//说明是长按{//长按执行内容GPIO_WriteBit(GPIOA,GPIO_Pin_6,Bit_SET);delay_ms(50);GPIO_WriteBit(GPIOA,GPIO_Pin_6,Bit_RESET);Key.leftLong = 1;}else if(Key.leftCnt>100) //短按{//执行短按内容GPIO_WriteBit(GPIOA,GPIO_Pin_6,Bit_SET);delay_ms(50);GPIO_WriteBit(GPIOA,GPIO_Pin_6,Bit_RESET);Key.leftshort = 2;}Key.leftCnt=0;//清除计数变量Key.left = 0;//标志位}/********ok********/if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==RESET) //记录按键低电平时间{Key.okCnt++; //计数变量}if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==SET) //按键释放/没有按下按键/按键按下的抖动{if(Key.okCnt>1000)//说明是长按{//长按执行内容GPIO_WriteBit(GPIOA,GPIO_Pin_6,Bit_SET);delay_ms(50);GPIO_WriteBit(GPIOA,GPIO_Pin_6,Bit_RESET);Key.okLong = 1;}else if(Key.okCnt>100) //短按{//执行短按内容GPIO_WriteBit(GPIOA,GPIO_Pin_6,Bit_SET);delay_ms(50);GPIO_WriteBit(GPIOA,GPIO_Pin_6,Bit_RESET);Key.okshort = 2;}Key.okCnt=0;//清除计数变量Key.ok = 0;//标志位}
标志位:我都放在key.h的结构体里了
key.h
#ifndef _KEY_H_
#define _KEY_H_#include "system.h"typedef struct
{uint8_t right; //不按标志位uint16_t rightCnt;//计数uint8_t rightLong;//长按标志位uint8_t rightshort;//短按标志位uint8_t left;uint16_t leftCnt;uint8_t leftLong;uint8_t leftshort;uint8_t ok;uint16_t okCnt;uint8_t okLong;uint8_t okshort;
}KEYVALUE; //多个按键就继续写里面extern KEYVALUE Key;void KEY_Scan(void);
#endif
main.c
#include "system.h"
#include "key.h"int main(void)
{delay_init();RCC_Config();NVIC_Config();InterruptConfig();GPIO_Config();while (1)
{if(RunData.RunCnt>2)//20ms扫描一次按键{KEY_Scan(); RunData.RunCnt = 0;}
}
以上就是实现让按键长按,短按,蜂鸣器响一下的实验代码,欢迎指导讨论哦!