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

2015-06-16 10:34:41 +08:00
 Exin
语言用的是C
有两种写法:
while(1){
delay(100);
if(press){
func();
}
}

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

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

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

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

所以delay写在前面或者后面并没有区别吧!(老师因为这个扣我分
sennes
2015-06-16 13:03:37 +08:00
@Exin 如果只是你上面那两段代码,我个人觉得在想消抖这方面是没有任何区别的。
唯一的区别是。后面那段代码,会在func()运行完之后多了个没有意义的delay
这样看的话,还是上面的好一点点
Exin
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
2015-06-16 16:31:25 +08:00
延时问题吧 按下延时一段再判断。
Exin
2015-06-16 16:57:24 +08:00
@yanyandenuonuo 那应该是两级判断,不是这种吧
yanyandenuonuo
2015-06-16 17:09:06 +08:00
@Exin 总感觉不应该是while(1),而应该是while(Press),这样解释就合理了。
linhua
2015-06-16 17:14:22 +08:00
你这应该在中断函数里吧。按键按下触发中断时,电平可能并没有一个确定的状态,即在抖动状态。需要等一会,再判断。所以delay应该放前面。放后面是不对的。就算是由按键松开触发中断的,delay也应该放前面。
Exin
2015-06-16 17:15:01 +08:00
@yanyandenuonuo 这样不好吧,而且并不能解决误触/抖动的问题
Exin
2015-06-16 17:18:52 +08:00
@linhua 在main函数,没有用中断,是简易版的功能实现
另外前后的问题我在11l说了我的理解,您看看?
linhua
2015-06-16 17:28:03 +08:00
@Exin
如果不用中断的话,应该就像14L说的是while(press)。因为第一次判断并不能确定按键是否真的按下,需要delay后,再进行一次判断。
Exin
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
2015-06-16 17:59:39 +08:00
@Exin
非while(press)版本中,第一个delay没用 。
while(press)版本可以。
哦,对,你要循环检测,那就不应该用while(press)。
为了防止按键按下一次func被多次执行,需要检测按键是否松开。建议用非while(press)版本
while(1){
if(press){
delay();
if(press){
func();
while(press); //检测是否松开按键
}
}
}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/198890

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX