valetang-126879 发表于 2017-3-3 14:20:27

按键这个看似简单的应用

suyong_yq 发表于 2017-3-5 00:47:20

无帝老三 发表于 2017-2-22 13:56
您好,是不是状态机加定时器?
可不可以用任务延时代替定时器?

是状态机+定时器的做法。
不建议用任务延时代替定时器,因为任务延时会额外占用一个任务描述符。但是在操作系统环境下,用一个专门的任务监控状态机并且分发按键消息是非常有必要的。

阿陆 发表于 2017-3-8 16:06:17

很不错,学到了,谢谢 楼主

秋水之下 发表于 2017-5-27 15:10:38

suyong_yq 发表于 2017-3-5 00:47
是状态机+定时器的做法。
不建议用任务延时代替定时器,因为任务延时会额外占用一个任务描述符。但是在操 ...

这还有一个方法就是,用OS的软件定时器,对于还有误触发情况我们可以用STM32硬件按键滤波方法
---》STM32的定时器输入通道都有一个滤波单元,分别位于每个输入通路上(下图中的黄色框)和外部触发输入通路上(下图中的兰色框),它们的作用是滤除输入信号上的高频干扰。

http://www.eeworld.com.cn/mndz/2013/0922/article_19360.html

这个是香水城分享的

秋水之下 发表于 2017-6-1 09:23:58

appllo 发表于 2015-12-18 11:12
消息队列肯定是更好的
方法很多,基于队列也很好。不过基于队列同时相应两个按键连击好像处理就麻烦点了。

下面是我开一个按键扫描任务里面发送标志到标志组,其他任务检查标志组就可以。
void KeyTask(void *parg)
{
      OS_ERRerr;
      CPU_INT08U key;
      APP_ARG *p_arg         =         (APP_ARG *)parg;
      static LCDDAT lcd;
      
      if(OSFlagPend(p_arg->pfgrp,(OS_FLAGS)SDCardLessFlag+NoSDCardFlag,100,OS_OPT_PEND_NON_BLOCKING + OS_OPT_PEND_FLAG_SET_ANY,NULL,&err))
      {
                lcd.pic = FlashDiyLCD;lcd.period = 0;
                SysPower(CLOSE);      
      }else {
      lcd.pic = SystemNormalLCD;lcd.period = 1;
      }

      OSQPost(p_arg->pLCDQ,(void *)&lcd,sizeof(lcd),OS_OPT_POST_FIFO,&err);      
      OSTimeDlyResume(p_arg->LCDTaskTCB,&err);
      LED_B(CLOSE);
      do{OSTimeDlyHMSM(0,0,0,100,OS_OPT_TIME_DLY,&err);}
      while(GetKEYStatus(POWER));

      while(1)
      {      
                key = QueryKeyCode();
                if(key != NoKey){

                        if(key==POWER_CTL_KEY){      
                              //OSTimeDlyHMSM(0,0,PWR_KEY_TIME_DELAY,0,OS_OPT_TIME_DLY,&err);                        /*         关机延时                                        */
                              OSFlagPost(p_arg->pfgrp,BeepRunFlag,OS_OPT_POST_FLAG_SET,&err);//打开蜂鸣器
                              OSTimeDlyHMSM(0,0,0,300,OS_OPT_TIME_DLY,&err);
                              OSFlagPost(p_arg->pfgrp,BeepRunFlag,OS_OPT_POST_FLAG_CLR,&err);//关闭蜂鸣器
                              OSTimeDlyHMSM(0,0,0,300,OS_OPT_TIME_DLY,&err);      
                              OSFlagPost(p_arg->pfgrp,BeepRunFlag,OS_OPT_POST_FLAG_SET,&err);//打开蜂鸣器
                              OSTimeDlyHMSM(0,0,0,300,OS_OPT_TIME_DLY,&err);
                              OSFlagPost(p_arg->pfgrp,BeepRunFlag,OS_OPT_POST_FLAG_CLR,&err);//关闭蜂鸣器
                              GPIO_ResetBits(GPIOC, GPIO_Pin_2);//不叫      
                              
                        }else{
                              OSTimeDlyHMSM(0,0,0,KEY_TIME_DELAY,OS_OPT_TIME_DLY,&err);                                        /*         按键去抖延时                              */
                        }
               
                        if(key == QueryKeyCode())
                        {
                              lcd.period = 1;      
                              switch(key){
      
                                        case POWER_CTL_KEY:                                                                                                                                                                              
                                                if(StartADCFlag)StartADCFlag = 0;
                                                OSFlagPost(p_arg->pfgrp,PowerDownFlag,OS_OPT_POST_FLAG_SET,&err);
                                                SysPower(CLOSE);      LED_B(CLOSE);LED_G(CLOSE);
                                                lcd.pic = ShutDownFinishLCD;
                                                OSQPost(p_arg->pLCDQ,(void *)&lcd,sizeof(lcd),OS_OPT_POST_FIFO,&err);      
                                                OSTimeDlyResume(p_arg->LCDTaskTCB,&err);
                                                break;
                                       
                                        case START_RECORD_KEY:
                                                OSFlagPost(p_arg->pfgrp,StartRecordFlag,OS_OPT_POST_FLAG_SET,&err);
                                                //OSFlagPend(p_arg->pfgrp,(OS_FLAGS)StartADCCnvFlag,0,OS_OPT_PEND_BLOCKING + OS_OPT_PEND_FLAG_SET_ALL,NULL,&err);
                                                lcd.pic = RecordingLCD;
                                                OSQPost(p_arg->pLCDQ,(void *)&lcd,sizeof(lcd),OS_OPT_POST_FIFO,&err);      
                                                OSTimeDlyResume(p_arg->LCDTaskTCB,&err);
                                                OSFlagPost(p_arg->pfgrp,RecordRunFlag,OS_OPT_POST_FLAG_SET,&err);      
                                                break;
                                                
                                        case ECG_MARK_KEY:
                                                if(OSFlagPend(p_arg->pfgrp,(OS_FLAGS)RecordRunFlag,0,OS_OPT_PEND_FLAG_SET_ALL+
                                                                                                                              OS_OPT_PEND_NON_BLOCKING,NULL,&err)){      
                                                      if(OS_ERR_NONE == err){
                                                                OSFlagPost(p_arg->pfgrp,(OS_FLAGS)ECGMarkFlag,OS_OPT_POST_FLAG_SET,&err);      
                                                                lcd.pic = EcgMarkLCD;      
                                                      }
                                                }else lcd.pic = SystemNormalLCD;
                                                OSQPost(p_arg->pLCDQ,(void *)&lcd,sizeof(lcd),OS_OPT_POST_FIFO,&err);      
                                                OSTimeDlyResume(p_arg->LCDTaskTCB,&err);
                                                break;
                                                
                                        case DISPLAY_INFO_KEY:
                                                if(OSFlagPend(p_arg->pfgrp,(OS_FLAGS)StartRecordFlag,0,OS_OPT_PEND_FLAG_SET_ALL+
                                                                                                                              OS_OPT_PEND_NON_BLOCKING,NULL,&err)){      
                                                      lcd.pic = DisplayInfoLCD;                                                                                       
                                                }else lcd.pic = SystemNormalLCD;                                                                                                                              
                                                OSQPost(p_arg->pLCDQ,(void *)&lcd,sizeof(lcd),OS_OPT_POST_FIFO,&err);      
                                                OSTimeDlyResume(p_arg->LCDTaskTCB,&err);
                                                break;
                                                
                              }
                              OSTimeDlyHMSM(0,0,0,200,OS_OPT_TIME_DLY,&err);
                        }               
                }elseOSTimeDlyHMSM(0,0,0,100,OS_OPT_TIME_DLY,&err);
               
      }
}
页: 1 2 [3]
查看完整版本: FREERTOS下的按键处理方式讨论