找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2162|回复: 1
打印 上一主题 下一主题
收起左侧

进一步完善的可在任何系统上移植的按键操作系统,包含单击、双击、多击、N击、长按...

[复制链接]
跳转到指定楼层
楼主
ID:391730 发表于 2019-12-17 16:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这个系统可以近似的看成是按键并发操作,单击、双击等一系列的动作都已经定义过。以下是头文件:

#define BaseTime 10   //时基,由单片机时钟中断精准产生
#define number_init          0xfffffffd  //对任何时间变量需要初始化的地方预设的初始化值


typedef  unsigned char         uchar  ;
typedef  unsigned int         uint         ;
typedef  unsigned long   ulong         ;
typedef  unsigned long   utime  ;


enum ButtonModel{noneClick=0,singalClick,doubleClick,repeatClick,longPress};
enum ButtonStaus{nonePress=1,pressDown,pressUp,pressDownHold};       


struct button
{
    uchar outPutEn:1;       //发送数据使能
    uchar lastButton:1;     //缓存按键上次变动后的状态
    uchar init_leavel:1;    //设置默认按键电平
        uchar longPressFlag:1;        //长按释放标志 默认0,一旦开始长按则置1
        uchar Gpio_level :3;     //读取IO口电平
        uchar applyUseOpenAPI:1;         //在关机状态下,若本按键按下启动了系统,则需要申请全局变量标明,禁止其他按键关闭被本按键打开的系统(自己打开自己负责关闭)

        uchar ticks;            //按键按下次数
    enum ButtonStaus lastButtonStaus;   //缓存按键上个循环的状态
    enum ButtonStaus thisButtonStaus;   //缓存按键本循环的状态
    enum ButtonModel lastButtonModel; //缓存按键上个循环所处的模式
    enum ButtonModel thisButtonModel; //缓存按键本循环应该所处的模式

    uint changeModelTime;  //10ms基准 多击时间定义
    uint pressLongTime;    //10ms基准 长按时间定义

    utime lastPressDownMoment;     //上次按键按下所处的时刻
    utime thisPressDownMoment;     //本次按键按下所处的时刻
    uint tempTime;                //缓存按键两次按下之间的时长

    utime buttonConfir;     //按键防抖时长


    utime getTimer; //获取时钟精准时刻,用于设定按键扫描周期
    utime acquisitionMoment; //获取时钟精准时刻,用于记录相同按键状态持续时长

    uchar  (*read_gpio)(void); //获取按键状态方法
};

void Button_init(struct button *Key,uchar(*get_leavel)(),bit init_button_leavel,uint LongPressTimes,uint changeModelTime);  //按键初始化
void Scan_key(struct button *Key,utime timer ,uint enOutTime ,uint noiseProofTime);  //按键扫描函数

以下是DEMO:
#include"button.h"

struct button button1,button2;

uchar keyCounter=0;
uint Pwm=0;
utime COLCK=0;

inline uchar Get_gpio_level1(void)//获取开关的电平,特别注意:如果一个IO口下有三四十个按钮,用ADC扫描不同的电压值来判断是哪个按钮动作时,要注意程序嵌套层数,层数太多会有栈溢出的问题,暂时无解
{
    return P10;   //P10是单片机接开关的IO口
}
inline uchar Get_gpio_level2(void)
{
    return P11;   //P11是单片机接开关的IO口
}
uchar Pwm_excute(uchar pwmDuty); //pwm示例程序,不填充
void Get_button_model(struct button* ); //对扫描到的单击,双击,长按动作响应

main()
{
    Button_init(&button1,Get_gpio_level1,1,300,100);// 默认开关不动作时是高电平,定义长按时长为300个10ms,定义多击时长为100个10ms
    Button_init(&button2,Get_gpio_level2,1,300,100);

    /*记得开COLCK所在的中断!这个时间中断程序就不填充了*/
    while(1)
    {
        Scan_key(&button1,COLCK,50,20); //定义50ms 扫描一次,定义按键防抖时间20ms
        Scan_key(&button2,COLCK,50,20);
        Get_button_model(&button1); //对按键动作响应
        Get_button_model(&button2);
    }
}

void Get_button_model(struct button* Key  )
/*注意啦!多按键会存在资源竞争的风险,比如按键1打开了某个操作只能由按键1关闭,
如果不仔细设计会存在按键2执行某个动作时关闭掉按键1打开的操作,遇到这个问题记得applyUseOpenAPI这个玩意来申请权限,然后用全局变量标识这个操作已经被占用,
目前在本DEMO例程中没有用到这么复杂的设计
*/
{
    if(Key->outPutEn)
    {
        switch(Key->thisButtonModel)
        {
            switch noneClick:
                {
                    /*
                    最精华的部分,在按键无动作的时候该处理那些数据,

                    */
                    break;
                }
            switch singalClick:
                {
                    Pwm++;
                    if(Pwm>255)
                        Pwm=255;
                    Pwm_excute(Pwm); //这个函数没有填充,每个单片机的PWM定义不一样,甚至不是PWM的动作,单击执行什么动作,自己发挥
                    break;
                }
            switch doubleClick:
                {
                   /*

                   */

                   break;
                }
            switch repeatClick:
                {

                    /*

                    */
                    break;
                }
            switch longPress:
                {

                    /*

                    */
                    break;
                }

        }

        Key->outPutEn=0;  //单片机运行的速度太快,但是按键扫描又设置的固定多长时间扫描一次,为了解决矛盾,才有的这么个参数
    }
}

EXN interrupt N  //定时器中断
{
    /*
    */
    COLCK++; //每10ms加1
}




PS:公司的项目非常复杂,用的是多按键并发,等过段时间我整一张原理图上来。当然,公司项目的源程序有5千行,处于保密需求是不可能上传的。

按键驱动.zip

5.07 KB, 下载次数: 34, 下载积分: 黑币 -5

程序

评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:391730 发表于 2019-12-17 16:46 | 只看该作者
Get_button_model函数中的SWITCH 下面一系列的SWITCH应该是CASE。没处理,自己发挥。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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