最近在准备蓝桥杯,虽然以前也写过按键函数,但是没保存,每次写的时候思路都不一样。这里把现在想到的思路记录一下,为大家提供参考。
使用的开发板是蓝桥杯嵌入式的STM32G431RBT6,开发环境是用的keil5+STM32CubeMX(HAL库)。
连续按键
这里的连续按键是指,按键按下后会在按下期间一直返回,可以用在快速计算中。主要思路是用定时器定10ms后改变标志位来实现去抖动。
首先定义了两个标志位的存放寄存器:
u8 key_contr=0; //0位控制10ms,1位控制单独按键,2位控制500ms,3位控制长短按键
u8 key_tims=0; //0位代表10ms,2位代表500ms,3位控制长短按键
定时器7(周期1ms)回调函数的内容:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //定时器中断里面不能加hal延时
{
if(htim->Instance==TIM7) //1ms进一次
{
static u8 tmp_10ms=0;
static u16 tmp_500ms=0;
(key_contr & 0x01)?(tmp_10ms++):(tmp_10ms = 0);//10ms计时
if(tmp_10ms>10)
{
tmp_10ms = 0;
key_tims |= 0x01;
}
(key_contr & 0x04)?(tmp_500ms++):(tmp_500ms = 0);//10ms计时
if(tmp_500ms>500) //用于流水灯控制
{
tmp_500ms = 0;
key_tims |= 0x04;
}
}
}
按键扫描函数如下:
/*********************连续按键,返回多次键值(10ms)******************************/
u8 Key_Scan1(void)
{
u8 key=0; //保存键值
key = (GPIOB->IDR&0x0007)|(GPIOA->IDR&0x0001)<<3; //读取A0,B0,B1,B2,B3四个按键状态
key ^= 0x0f; //按键是低电平有效所以取反一下
if(key)
{
key_contr |= 0x01; //按下后标志位置1
if(key && key_tims&0x01) //按下且定时器记到10ms后进入
{
key_contr &= 0xfe; //一次按键监测完成,清零标致位返回键值
key_tims &= 0xfe;
return key;
}
else //没到10ms,程序不等待继续往下运行
return 0;
}
else
{
key_contr &= 0xfe; //松开或按键抖动期间,清零标致位
return 0;
}
}
/*************************************************************************/
单独按键
这里的单独按键是指,按下松手后返回一次键值。可用在一般的按键控制逻辑中。主要思路:结合前面的连续按键定时器去抖动,增加一个标志位控制只返回一次键值。
/*********************单独按键,松手后返回一次键值******************************/
u8 Key_Scan2(void) //单独按键,返回键值
{
u8 key=0; //保存键值
static u8 key_temp=0; //储存获取到的次数,用于标记按下的时间,理论上是10ms加一
key = (GPIOB->IDR&0x0007)|(GPIOA->IDR&0x0001)<<3; //读取A0,B0,B1,B2,B3四个按键状态
key ^= 0x0f; //按键是低电平有效所以取反一下
if(key)
{
key_contr |= 0x01; //按下后10ms判断标志位置1
if(key && key_tims&0x01) //按下且定时器记到10ms后进入
{
key_contr &= 0xfe; //获取到一次有效按键,清零10ms判断标志位
key_tims &= 0xfe;
key_contr |= 0x02; //打开单独按键控制标志位
key_temp = key; //储存键值,松手后返回
}
else
return 0;
}
else
{
if(key_contr&0x02) //按下后松开
{
key_contr &= ~0x03; //清除单独按键控制标志位
return key_temp; //松手后返回键值
}
else //未按下
{
key_contr &= 0xfe; //松开或按键抖动期间,清零标致位
return 0;
}
}
return 0;
}
/*************************************************************************/
长短按键
这里的长短按键指,按下时间少于2S只返回一次键值,大于两秒后和连续按键一样,可用在输入比较大的数字的时候。主要思路:通过检测到的连续按键次数,大于设定值后一直检测到一次连续按键返回一次键值,小于的时候用标志位控制只返回一次键值。
/*********************长短按(用于实现长按2s以上连续加,2s以下加一次),返回按键值******************************/
u8 Key_Scan3(void)
{
static u16 key_num=0;
u8 key1=0,key2=0;
key1 = (GPIOB->IDR&0x0007)|(GPIOA->IDR&0x0001)<<3; //读取A0,B0,B1,B2,B3四个按键状态
key1 ^= 0x0f; //按键是低电平有效所以取反一下
if(!key1) //未按下清除计数和标志位
{
key_contr &= ~0x08;
key_num = 0;
}
key2 = Key_Scan1(); //检测是否有有效按键
if(key2) //按下
{
key_num++; //计数
if(key_num>100) //超过100后一直返回键值
return key2;
else if(!(key_contr & 0x08)) //小于100时,只返回1次键值
{
key_contr |= 0x08; //标志已返回过键值
return key2;
}
else //按下返回过一次键值后一直返回0
return 0;
}
else //未按下
return 0;
}
/*************************************************************************/
总结
感觉写的比较冗余,还可以在改进一下,欢迎大家批评指正!(0_0)!
上传不了视频就放个动态图吧…:
版权声明:本文为CSDN博主「《CHANGE》」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43698771/article/details/122565480
最近在准备蓝桥杯,虽然以前也写过按键函数,但是没保存,每次写的时候思路都不一样。这里把现在想到的思路记录一下,为大家提供参考。
使用的开发板是蓝桥杯嵌入式的STM32G431RBT6,开发环境是用的keil5+STM32CubeMX(HAL库)。
连续按键
这里的连续按键是指,按键按下后会在按下期间一直返回,可以用在快速计算中。主要思路是用定时器定10ms后改变标志位来实现去抖动。
首先定义了两个标志位的存放寄存器:
u8 key_contr=0; //0位控制10ms,1位控制单独按键,2位控制500ms,3位控制长短按键
u8 key_tims=0; //0位代表10ms,2位代表500ms,3位控制长短按键
定时器7(周期1ms)回调函数的内容:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //定时器中断里面不能加hal延时
{
if(htim->Instance==TIM7) //1ms进一次
{
static u8 tmp_10ms=0;
static u16 tmp_500ms=0;
(key_contr & 0x01)?(tmp_10ms++):(tmp_10ms = 0);//10ms计时
if(tmp_10ms>10)
{
tmp_10ms = 0;
key_tims |= 0x01;
}
(key_contr & 0x04)?(tmp_500ms++):(tmp_500ms = 0);//10ms计时
if(tmp_500ms>500) //用于流水灯控制
{
tmp_500ms = 0;
key_tims |= 0x04;
}
}
}
按键扫描函数如下:
/*********************连续按键,返回多次键值(10ms)******************************/
u8 Key_Scan1(void)
{
u8 key=0; //保存键值
key = (GPIOB->IDR&0x0007)|(GPIOA->IDR&0x0001)<<3; //读取A0,B0,B1,B2,B3四个按键状态
key ^= 0x0f; //按键是低电平有效所以取反一下
if(key)
{
key_contr |= 0x01; //按下后标志位置1
if(key && key_tims&0x01) //按下且定时器记到10ms后进入
{
key_contr &= 0xfe; //一次按键监测完成,清零标致位返回键值
key_tims &= 0xfe;
return key;
}
else //没到10ms,程序不等待继续往下运行
return 0;
}
else
{
key_contr &= 0xfe; //松开或按键抖动期间,清零标致位
return 0;
}
}
/*************************************************************************/
单独按键
这里的单独按键是指,按下松手后返回一次键值。可用在一般的按键控制逻辑中。主要思路:结合前面的连续按键定时器去抖动,增加一个标志位控制只返回一次键值。
/*********************单独按键,松手后返回一次键值******************************/
u8 Key_Scan2(void) //单独按键,返回键值
{
u8 key=0; //保存键值
static u8 key_temp=0; //储存获取到的次数,用于标记按下的时间,理论上是10ms加一
key = (GPIOB->IDR&0x0007)|(GPIOA->IDR&0x0001)<<3; //读取A0,B0,B1,B2,B3四个按键状态
key ^= 0x0f; //按键是低电平有效所以取反一下
if(key)
{
key_contr |= 0x01; //按下后10ms判断标志位置1
if(key && key_tims&0x01) //按下且定时器记到10ms后进入
{
key_contr &= 0xfe; //获取到一次有效按键,清零10ms判断标志位
key_tims &= 0xfe;
key_contr |= 0x02; //打开单独按键控制标志位
key_temp = key; //储存键值,松手后返回
}
else
return 0;
}
else
{
if(key_contr&0x02) //按下后松开
{
key_contr &= ~0x03; //清除单独按键控制标志位
return key_temp; //松手后返回键值
}
else //未按下
{
key_contr &= 0xfe; //松开或按键抖动期间,清零标致位
return 0;
}
}
return 0;
}
/*************************************************************************/
长短按键
这里的长短按键指,按下时间少于2S只返回一次键值,大于两秒后和连续按键一样,可用在输入比较大的数字的时候。主要思路:通过检测到的连续按键次数,大于设定值后一直检测到一次连续按键返回一次键值,小于的时候用标志位控制只返回一次键值。
/*********************长短按(用于实现长按2s以上连续加,2s以下加一次),返回按键值******************************/
u8 Key_Scan3(void)
{
static u16 key_num=0;
u8 key1=0,key2=0;
key1 = (GPIOB->IDR&0x0007)|(GPIOA->IDR&0x0001)<<3; //读取A0,B0,B1,B2,B3四个按键状态
key1 ^= 0x0f; //按键是低电平有效所以取反一下
if(!key1) //未按下清除计数和标志位
{
key_contr &= ~0x08;
key_num = 0;
}
key2 = Key_Scan1(); //检测是否有有效按键
if(key2) //按下
{
key_num++; //计数
if(key_num>100) //超过100后一直返回键值
return key2;
else if(!(key_contr & 0x08)) //小于100时,只返回1次键值
{
key_contr |= 0x08; //标志已返回过键值
return key2;
}
else //按下返回过一次键值后一直返回0
return 0;
}
else //未按下
return 0;
}
/*************************************************************************/
总结
感觉写的比较冗余,还可以在改进一下,欢迎大家批评指正!(0_0)!
上传不了视频就放个动态图吧…:
版权声明:本文为CSDN博主「《CHANGE》」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43698771/article/details/122565480
暂无评论