打印

关于嵌入式系统编程中的实时性问题

[复制链接]
3008|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
linuo|  楼主 | 2011-9-8 10:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请教各位前辈及老师:在入门级的单片机与嵌入式系统书籍中,以按键扫描检测程序为例,我们经常会看到这样的程序实现方法:
#define K1 P0_4
#define K2 P0_5
uchar KeyScan(void)
{
  if(K1 == 0)
  {
    Delay(100);
    if(K1 == 0)
    {
      while(!K1);
      return(1);
    }
  };
  if(K2 == 0)
  {
    Delay(100);
    if(K2 == 0)
    {
      while(!K2);
      return(2);
    }
  };
  return(0);
}

我的问题:这样的程序实现能保证系统对其它任务的实时响应(执行)么?比如当一直按住K1按键不放开的话,程序就一直在 while(!K1);处循环,是这样么?是这样的话系统如何有时间执行其它任务(至少对于前后台系统是这样)?另外:如果整个应用软件是基于嵌入式操作系统开发的话,是不是这种按键检测程序写法就是可行的?即不用考虑上述对其它任务的响应实时性问题,因为OS会在按键检测超时强制将该任务挂起?是这样么?
急盼高手解疑,谢谢!

相关帖子

沙发
lixiaoxu2meng| | 2011-9-8 10:31 | 只看该作者
嵌入式中 用系统延时不会出现这种问题  再有按键检测有很多方法 这种不太好

使用特权

评论回复
板凳
linuo|  楼主 | 2011-9-8 10:40 | 只看该作者
首先谢谢lixiaoxu2meng的解答。这种按键检测方法是很多入门书籍及当前在高校教科书中最常见的,还是希望大家能就我的问题给出明确解答,先谢谢各位了!

使用特权

评论回复
地板
linuo|  楼主 | 2011-9-8 16:05 | 只看该作者
期待高手赐教!等待中... ...

使用特权

评论回复
5
delin17| | 2011-9-9 08:52 | 只看该作者
正常产品中,没有谁会用这个按键处理,写书的人太不负责了

使用特权

评论回复
6
linuo|  楼主 | 2011-9-9 09:16 | 只看该作者
谢谢delin17的回复。在目前很多高校的实验指导书提供的例程中,这种按键检测方法是出现最多的,也许是为了让初学者好理解。但正象delin17所说,“在正常产品中,没有人会用这样的按键处理”,至少在单片机前后台方式写的程序中,这种按键检测方式肯定不可取(当按住按键不放开时,系统将只能对有关中断程序进行相应和执行,而后台中的任何其他任务都不可能再有机会得到运行)。还是那个问题:如果这种按键检测程序写法,是在某个基于嵌入式操作系统的软件中运行,是否就不存在上述问题?(即这种按键检测方式也不会独占CPU)。仍旧期待高人指点!

使用特权

评论回复
7
delin17| | 2011-9-9 11:31 | 只看该作者
会不会独占CPU,看你任务的优先级,
按键不放,会导致低你优先级的任务无法运行。

使用特权

评论回复
8
linuo|  楼主 | 2011-9-28 15:17 | 只看该作者
希望各位专家老师继续给出更详细解答,深表感谢!

使用特权

评论回复
9
wenhenshi| | 2011-10-17 14:08 | 只看该作者
按键做成以单独任务,只检测键值,做一个循环缓冲区然后依次存储起来来,使用按键的的程序去取

使用特权

评论回复
10
adofu2008| | 2011-10-17 20:30 | 只看该作者
加个按键去抖芯片搞定完,何毕搞得这么麻烦!

使用特权

评论回复
11
sc_hqzhang| | 2011-10-17 20:52 | 只看该作者
这是最简单的实现,不用考虑其他任务,默认只有检测到按键后才执行其他任务!

使用特权

评论回复
12
linuo|  楼主 | 2011-10-20 15:50 | 只看该作者
感谢wenhenshi  adofu2008 sc_hqzhang 三位继续关注此贴!

使用特权

评论回复
13
yxwsz| | 2011-10-23 23:53 | 只看该作者
给大家发个代码(以前写按键处理程序就是这样的思路):

//按键去抖动时间
//测试去抖动的方法是将该参数设置为较大的值,比如5秒钟时间
//连续按键,只有间隔时间大于5秒情况下扫描程序才可以检测到有效按键输入
//连续按键,间隔时间小于5秒情况下扫描程序不可以检测到有效按键输入
#define KEY_DEBOUNCE_TIMEOUT        20

static unsigned int key_port, key_port_pre;
static unsigned int key_value , key_bit;
static unsigned int key_debounce_timer;

//从端口中读取按键值
//read key port
unsigned int key_get_port()
{
}

//
// 在主程序循环中调用该函数
// 去抖动后,有变化的按键位存放在key_bit中
// 使用后需要将key_bit清除
void key_scan()
{
        key_port = key_get_port();
        if(key_port != key_port_pre)
        {
                key_port_pre = key_port;
                key_debounce_timer = 0;
        }
        else
        {
                //key input is debounced
                if(key_debounce_timer > KEY_DEBOUNCE_TIMEOUT)
                {
                        if(key_port != key_value)
                        {
                                key_bit = key_port ^ key_value;
                        }
                        key_value = key_port;
                }
        }
}

//设置一个定时器中断,中断时间为1毫秒
//set up time with interval of 1 milisecond
void timer_isr()
{
        key_debounce_timer ++;
}

使用特权

评论回复
14
linuo|  楼主 | 2011-10-25 09:48 | 只看该作者
感谢YXWSZ的发帖,给出了一种按键检测的思路和代码。但仍感觉没有从软件系统角度回答我最初的问题。再次明确一下我的问题:请大家从基于裸机编程(即常说的前后台软件系统架构)和基于嵌入式OS两种开发架构方面探讨按键检测程序的开发问题!

使用特权

评论回复
15
yxwsz| | 2011-10-25 22:42 | 只看该作者
如果是裸机编程,就是使用我前面贴的那种代码,把按键扫描放到程序主循环里面去执行就可以了;

从系统应用程序(比如基于LINUX, WINDOW CE)的角度来看,应用程序不应该去处理这些按键扫描任务,这些事情应该由驱动程序去实现; 如果是使用这类系统,建议是如果应用处理器没有按键扫描模块,就外加一个按键处理芯片或者MCU,专门做按键扫描及处理。

使用特权

评论回复
16
jinyuewei| | 2012-5-18 20:38 | 只看该作者
学习了 呵呵 最近也在考虑这个问题

使用特权

评论回复
17
madcool| | 2012-5-19 12:56 | 只看该作者
根据楼主的描述,楼主的程序片段有可能阻塞调用它的上下文,如果在前后台系统中,函数片在主应用程序中被调用,中断例程可以被正常执行,而主应用程序会一直阻塞,至于能不能用这段程序主要还是要结合应用场景。如果系统部署了嵌入式操作系统的话,程序片段出现在线程中的话要注意线程采用的调度方式,比如在基于优先级的调度系统中,它会阻塞其他低优先级的线程,如果是基于时间片轮转的话,当进程的时间片到了OS也会强制进程释放CPU从而使其他优先级更低的进程得到CPU时间。具体采用什么做法需要结合你的应用场景,你的系统环境如硬件、OS等具体考虑,而且始终需要关注程序在何种上下文被调用

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
linuo + 1 很给力!
18
hotyong| | 2012-5-22 12:47 | 只看该作者
最简单的方法,就是在while中加入Delay(x);,当然这个函数一定要是系统延时,不能由for构成的。

#define K1 P0_4
#define K2 P0_5
uchar KeyScan(void)
{
  if(K1 == 0)
  {
    Delay(100);
    if(K1 == 0)
    {
      while(!K1)Delay(10);
      return(1);
    }
  };
  if(K2 == 0)
  {
    Delay(100);
    if(K2 == 0)
    {
      while(!K2)Delay(10);
      return(2);
    }
  };
  return(0);
}

使用特权

评论回复
19
linuo|  楼主 | 2013-3-8 10:51 | 只看该作者
感谢大家所有的回复,尤其是madcool的回答真的让我获益匪浅。再次感谢大家!

使用特权

评论回复
20
john_lee| | 2013-3-9 16:53 | 只看该作者
直接在OS的节拍中断(TICK)例程中扫描按键。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

44

帖子

0

粉丝