最近在做单片机独立按键长按连加,短按加1的功能,网上找了很多例子,都不是很满意,试了很多都不成功。最后找了一个很多人在用的代码,不知道什么原因,在我这边总是无法实现功能,搞了好几天都不能解决,修修改改无数次,实在是没思路了。以下是这部分代码,希望大神赐教!
现在的主要问题是:
1,只能实现短按一次的功能,即数码管显示0时,短按一下可以增加到1,再按就没反应了。
2,应该是KEY_SCAN() 和KEY_PROCESS()这两个函数的问题,但是找了好久,改了很多也没解决问题,现在没有思路了。按键扫描函数KEY_SCAN()是在网上找的朱兆琪学习板的程序,我用的单片机是AVR的,在我上面怎么都用不了,不知道啥问题,不知道是程序问题还是硬件问题,感觉硬件没啥问题,换另一种写法就没问题,但是如下写法总是不行。
单片机源程序如下:
unsigned char key_number=0; //触发的按键编号
unsigned short key_time_delay_cnt_SW1 =0; // SW1 按键去抖动计数器
unsigned char key_lock_SW1=0; // SW1 自锁变量
unsigned short key_cont_trigg_cnt_SW1 =0; //SW1连加计数器
unsigned short key_start_cnt1 =0; //中断启动计数器标志位
unsigned short key_start_cnt2 =0;
unsigned short key_start_trigg_cnt1 =0;
unsigned short key_start_trigg_cnt2 =0;
uint8_t KEY_SCAN(void); // 按键扫描函数
void KEY_PROCESS(uint8_t); //按键处理函数
int main(void)
{
KEY_PROCESS(P_min_set_temp_ON); //P_min_set_temp_ON在数码管上显示分和秒
}
uint8_t KEY_SCAN(void)
{
// 扫描SW1
if (1==KEY_SW1) //按键没有被按下(高电平),清零标志位
{
key_lock_SW1 =0; //自锁标志位清零
key_time_delay_cnt_SW1=0; //去抖延时清零
key_start_cnt1=0; //在中断中启动计数
key_cont_trigg_cnt_SW1 =0;
key_start_trigg_cnt1=0; //在中断中启动计数
}
else if (0==key_lock_SW1) //如果有按键按下,且是第一次按下
{
key_start_cnt1=1; //中断中启动计数器,key_time_delay_cnt_SW1开始自加
if (key_time_delay_cnt_SW1 > KEY_TIME_DELAY_SW1) //自加到10mms去抖动,KEY_TIME_DELAY_SW1为进入中断10次,约10ms
{
key_time_delay_cnt_SW1 =0;
key_start_cnt1=0;
key_lock_SW1=1;
key_number=1; //触发 一次SW1单次触发,如果松手,立即返回到if (KEY_SW1)
}
}
else if (key_time_delay_cnt_SW1 < KEY_TIME_ALWAYS_PRESS) //如果按住不放, 在1s内自加,KEY_TIME_ALWAYS_PRESS为1s
{
key_start_cnt1=1;
}
else //持续按住大于1s时,进入连加状态
{
key_start_trigg_cnt1=1; //启动key_cont_trigg_cnt_SW1自加
if (key_cont_trigg_cnt_SW1 > KEY_TIME_SEQ_INTER) //自加到250ms后,清零,KEY_TIME_SEQ_INTER为250ms
{
key_cont_trigg_cnt_SW1 =0;
key_start_trigg_cnt2=0;
key_number =2; //触发SW1连续触发,实现长按SW1超过1s, 产生每250ms触发一次按键的效果
}
}
return key_number; //返回按键编号值
}
void KEY_PROCESS (uint8_t min_sec_set_temp)
{
KEY= KEY_SCAN(); //根据返回的按键编号值处理
switch (KEY)
{
case 1: // SW1 单次触发
min_sec_set_temp ++;
if (min_sec_set_temp >99)
{
min_sec_set_temp=0;
}
//key_number=0;
break;
case 2: //SW1开始连加触发
min_sec_set_temp --;
if (min_sec_set_temp >99)
{
min_sec_set_temp=99;
}
break;
default: ; break;
}
min_decade=min_sec_set_temp /10; //数码管显示
min_the_uint=min_sec_set_temp %10;
sec_decade=min_sec_set_temp /10;
sec_the_uint=min_sec_set_temp %10;
DISPLAY_TIME_SET_MIN_SEC(1); //数码管显示函数,通过按键加减数字可以显示出来
}
ISR(TIMER1_OVF_vect) //中断服务程序, 8M/256分频,1ms进一次中断
{
TIFR1 =0x01; //中断标志置位
TIMSK1 =0x00; //关中断
if (key_start_cnt1==1)
{
key_time_delay_cnt_SW1 ++;
}
else
{
key_time_delay_cnt_SW1=0;
}
if (key_start_cnt2==1)
{
key_time_delay_cnt_SW2++;
}
else
{
key_time_delay_cnt_SW2=0;
}
if (key_start_trigg_cnt1==1)
{
key_cont_trigg_cnt_SW1 ++;
}
else
{
key_cont_trigg_cnt_SW1=0;
}
if (key_start_trigg_cnt2==1)
{
key_cont_trigg_cnt_SW2 ++;
}
else
{
key_cont_trigg_cnt_SW2=0;
}
TCNT1H =0xFF; //计数器重装初值高八位
TCNT1L =0xE0; //计数器重装初值低八位
TIMSK1=0x01; //开中断
}
|