【蓝桥杯单片机国赛】长按和短按
问题
第九届蓝桥杯单片机设计与开发项目决赛有这一部分:
“S7 :定义为参数”设置”按键,按下此按键,进入电压阈值参数设置界面(图6), 在阈值设置界面下,S6″回显”按键定义为阈值调整功能(备注:非阈值设置界面下,S6按键为回显功能),每次按下S6,电压阈值增加0.1V,长按0.8秒以上,可实现快速增加功能(备注:电压阈值设置范围:0.1V~5.0V),阈值调整完成后,再次按下S7按键,退出”设置”界面(图6),返回数据显示界面。”
如何利用定时器区分长按和短按?
解决思路
设置两类变量
1.检测当前状态变量 (如flag_key_1,count_t)
他们会随着按键的状态随时发生变化
2.记录当前状态变量 (如flag_key_2,time_dat)
用于记录第一种变化,便于后续的数据处理
例题
短按S7点亮L1,短按S7点亮L2,短按S6点亮L3,短按S6点亮L4
衡量长按短按的时间自拟
(硬件平台:北京国信长天科技CT107D 单片机综合实训平台)
按键处理函数:
void Scanf_Key()
{
while(S7 == 0) //flag_key_1是是否按下的标志位,如果按下就为1,没按下就为0
{
NixieTube_show();
flag_key_1 = 1;
}
while(S6 == 0)
{
NixieTube_show();
flag_key_1 = 2;
}
if((S7 != 0)||(S6 != 0))
{
flag_key_1 = 0;
}
}
定时器中断服务函数:
void Time_Ser()interrupt 3
{
TH1 = (65536-50000)/256;
TL1 = (65536-50000)%256;
if(flag_key_1 != 0) //当按键按下时count才计数
{
count_t++;
time_dat = count_t; //记录完把值赋给time_dat
flag_key_2 = flag_key_1; //把选择什么按键记录下来
}
else count_t = 0;
}
数据处理函数(此处是点亮LED):
void LED_Show()
{
switch(flag_key_2)
{
case 1:
if((time_dat <= 10)&&(time_dat >= 1))//(time_dat >= 1)也有消抖的作用
{
LED_dat = ~0x01;
}
else if(time_dat >= 10)
{
LED_dat = ~0x02;
}
break;
case 2:
if((time_dat <= 10)&&(time_dat >= 1))
{
LED_dat = ~0x04;
}
else if(time_dat >= 10)
{
LED_dat = ~0x08;
}
break;
}
XBYTE[0x8000] = LED_dat;
flag_key_2 = 0; //处理完毕之后flag_key_2要清零
}
整体代码参考
#include <STC15F2K60S2.h>
#include "absacc.h"
unsigned char code NixieTube_date[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char LED_dat = 0xff;
sbit S7 = P3^0;
sbit S6 = P3^1;
unsigned int count_t = 0,time_dat= 0;
void NixieTube_show();
void Delay(unsigned int t);
unsigned char flag_key_1 = 0,flag_key_2 = 0;
void NixieTube_Byte_show(unsigned char pos,unsigned char value)
{
XBYTE[0xc000] = 0x00;
XBYTE[0xe000] = value;
XBYTE[0xc000] = (0x01<<pos);
}
void Delay(unsigned int t)
{
while(t--);
}
void System_init()
{
XBYTE[0x8000] = 0xff;
XBYTE[0xa000] = 0x00;
}
void Time_Init() //定时器1初始化
{
TMOD = 0x10;
TH1 = (65536-50000)/256;
TL1 = (65536-50000)%256;
TR1 = 1;
ET1 = 1;
EA = 1;
}
/*================================
这里的变量有2类
1.检测当前状态变量 (如flag_key_1,count_t)
他们会随着按键的状态随时发生变化
2.记录当前状态变量 (如flag_key_2,time_dat)
用于记录第一种变化
================================*/
void NixieTube_show() //可以用这个函数看按键的状态
{
NixieTube_Byte_show(0,NixieTube_date[flag_key_1/10]);Delay(100);
NixieTube_Byte_show(1,NixieTube_date[flag_key_1%10]);Delay(100);
NixieTube_Byte_show(1,0xff);
}
void Time_Ser()interrupt 3
{
TH1 = (65536-50000)/256;
TL1 = (65536-50000)%256;
if(flag_key_1 != 0) //当按键按下时count才计数
{
count_t++;
time_dat = count_t; //记录完把值赋给time_dat
flag_key_2 = flag_key_1; //把选择什么按键记录下来
}
else count_t = 0;
}
void Scanf_Key()
{
while(S7 == 0) //flag_key_1是是否按下的标志位,如果按下就为1,没按下就为0
{
NixieTube_show();
flag_key_1 = 1;
}
while(S6 == 0)
{
NixieTube_show();
flag_key_1 = 2;
}
if((S7 != 0)&&(S6 != 0))
{
flag_key_1 = 0;
}
}
void LED_Show()
{
switch(flag_key_2)
{
case 1:
if((time_dat <= 10)&&(time_dat >= 1))//(time_dat >= 1)也有消抖的作用
{
LED_dat = ~0x01;
}
else if(time_dat >= 10)
{
LED_dat = ~0x02;
}
break;
case 2:
if((time_dat <= 10)&&(time_dat >= 1))
{
LED_dat = ~0x04;
}
else if(time_dat >= 10)
{
LED_dat = ~0x08;
}
break;
}
XBYTE[0x8000] = LED_dat;
flag_key_2 = 0; //处理完毕之后flag_key_2要清零
}
void main()
{
System_init();
Time_Init();
while(1)
{
NixieTube_show();
LED_Show();
Scanf_Key();
}
}
版权声明:本文为weixin_45413123原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。