目录:
1:概述
2:代码功能
3:代码分享
概述:
代码利用轮询方式对按键状态进行扫描,扫描得出按键的键值(短按、长按、双击),然后根据键值进行相应的事件处理;
平台:奋斗STM32F103 V5开发板 开发环境:KEIL MDK5
代码功能:
短按K1按键,LED1灯闪烁,闪烁间隔250ms;
长按K1按键1.5S以上,三个LED同时闪烁,闪烁间隔250ms;
双击K1按键,实现三个LED的流水灯;
代码分享:
main.c函数:
/*
*FUNC:轮询按键键值,实现按键短按(单击)、长按、双击功能
*MCU:stm32f103
*DATE:2016/10/07
*/
#include "Key_Board.h"
#include "Rcc_Driver.h"
#include "Led_Driver.h"
#include "Sysclk_Driver.h"
/*led闪烁标志 为1--led亮 为0--led灭*/
bool led_flag = 0;
bool led1_flag = 0;
/*任务:led闪烁时间间隔*/
volatile unsigned int led_flash_timing = 0;
/*任务:按键轮询时间间隔*/
volatile unsigned int key_scan_timing = 0;
unsigned char i = 0;
int main()
{
RCC_PeriphClock_Config(); //模块时钟初始化
Key_Init(); //按键初始化
Led_Init(); //按键初始化
SysTick_Init(INT_1MS,SysTick_CLKSource_HCLK_Div8); //内核滴答定时器配置
while(1)
{
/*任务1:10ms进行一次按键键值扫描和按键事件处理*/
if(key_scan_timing > 10)
{
key_scan_timing = 0;
Key_Scan(); //扫描按键是否按下,上报按键键值
Key_Func(); //根据按键键值,对应事件的标志位置1
}
/*任务2:完成led闪烁*/
if(led_flash_timing > 250)
{
led_flash_timing = 0;
if(led_water_flag == 1) //led流水灯:LED1 LED2 LED3
{
if(++i > 3)
i = 1;
switch(i)
{
case 1:
LED1_ON;
LED3_OFF;
break;
case 2:
LED2_ON;
LED1_OFF;
break;
case 3:
LED3_ON;
LED2_OFF;
break;
}
}
else
if(led_all_flash_flag == 1) //LED1 LED2 LED3同时闪烁
{
led_flag = !led_flag;
if(led_flag==1)
{
LED1_ON;
LED2_ON;
LED3_ON;
}
else
{
LED1_OFF;
LED2_OFF;
LED3_OFF;
}
}
else
if(led1_flash_flag==1) //LED1闪烁
{
led1_flag = !led1_flag;
if(led1_flag==1)
{
LED1_ON;
}
else
{
LED1_OFF;
}
}
else //当没有按键事件需要处理时,熄灭三个led灯
{
LED1_OFF;
LED2_OFF;
LED3_OFF;
}
}
}
}
按键扫面函数(Key_Scan(void))和按键事件处理函数(Key_Func(void)):
Key_Board.c:
#include "Key_Board.h"
/*记录按键按下时间 时间小于1.5S,按键为短按;时间大于1.5S,按键为长按*/
volatile unsigned int key1_timing = 0;
/*记录两次短按之间的时间间隔*/
volatile unsigned int key1_doublepress_timing = 0;
/*定义按键键值结构体*/
Key_Value k1_value;
/*K1按键短按标志位*/
bool k1_shortpress_happen = 0;
/*K1按键长按标志位*/
bool k1_longpress_happen = 0;
/*K1按键双击标志位*/
bool k1_doublepress_happen = 0;
/*led1闪烁时间标志位,主函数检测到此标志位为1时,led1开始闪烁,否则,结束闪烁*/
bool led1_flash_flag = 0;
/*3个led全部闪烁标志位,主函数检测到此标志为1时,三个led灯开始同时闪烁,否则结束闪烁*/
bool led_all_flash_flag = 0;
/*流水灯事件标志位*/
bool led_water_flag = 0;
/*按键初始化
*设置GPIOC2/GPIOC3/GPIOC5为上拉输入,按键按下为低电平,按键抬起为高电平
*/
void Key_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOC, &GPIO_InitStruct);
}
/*按键键值扫描函数*/
void Key_Scan(void)
{
/*程序不支持两个按键同时按下*/
// if((K1==0&&K2==0) || (K1==0&&K3==0) || (K2==0&&K3==0))
// return ;
if(K1==0) //当K1按键按下
{
if(k1_shortpress_happen==0)
{
k1_shortpress_happen = 1; //开始一次按键键值扫描
key1_timing = 0; //按键按下计时变量清0,开始计时,此值每1ms加1,sysclk中断函数中实现自加
}
if(k1_shortpress_happen==1)
{
if(key1_timing > 1500) //按键按下时间超过1.5S,长按事件发生,置k1_value.long_press为1
{
k1_value.long_press = 1;
k1_shortpress_happen = 0; //按键短按标志位置0
}
}
}
if(K1==1) //当K1按键抬起
{
if(k1_shortpress_happen==1) //按键抬起后,k1_shortpress_happen等于1,说明按键为短按,不是长按
{
k1_shortpress_happen = 0;
if(k1_doublepress_happen==0)
{
k1_doublepress_happen = 1; //按键双击标志位置1,等待确认按键是否为双击
key1_doublepress_timing = 0; //开始计时,同样1ms自增加1
}
else
{
if(key1_doublepress_timing < 500) //第一次短按发生后,在500ms时间内,发生第二次短按,完成一次双击,跟新按键键值
{
k1_doublepress_happen = 0;
k1_value.double_press = 1;
}
}
}
else
if(k1_doublepress_happen == 1) //第一次短按后,等待500ms,如未再发生短按,跟新按键短按键值
{
if(key1_doublepress_timing > 500)
{
k1_doublepress_happen = 0;
k1_value.short_press = 1;
}
}
else
if(k1_longpress_happen==1)
k1_longpress_happen = 0;
}
}
/*按键事件处理函数 根据键值 进行相应的事件处理*/
void Key_Func(void)
{
if(k1_value.short_press == 1)
{
k1_value.short_press = 0;
//led1_flash_flag = (led1_flash_flag==TRUE? FALSE:TRUE);
led1_flash_flag = !led1_flash_flag;
}
if(k1_value.long_press == 1)
{
k1_value.long_press = 0;
//led_all_flash_flag = (led_all_flash_flag==TRUE?FALSE:TRUE);
led_all_flash_flag = !led_all_flash_flag;
}
if(k1_value.double_press == 1)
{
k1_value.double_press = 0;
//led_water_flag = (led_water_flag==TRUE?FALSE:TRUE);
led_water_flag = !led_water_flag;
}
}
上一篇:stm32f103按键轮询实现方法
下一篇:STM32F429(HAL库)_USART串口发送&接收(使用STM32CubeMX)
推荐阅读最新更新时间:2024-03-16 16:22