蓝桥杯单片机组对按键模块的考察不仅仅会涉及到普通的按键扫描,还有可能设计到一些按键的高级用法:按下与松开、长短按等。
现在,我们介绍一下按键“按下与松开”功能的实现方法。
1、要使用独立按键,那么开发板上的J5跳帽必须接到BTN(独立按键)。
2、第二步,大家可以先参考一下独立按键一般作用的代码块:
https://blog.csdn.net/qq_44629819/article/details/104486419
在本次实验中,我们需要将原先的代码做轻微的变动:
static char KEY_STATE=KEY_STATE0;
将上述代码段(第二十二行)中“KEY_STATE”作为外部变量,也就是将代码移植出去。
Q:这样做有何目的?
A:有益于我们在主函数里读取到按键状态。
3、我们假设有一个这样的赛题片段:
如果大家对led模块不是很熟悉,可以先参考一下led模块显示的代码块:
https://blog.csdn.net/qq_44629819/article/details/104498166
T:在按键状态KEY_STATE=0的情况下,按键松开;在 KEY_STATE=2的情况下,按键按下。在按键松开的条件下,键值为0;在按键按下的一刹那,键值为按键本身后瞬间转为0。
4、如下,附上独立按键松开与按下代码块。
#include "STC15F2K60S2.h"
#define u8 unsigned char
#define KEY_STATE0 0 //判断按键是否按下
#define KEY_STATE1 1 //按键按下标志
#define KEY_STATE2 2 //判断按键是否松开
#define led_0 0x00
#define led_1 ((0x01)<<(1-1))
#define led_2 ((0x01)<<(2-1))
#define led_3 ((0x01)<<(3-1))
#define led_4 ((0x01)<<(4-1))
#define led_5 ((0x01)<<(5-1))
#define led_6 ((0x01)<<(6-1))
#define led_7 ((0x01)<<(7-1))
#define led_8 ((0x01)<<(8-1))
u8 code t_display[]={ //????
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //??
void Timer0Init(void) //配置定时器0,1ms中断
{
AUXR |= 0x80;
TMOD &= 0xF0;
TL0 = 0xCD;
TH0 = 0xD4;
TF0 = 0;
TR0 = 1;
ET0=1;
EA=1;
}
static char KEY_STATE=KEY_STATE0;//改变之后的效果
unsigned char key_scan()
{
u8 KEY=0;
u8 key_value=0;
P30=1;P31=1;P32=1;P33=1;
if(P30==0) KEY=7;
if(P31==0) KEY=6;
if(P32==0) KEY=5;
if(P33==0) KEY=4;
if((P30==1)&&(P31==1)&&(P32==1)&&(P33==1)) KEY=0;
switch(KEY_STATE)
{
case KEY_STATE0:
if(KEY!=0)
{
KEY_STATE=KEY_STATE1;
}
break;
case KEY_STATE1:
switch(KEY)
{
case 4: key_value=4; break;
case 5: key_value=5; break;
case 6: key_value=6; break;
case 7: key_value=7; break;
}
KEY_STATE=KEY_STATE2;
break;
case KEY_STATE2:
if(KEY==0)
{
KEY_STATE=KEY_STATE0;
}
break;
}
return key_value;
}
bit key_flag;
u8 key_val=0;
bit led_flag;
u8 led_COM[10]={led_0,led_1,led_2,led_3,led_4,led_5,led_6,led_7,led_8};
char led_choose1=0;
void main()
{
P0=~0X00;P2=0X80;P2=0X00;
P2=0XA0;P0=0X00;P2=0X00;
Timer0Init();
while(1)
{
if(led_flag)
{
led_flag=0;
P0=~led_COM[led_choose1];P2=0X80;P2=0X00;
}
if(key_flag)
{
key_flag=0;
key_val=key_scan();
switch(key_val)
{
case 4: break; //任务1
case 5: break; //任务2
case 6: break; //任务3
case 7: break; //任务4
}
}
if(KEY_STATE==KEY_STATE2)//先判断是否有按键按下
{
if(key_val==4)//再判断按下的按键是否是S4,注意:因为键值会瞬间改变,所以必须按照这样的顺序才可。
{
if(led_choose1!=1)//防止重复写锁存器
{
led_flag=1;led_choose1=1;//led1亮
}
}
}
else//此时按键松开
if(led_choose1!=0)//防止重复写锁存器
{
led_flag=1;led_choose1=0;//led1灭
}
}
}
void Timer0() interrupt 1 //[email protected]
{
static int key_count=0;
key_count++;
if(key_count==10)
{
key_count=0;
key_flag=1;
}
}
5、关于按键的长按与短按等内容以后会提到。
祝大家在蓝桥杯比赛中获得优异的成绩!
——南昌大学 电子183刘昊