1.stm32定时器轮询按键

发布时间 2023-03-26 14:57:30作者: 在下彦祖
1.C文件

#include "user_key.h" #include "stm32f10x.h" #include <stdio.h> /*********************************如增减按键或者修改引脚,注意看下6项需要改动的地方****************************************/ /**************************************1按键的硬件定义,改动硬件需修改*********************************/ #define KEY1 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3) //按键的状态函数,增加按键,可以去掉注释符 #define KEY2 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4) /***************************************************************************************************/ typedef struct { volatile unsigned char key_lock_flag; //自锁标志,用于保证按键轮询是第一次进入计时,保证一次的准确计时 volatile unsigned int key_scan_count; //按键在定时器轮询计数变量,自加 volatile unsigned char key_short_press_flag; //按键短按标志位 volatile unsigned char key_long_press_flag; //按键长按标志位,目前这变量没用到,一般是多次单击会用到这个变量 volatile unsigned char key_num; //按键的键值 }KEY_InitTypeDef; /**************************************2按键的硬件定义,改动硬件需修改*********************************/ KEY_InitTypeDef key_array[2] = //按键结构体数组,如增加按键,可以去掉注释符 { {0,0,0,0,0,}, {0,0,0,0,0,} }; /***************************************************************************************************/ /*****************************3按键的硬件定义,改动硬件需修改***************************/ void user_key_init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOE, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOE, &GPIO_InitStruct); } /*******************************************************************************************/ /*******************************4按键的硬件定义,改动硬件需修改*********************************/ void user_key_scan(void) { /***此函数放置在定时器的更新函数里***/ /***第一个参数 按键按下类型:1:短按 11:长按 111:短按和长按***/ /***第二个参数 按键电压:(if{1} else{0}是按键上拉,低电平触发按键有效)(if{0} else{1}是按键下拉,高电平触发按键有效)***/ /***第三个参数 按键的编号: key number 依次编号下去即可***/ if(KEY1){user_key_set_scan(111,1,1);}else{user_key_set_scan(111,0,1);} if(KEY2){user_key_set_scan(111,1,2);}else{user_key_set_scan(111,0,2);} // if(KEY3){user_key_set_scan(1,1,3);}else{user_key_set_scan(1,0,3);} // if(KEY4){user_key_set_scan(1,1,4);}else{user_key_set_scan(1,0,4);} // if(KEY5){user_key_set_scan(1,1,5);}else{user_key_set_scan(1,0,5);} } /*******************************************************************************************/ /*****************************5按键的硬件定义,改动硬件需修改***************************/ unsigned char key_get_num(unsigned char key_id) { unsigned char key_local_param; switch(key_id) { case 1: key_local_param = key_array[0].key_num;break; case 2: key_local_param = key_array[1].key_num;break; // case 3: key_local_param = key_array[2].key_num;break; // case 4: key_local_param = key_array[3].key_num;break; // case 5: key_local_param = key_array[4].key_num;break; } return key_local_param; } /**********************************************************************************/ /*****************************6按键的硬件定义,改动硬件需修改***************************/ void key_clear_num(unsigned char key_id) { switch(key_id) { case 1: key_array[0].key_num = 0;break; case 2: key_array[1].key_num = 0;break; // case 3: key_array[2].key_num = 0;break; // case 4: key_array[3].key_num = 0;break; // case 5: key_array[4].key_num = 0;break; } } /**********************************************************************************/ void user_key_set_scan(unsigned char key_press_type,unsigned char key_IOvaule, unsigned char key_id) { /***此函数不需要动,但可以修改key_scan_count判定值来调整按键灵敏度***/ if(key_press_type == 1) //短按判断 { switch(key_IOvaule) { case 1:key_array[key_id - 1].key_scan_count = 0; //按键没按下,计数清零 key_array[key_id - 1].key_lock_flag = 0; //自锁标志清零 break; case 0:if(key_array[key_id - 1].key_lock_flag == 0) //按键按下,并且标志位是0,判定是第一次进入计时 { key_array[key_id - 1].key_scan_count++; //计时 if(key_array[key_id - 1].key_scan_count > 100) //短按一次持续的时间,可以调整数字调灵敏度 { key_array[key_id - 1].key_scan_count = 0; //计时清零 key_array[key_id - 1].key_lock_flag = 1; //自锁置1,完成了一次短按判断,防止重复进入 key_array[key_id - 1].key_num = 1; //短按赋键值 } } default:break; } } if(key_press_type == 11) //长按判断 { switch(key_IOvaule) { case 1:key_array[key_id - 1].key_scan_count = 0; key_array[key_id - 1].key_lock_flag = 0; break; case 0:if(key_array[key_id - 1].key_lock_flag == 0) { key_array[key_id - 1].key_scan_count++; if(key_array[key_id - 1].key_scan_count > 5000) //长按一次持续的时间,可以调整数字调灵敏度 { key_array[key_id - 1].key_scan_count = 0; key_array[key_id - 1].key_lock_flag = 1; key_array[key_id - 1].key_num = 11; } } default:break; } } if(key_press_type == 111) //短按和长按判断 { switch(key_IOvaule) { case 1:key_array[key_id - 1].key_scan_count = 0; //按键没按下,计数清零 key_array[key_id - 1].key_lock_flag = 0; //自锁标志清零 if(key_array[key_id - 1].key_short_press_flag == 1) //按键松开会跳到这,可判定为短按 { key_array[key_id - 1].key_short_press_flag = 0; //短按标志清零 key_array[key_id - 1].key_num = 1; //短按赋键值 } break; case 0:if(key_array[key_id - 1].key_lock_flag == 0) //按键按下,并且标志位是0,判定是第一次进入计时 { key_array[key_id - 1].key_scan_count++; //计时 if(key_array[key_id - 1].key_scan_count > 100) //短按一次持续的时间,可以调整数字调灵敏度 { key_array[key_id - 1].key_short_press_flag = 1; //给短按标志置1,等待接下来的转态,松手或者按键持续按着 } } if(key_array[key_id - 1].key_scan_count > 5000) //按键没有松手,一直按着 { key_array[key_id - 1].key_scan_count = 0; //计时清零 key_array[key_id - 1].key_short_press_flag = 0; //短按标志清零 key_array[key_id - 1].key_lock_flag = 1; //自锁置1,完成了一次长按判断,防止重复进入 key_array[key_id - 1].key_num = 11; //长按赋键值 } default:break; } } }

2.头文件
#ifndef _user_key_h_
#define _user_key_h_

/*******************************************************************************************/
/***按键初始化函数,如脚位修改,函数需要修改***/
void user_key_init(void);

/***设置轮询按键***/
void user_key_set_scan(unsigned char key_press_type,unsigned char key_IOvaule, unsigned char key_id);

/***此函数放置在定时器的更新函数里***/
void user_key_scan(void);
/*******************************************************************************************/



/*******************************************************************************************/
/***主要使用这两个函数,获取按键的键值和清除按键的键值***/
/***获取按键的键值后必须清除按键的键值***/
/***注意获取和清除的编号一定要对应,不然容易出现按键一直处于长按或者短按***/
unsigned char key_get_num(unsigned char key_id);
void key_clear_num(unsigned char key_id);
/*******************************************************************************************/
#endif