#include "user_key.h"
#include "stm32f10x.h"
/***************************************************************************************************/
/*移植需要改动4处地方*/
/***************************************************************************************************/
/**************************************移植修改的第1处*************************************************/
/*按键的数量,短按时间,长按时间设置*/
/***************************************************************************************************/
#define KEY_NUM_ALL 2 //按键的总的数量,预设了7个按键,如值超过7的话,记得按例修改代码
#define KEY_SHORT_TIME 20 //短按的持续时间,这个值可以调整按键的灵敏度
#define KEY_LONG_TIME 4000 //长按的持续时间,这个值可以调整按键的灵敏度
/***************************************************************************************************/
/**************************************移植修改的第2处**********************************************/
/*按键电平的宏定义,改变按键需要改动这里宏定义,且必须按KEY1-KEY7一次增加*/
/***************************************************************************************************/
#define KEY1 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3) //按键的状态函数,增加按键,可以按这个格式增加
#define KEY2 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4)
/***************************************************************************************************/
/***************************************************************************************************/
/*此结构体类型无需改动*/
/***************************************************************************************************/
typedef struct
{
const unsigned char key_press_type; //按键按下类型设置,1:短按 11:长按 111:短按和长按
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;
/***************************************************************************************************/
/*************************************移植修改的第3处**********************************************/
/*预设7个按键,如增加新按键,可按格式增加,只允许改动第一个值,只有1,11,111三个值*/
/***************************************************************************************************/
KEY_InitTypeDef key_array[KEY_NUM_ALL] =
{
{111,0,0,0,0,0,},
#if KEY_NUM_ALL > 1
{111,0,0,0,0,0,},
#endif
#if KEY_NUM_ALL > 2
{1,0,0,0,0,0,},
#endif
#if KEY_NUM_ALL > 3
{1,0,0,0,0,0,},
#endif
#if KEY_NUM_ALL > 4
{1,0,0,0,0,0,},
#endif
#if KEY_NUM_ALL > 5
{1,0,0,0,0,0,},
#endif
#if KEY_NUM_ALL > 6
{1,0,0,0,0,0,},
#endif
};
/***************************************************************************************************/
/***************************************移植修改的第4处*****************************************/
/*按键初始化函数,更改按键硬件需要改动此函数*/
/***************************************************************************************************/
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_IPU;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStruct);
}
/*******************************************************************************************/
/***************************************************************************************************************/
/*此函数必须放置到定时器中断服务函数中,轮询判断按键状态*/
/*如按键超过7个,按次格式依次增加即可,此函数移植无需改动*/
/**************************************************************************************************************/
void user_key_scan(void)
{
unsigned char i,key_IOvaule; //定义按键的电压变量
for(i = 0;i < KEY_NUM_ALL; i++) //轮询按键电平
{
switch(i)
{
case 0: if(KEY1 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break; //条件编译方式预设了7个按键
//超过7个按格式增加即可
#if KEY_NUM_ALL > 1
case 1: if(KEY2 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break; //判断按键电平
#endif
#if KEY_NUM_ALL > 2
case 2: if(KEY3 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break;
#endif
#if KEY_NUM_ALL > 3
case 3: if(KEY4 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break;
#endif
#if KEY_NUM_ALL > 4
case 4: if(KEY5 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break;
#endif
#if KEY_NUM_ALL > 5
case 5: if(KEY6 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break;
#endif
#if KEY_NUM_ALL > 6
case 6: if(KEY7 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break;
#endif
}
if(key_array[i].key_press_type == 1) //判断按键需要做什么类型的检测
{ //做短按判断
switch(key_IOvaule)
{
case 1: key_array[i].key_scan_count = 0; //按键没按下,计数清零
key_array[i].key_lock_flag = 0; //自锁标志清零
break;
case 0: if(key_array[i].key_lock_flag == 0) //按键按下并且是第一次按下
{
key_array[i].key_scan_count++; //计数时间开始
if(key_array[i].key_scan_count > KEY_SHORT_TIME) //计数时间大于设定的值,按键短按下
{
key_array[i].key_scan_count = 0; //计数清零
key_array[i].key_lock_flag = 1; //完成了一次短按判断.标志清零,避免重复请进入
key_array[i].key_num = 1; //给按键赋键值,短按
}
};break;
}
}
if(key_array[i].key_press_type == 11) //判断按键需要做什么类型的检测
{ //做长按判断
switch(key_IOvaule)
{
case 1: key_array[i].key_scan_count = 0; //按键没按下,计数清零
key_array[i].key_lock_flag = 0; //自锁标志清零
break;
case 0: if(key_array[i].key_lock_flag == 0) //按键按下并且是第一次按下
{
key_array[i].key_scan_count++; //计数时间开始
if(key_array[i].key_scan_count > KEY_LONG_TIME) //计数时间大于设定的值,按键长按下
{
key_array[i].key_scan_count = 0; //计数清零
key_array[i].key_lock_flag = 1; //完成了一次短按判断.标志清零,避免重复请进入
key_array[i].key_num = 11; //给按键赋键值,长按
}
};break;
}
}
if(key_array[i].key_press_type == 111) //判断按键需要做什么类型的检测
{ //做短按和长按一起判断
switch(key_IOvaule)
{
case 1: key_array[i].key_scan_count = 0; //按键没按下,计数清零
key_array[i].key_lock_flag = 0; //自锁标志清零
if(key_array[i].key_short_press_flag == 1) //按键松开会跳到这,最终判定为短按
{
key_array[i].key_short_press_flag = 0; //短按标志清零
key_array[i].key_num = 1; //给按键赋键值,短按
};break;
case 0: if(key_array[i].key_lock_flag == 0) //按键按下并且是第一次按下
{
key_array[i].key_scan_count++; //计数时间开始
if(key_array[i].key_scan_count > KEY_SHORT_TIME) //计数时间大于设定的值, 属于按键短按
{
key_array[i].key_short_press_flag = 1; //设置短按标志位,初步判断为短按
} //接下来等待计时,可以判断按键是松开还是继续按着
}
if(key_array[i].key_scan_count > (KEY_LONG_TIME - KEY_SHORT_TIME))
{ //按键计时接着增加,大于设定的长按时间
key_array[i].key_scan_count = 0; //计时清零
key_array[i].key_lock_flag = 1; //设置自锁标志,完成一个长按判断,放置重复进入
key_array[i].key_short_press_flag = 0; //清除短按标志
key_array[i].key_num = 11; //给按键赋键值,长按
};break;
}
}
}
}
/*********************************************************************************************************************/
/*********************************************************************************************/
/*此函数获取按键键值,如按键个数小于7,移植无需改动,参数为按键的序号key_id:1-7,返回值1,11,111三种*/
/*如按键超过7个,按次格式依次增加即可*/
/*********************************************************************************************/
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;
#if KEY_NUM_ALL > 1
case 2: key_local_param = key_array[1].key_num;break;
#endif
#if KEY_NUM_ALL > 2
case 3: key_local_param = key_array[2].key_num;break;
#endif
#if KEY_NUM_ALL > 3
case 4: key_local_param = key_array[3].key_num;break;
#endif
#if KEY_NUM_ALL > 4
case 5: key_local_param = key_array[4].key_num;break;
#endif
#if KEY_NUM_ALL > 5
case 6: key_local_param = key_array[5].key_num;break;
#endif
#if KEY_NUM_ALL > 6
case 7: key_local_param = key_array[6].key_num;break;
#endif
}
return key_local_param;
}
/***************************************************************************************/
/***************************************************************************************/
/*此函数清除按键键值,如按键个数小于7,移植无需改动,参数为按键的序号key_id:1-7*/
/*如按键超过7个,按次格式依次增加即可*/
/***************************************************************************************/
void key_clear_num(unsigned char key_id)
{
switch(key_id)
{
case 1: key_array[0].key_num = 0;break;
#if KEY_NUM_ALL > 1
case 2: key_array[1].key_num = 0;break;
#endif
#if KEY_NUM_ALL > 2
case 3: key_array[2].key_num = 0;break;
#endif
#if KEY_NUM_ALL > 3
case 4: key_array[3].key_num = 0;break;
#endif
#if KEY_NUM_ALL > 4
case 5: key_array[4].key_num = 0;break;
#endif
#if KEY_NUM_ALL > 5
case 6: key_array[5].key_num = 0;break;
#endif
#if KEY_NUM_ALL > 6
case 7: key_array[6].key_num = 0;break;
#endif
}
}
/*************************************************************************************/
#ifndef _user_key_h_
#define _user_key_h_
/**************************/
/*按键初始化,移植需改动*/
void user_key_init(void);
/**************************/
/******************************************************/
/*此函数必须放置到定时器中断服务函数中,轮询判断按键状态*/
/*如按键超过7个,按次格式依次增加即可,此函数移植无需改动*/
void user_key_scan(void);
/*****************************************************/
/*****************************************************/
/*这两个函数配合使用,在主函数调用*/
/*如按键超过7个,按次格式依次增加即可,此函数移植无需改动*/
/*主要使用这两个函数,获取按键的键值和清除按键的键值*/
/*获取按键的键值后必须清除按键的键值*/
/*注意获取和清除的编号一定要对应,不然容易出现按键一直处于长按或者短按*/
unsigned char key_get_num(unsigned char key_id);
void key_clear_num(unsigned char key_id);
/*****************************************************/
#endif