V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Exin
V2EX  ›  问与答

在嵌入式硬件上编程的问题

  •  
  •   Exin · 2015-06-16 10:34:41 +08:00 · 3101 次点击
    这是一个创建于 3460 天前的主题,其中的信息可能已经有所发展或是发生改变。
    语言用的是C
    有两种写法:
    while(1){
    delay(100);
    if(press){
    func();
    }
    }

    while(1){
    if(press){
    func();
    }
    delay(100);
    }

    press是硬件按钮输入,按下为True。
    老师表示下面的写法不行,不能去颤。
    我不能理解,上下在执行时是一样的啊,求大神解释。
    21 条回复    2015-06-17 09:20:30 +08:00
    sennes
        1
    sennes  
       2015-06-16 11:00:53 +08:00
    按照你这个代码,我觉得是一样的。
    而且单单一个delay(100),好像没有消抖的作用?
    dacapoday
        2
    dacapoday  
       2015-06-16 11:06:10 +08:00 via Android
    跨号没弄错吗,这两个没区别啊?
    轮询法,去抖得弄个二级判断吧间?那个 press是边沿检测还是电平检测?
    按键什么的,弄中断触发吧
    lincanbin
        3
    lincanbin  
       2015-06-16 11:09:12 +08:00
    没区别吧?我一般用后者消除抖动,没发现有什么异常。
    你最好实际烧进去试试。
    另外也推荐中断触发。
    Exin
        4
    Exin  
    OP
       2015-06-16 11:23:51 +08:00
    @sennes 按老师的说法,这么个delay写在第一行就能消抖……
    @dacapoday @lincanbin 我也觉得需要二级判断。我这个按键状态简单地通过寄存器值获取了,使用中断的话,在除颤这个方面有区别吗?
    dacapoday
        5
    dacapoday  
       2015-06-16 11:39:33 +08:00 via Android
    @Exin 开单步调试,你while(1)里的汇编指令手动走一遍,看这两能有什么区别, 接示波器看,你就知道为啥要消抖了。
    Exin
        6
    Exin  
    OP
       2015-06-16 12:07:21 +08:00
    @dacapoday 考试结束了,没办法接触设备了……能简单讲讲吗
    dacapoday
        7
    dacapoday  
       2015-06-16 12:26:05 +08:00   ❤️ 1
    考试的话,听老师的吧,毕竟分是老师给的,应试的话应该彻底远离实际操作。
    sennes
        8
    sennes  
       2015-06-16 12:44:58 +08:00   ❤️ 1
    就算是按键触发也有很多种类型诶(我就讲实际的,可能和你考试的场景不一样)
    就说几种吧
    1. 按下、然后松手才执行func()
    2. 确定真的按下按钮,就执行func()
    一般来说这种情况会把按键做成一个“单脉冲触发” 最后按键的波形应该就是 ___|---|____
    3. 按下、并且按住,会连续触发func() <-比如键盘打字

    然后对应实际的每种场景,这个按键判断、消抖的代码都不太一样。
    但是基本上来说,都是判断、然后一个delay一段时间(这段时间正是按键抖动的时间)、然后再判断(这时候才能确定"press"不是由抖动引起的),然后再执行func()

    您的代码中只有一次判断、一次delay。总觉得,一定程度上可以做到消抖,但好像不是那么保险。
    有条件的话,买硬件来试试。
    Exin
        9
    Exin  
    OP
       2015-06-16 12:56:17 +08:00
    @sennes 好详细,非常感谢!

    所以delay写在前面或者后面并没有区别吧!(老师因为这个扣我分
    sennes
        10
    sennes  
       2015-06-16 13:03:37 +08:00
    @Exin 如果只是你上面那两段代码,我个人觉得在想消抖这方面是没有任何区别的。
    唯一的区别是。后面那段代码,会在func()运行完之后多了个没有意义的delay
    这样看的话,还是上面的好一点点
    Exin
        11
    Exin  
    OP
       2015-06-16 13:12:49 +08:00
    @sennes
    循环体展开后上面应该是这样子:("1?"表示while循环条件判断)
    delay //比下面多这一句
    if(){func();}
    1?
    delay
    if(){func();}
    1?
    delay
    if(){func();}
    1?
    delay
    ...

    下面的是
    if(){func();}
    delay
    1?
    if(){func();}
    delay
    1?
    if(){func();}
    delay
    1?
    ...


    当while走完一个周期以上,可以认为上下两种情况中if(){func();}都是被delay包裹的,区别在于if判断与while判断的先后而已。所以在除颤方面应该是一样的。所以不能说下面的delay相比于上面的没有意义吧……
    yanyandenuonuo
        12
    yanyandenuonuo  
       2015-06-16 16:31:25 +08:00
    延时问题吧 按下延时一段再判断。
    Exin
        13
    Exin  
    OP
       2015-06-16 16:57:24 +08:00
    @yanyandenuonuo 那应该是两级判断,不是这种吧
    yanyandenuonuo
        14
    yanyandenuonuo  
       2015-06-16 17:09:06 +08:00
    @Exin 总感觉不应该是while(1),而应该是while(Press),这样解释就合理了。
    linhua
        15
    linhua  
       2015-06-16 17:14:22 +08:00
    你这应该在中断函数里吧。按键按下触发中断时,电平可能并没有一个确定的状态,即在抖动状态。需要等一会,再判断。所以delay应该放前面。放后面是不对的。就算是由按键松开触发中断的,delay也应该放前面。
    Exin
        16
    Exin  
    OP
       2015-06-16 17:15:01 +08:00
    @yanyandenuonuo 这样不好吧,而且并不能解决误触/抖动的问题
    Exin
        17
    Exin  
    OP
       2015-06-16 17:18:52 +08:00
    @linhua 在main函数,没有用中断,是简易版的功能实现
    另外前后的问题我在11l说了我的理解,您看看?
    linhua
        18
    linhua  
       2015-06-16 17:28:03 +08:00
    @Exin
    如果不用中断的话,应该就像14L说的是while(press)。因为第一次判断并不能确定按键是否真的按下,需要delay后,再进行一次判断。
    Exin
        19
    Exin  
    OP
       2015-06-16 17:42:43 +08:00
    @linhua
    非while(press)版本:
    while(1){
    delay();
    if(press){
    delay();
    if(press){
    func();
    }
    }
    }

    while(press)版本:
    while(1){
    while(press){
    delay();
    if(!press)break;
    else func();
    }
    }

    这样吗?
    linhua
        20
    linhua  
       2015-06-16 17:59:39 +08:00   ❤️ 1
    @Exin
    非while(press)版本中,第一个delay没用 。
    while(press)版本可以。
    哦,对,你要循环检测,那就不应该用while(press)。
    为了防止按键按下一次func被多次执行,需要检测按键是否松开。建议用非while(press)版本
    while(1){
    if(press){
    delay();
    if(press){
    func();
    while(press); //检测是否松开按键
    }
    }
    }
    yanyandenuonuo
        21
    yanyandenuonuo  
       2015-06-17 09:20:30 +08:00
    @Exin 抖动 是可以解决的,误触就。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4999 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 03:56 · PVG 11:56 · LAX 19:56 · JFK 22:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.