关于稳定按键问题。涉及消抖,和按键开关。用来做电话免提。
我的电路上是这样连的。IO口直接读按键状态。下拉电阻。按下按键高电平输入。现在要求的功能是。按键按一下电话免提打开拨电话。再按一下免提挂机。用单片机读取这个按键。但是成功率不是很高。有时候挂不了电话。有时候打不开免提。很是头疼。中间用了一个状态机。按键也做了消抖。程序如下
while(1)
{
Key = Getkey();
if( Key == 11 ){ MeetKey = ~MeetKey; } 这个是转换状态标志
if(Key !=11)
{
if( MeetKey & ( Mcu_1062 == 0 ))
{
Led_Blue = 0;
}
if( ( MeetKey == 0 ) & ( Mcu_1062 == 0 ))
{
Led_Blue = 1;
}
if( MeetKey & Mcu_1062 )
{
Meet();
}
}
}
int Getkey()
{
int X;
X = 0;
if( Set){ delay(1100);if( Set ){ X = 1; } } //设置
if( Exit ){ delay(1100); if( Exit ){ X = 2;} } //退出
if( Flash ){delay(1100); if( Flash){ X = 3;}} //转接
if( Save){ delay(1100); if(Save){ X = 4;}} //保存
if( SetFlash ){delay(1100); if( SetFlash ){ X = 5;}} //设置FLASH时间
if( FlashIncre ){delay(1100);if( FlashIncre ){ X = 6;}} //Flash加
if( FlashDecre ){delay(1100); if( FlashDecre ){ X = 7;}} //Flash减
if( Memory ){ delay(1100);if( Memory ){ X = 8;} } //记忆
if( Mute2 ){delay(1100); if( Mute2 ){ X = 9;}} //静音外部
if( Mute1 ){delay(1100); if( Mute1 ){ X = 10;}} //静音内部
if( Hook ){ delay(1100);if( Hook ){ while(!Hook );X = 11;}} //会议
return X;
}
各位帮忙来点思路。
做产品的。一个会议电话 这可不算状态机哟~
你这不还是判断->延时->再判断,
正确的做法是数字滤波 #include "key.h"
KEY_T Key = {0};
void KEY_DoEvent(void)
{
// 读取键值,低电平表示有键按下,取反变成置位有效
u8 key_value = (~KEY_PORT)&(K1|K2|K3|K4);
if( key_value==Key.Value )
{
Key.Tick++;
// 稳态检测时间:40ms
if( Key.Tick>=MS(40) )
{
Key.Tick = 0;
// 长按,40ms*25 = 1s
Key.IsLong = false;
Key.CountLong++;
if( Key.CountLong>=25 )
{
Key.CountLong = 0;
Key.IsLong = true;
// K1允许长按触发
Key.Saved &= ~(K1);
}
// 重复,40ms*4 = 160ms
Key.CountRepeat++;
if( Key.CountRepeat>=Key.CountRepeatMax )
{
Key.CountRepeat = 0;
Key.CountRepeatMax = 4;
// K3,K4允许连续触发
Key.Saved &= ~(K3|K4);
}
}
else
{
return;
}
}
else
{
Key.Tick = 0;
Key.Value = key_value;
Key.CountLong = 0;
Key.CountRepeat = 0;
// 首次重复,40ms*12 = 480ms
Key.CountRepeatMax = 12;
return;
}
//
// 按键处理:允许多个按键被按下时,新按下的按键被响应
//
key_value ^= Key.Saved; // 异或:获取和上一次有效按键的不同键值
key_value &= Key.Value; // 与:只获取新增按键值
Key.Saved= Key.Value; // 保存这次有效键值
// K1:设定
if( key_value&K1 )
{
if( Key.IsLong )
{
Key_Setting();
}
else
{
Key_Shift();
}
}
// K2:移位
if( key_value&K2 )
{
Key_Shift();
}
// K3:递增
if( key_value&K3 )
{
Key_Inc();
}
// K4:递减
if( key_value&K4 )
{
Key_Dec();
}
} // key.h
#ifndef _H_KEY
#define _H_KEY
#include "main.h"
#define Init_KEY KEY_Init
extern void KEY_Init(void);
extern void KEY_DoEvent(void);
#define K1 _BIT(KEY1)
#define K2 _BIT(KEY2)
#define K3 _BIT(KEY3)
#define K4 _BIT(KEY4)
typedef struct
{
u8 Tick;
u8 CountLong;
u8 CountRepeat;
u8 CountRepeatMax;
u8 Value;
u8 Saved;
bool IsLong;
} KEY_T;
extern KEY_T Key;
extern void Key_Setting(void);
extern void Key_Shift(void);
extern void Key_Inc(void);
extern void Key_Dec(void);
enum
{
SHIFT_HOUR,
SHIFT_MIN,
SHIFT_SEC,
SHIFT_MS
};
#endif 保证KEY_DoEvent()在主循环中每若干个ms只执行一次...
(比如1ms,然后#define MS(ms) (ms)
如果是2ms,则是#define MS(ms) ((ms)+1)/2)
)
关键按键的端口定义如下
// KEY
#define KEY1 B,7
#define KEY2 B,6
#define KEY3 B,5
#define KEY4 B,4
#define KEY_PORT PINB 以上程序支持按键数字滤波,一次响应,长按触发,连续触发,
某键被按下不影响其它按键的响应和数字滤波
简单的修改后还可以检测按键抬起和复合按键... 谢谢各位的程序。程序我解决了。效果还可以。还有1楼。能不能给我说说状态机是怎么回事啊。不是很了解这个。谢谢。 snoopyzz 发表于 2009-7-20 15:50 static/image/common/back.gif
#include "key.h"
KEY_T Key = {0};
程序方案很好啊!我还想问下,这里的MS是如何实现的,定时器中断吗?
可不可以不用中断的?.c文件不全啊? 学习一下.... snoopyzz 发表于 2009-7-20 15:53 static/image/common/back.gif
保证KEY_DoEvent()在主循环中每若干个ms只执行一次...
(比如1ms,然后#define MS(ms) (ms)
如果是2ms,则是 ...
能发一下.c文件吗???
页:
[1]