搜索
bottom↓
回复: 9

关于稳定按键问题。涉及消抖,和按键开关。用来做电话免提。

[复制链接]

出0入0汤圆

发表于 2009-7-20 15:32:34 | 显示全部楼层 |阅读模式
我的电路上是这样连的。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;
}
各位帮忙来点思路。
做产品的。一个会议电话

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2009-7-20 15:47:01 | 显示全部楼层
这可不算状态机哟~

你这不还是判断->延时->再判断,
正确的做法是数字滤波

出0入0汤圆

发表于 2009-7-20 15:50:39 | 显示全部楼层
#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();
        }
}

出0入0汤圆

发表于 2009-7-20 15:51:07 | 显示全部楼层
// 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

出0入0汤圆

发表于 2009-7-20 15:53:02 | 显示全部楼层
保证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

出0入0汤圆

发表于 2009-7-20 15:57:43 | 显示全部楼层
以上程序支持按键数字滤波,一次响应,长按触发,连续触发,
某键被按下不影响其它按键的响应和数字滤波


简单的修改后还可以检测按键抬起和复合按键...

出0入0汤圆

 楼主| 发表于 2009-7-21 00:57:21 | 显示全部楼层
谢谢各位的程序。程序我解决了。效果还可以。还有1楼。能不能给我说说状态机是怎么回事啊。不是很了解这个。谢谢。

出0入0汤圆

发表于 2012-10-26 09:24:29 | 显示全部楼层
snoopyzz 发表于 2009-7-20 15:50
#include "key.h"

KEY_T        Key = {0};

程序方案很好啊!我还想问下,这里的MS是如何实现的,定时器中断吗?
可不可以不用中断的?.c文件不全啊?

出0入0汤圆

发表于 2013-4-7 12:04:54 来自手机 | 显示全部楼层
学习一下....

出0入0汤圆

发表于 2013-4-7 12:14:35 | 显示全部楼层
snoopyzz 发表于 2009-7-20 15:53
保证KEY_DoEvent()在主循环中每若干个ms只执行一次...
(比如1ms,然后#define MS(ms) (ms)
如果是2ms,则是 ...

能发一下.c文件吗???
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-27 02:19

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表