1.8.1. 硬件电路

最简单的接法如下图所示:

wps1[1]

按钮接通时,IO4读到高电平(这里不用担心灌电流,因为设置为输入模式时,IO口处于高阻态,流入单片机的电流非常有限)。

1.8.2. 程序设计

按键机械触点断开、闭合时,由于触点的弹性作用,按键开关不会马上稳定接通或一下子断开,使用按键时会产生下图的带波纹信号,需要用软件消抖处理滤波。

案例描述:每按下按钮,切换板载led的状态(由点亮切换为熄灭或有熄灭切换为点亮)。

需求分析:消斗处理是新内容,可以适用使用sleep函数,其它都是旧知识。

1.8.2.1. 传统方法

最原始的处理方法是延时3ms再去读值,两次读到值才算是有效动作,代码实现可以分两步进行:

1.8.2.1.1. 获取稳定按键输入
 1 from time import sleep
 2 from machine import Pin
 3 
 4 
 5 switch=Pin(4,Pin.IN)
 6 
 7 
 8 def button_deal():
 9     print("valid btn")
10 
11 
12 while True:
13     if(switch.value()):
14         sleep(0.03)                    #延时去抖
15         if(switch.value()):
16             button_deal()              #按钮响应
17             while(switch.value()):     #等待按钮释放
18                 pass
19     else:
20         sleep(0.1)
1.8.2.1.2. LED响应

LED响应可以放在button_deal()函数中,示例两种实现方式:

a.

 1 from time import sleep
 2 from machine import Pin
 3 
 4 
 5 switch=Pin(4,Pin.IN)
 6 led = Pin(2,Pin.OUT)
 7 
 8 
 9 def button_deal():
10     led.value(1-led.value())
11     print("valid btn")
12 
13 
14 while True:
15     if(switch.value()):
16         sleep(0.03)                    #延时去抖
17         if(switch.value()):
18             button_deal()              #按钮响应
19             while(switch.value()):      #等待按钮释放
20                 pass
21     else:
22         sleep(0.1)

b.

 1 from machine import Pin
 2 from time import sleep
 3 
 4 
 5 led = Pin(2,Pin.OUT)
 6 switch = Pin(4,Pin.IN)
 7 
 8 
 9 def button_deal():
10     if(led.value() > 0):
11         led.off()
12     else:
13         led.on()
14     print("valid btn")
15 
16 
17 while True:
18     if(switch.value() > 0):
19         sleep(0.03)
20         if(switch.value()>0):
21             button_deal()
22             while switch.value():
23                 pass
24         else:
25             pass
26     else:
27         pass
28     sleep(0.1)

 

a、b两种方式的翻转led的方法略有不同,但执行效果是一样的。

1.8.2.2. 基于计数器的按钮驱动

原始方法用于教学阐述原理无可厚非,但用于实际项目有众多不便,比如是堵塞式等待按钮释放、按钮长按响应实现麻烦、多个按钮一次性遍历等等,接下来介绍一个基于计数的按钮工作模式,基本原理:每个固定的时间间隔(比如10ms)查询一下按钮的状态值,状态值为高电平则对关联计数器计数(但不能高于最大值max),状态值为低则清零关联计数器,当关联计数器的值高于阀值则认定为按钮有效操作,具体代码实现如下:

 1 from machine import Pin
 2 from time import sleep
 3 
 4 led = Pin(2,Pin.OUT)
 5 switch = Pin(4,Pin.IN)
 6 
 7 
 8 cnt = 0
 9 max_value = 10
10 valve = 5
11 
12 
13 def button_deal():
14     if(led.value() > 0):
15         led.off()
16     else:
17         led.on()
18     print("valid btn")
19 
20 
21 while True:
22     #按钮部分
23     if(switch.value()>0):
24         if(cnt < max_value):
25             cnt = cnt +1
26     else:
27         cnt = 0
28     if(cnt==valve):
29         button_deal()
30     sleep(0.01)

其他方式请自行探讨。

1.8.3. 按键模块

实际系统中,除了响应按键的按下动作,还可以响应按键的长按、hold等动作,这里做成模块以便重复使用,示例案例:

案例描述:按下数码管计数+1,长按清零,hold快速+1

需求分析:数码管驱动模块+按键驱动模块

按键模块源代码如下:

 1 from machine import Pin
 2 
 3 class BUTTON:
 4     def __init__(self,\
 5                  pin,\
 6                  pressCallBack,\
 7                  pressed_valve=3,\
 8                  long_valve=50,\
 9                  holding_valve=99,\
10                  longCallBack=None,\
11                  holdCallBack=None):
12         self.btn = Pin(pin,Pin.IN)
13         self.pressCallBack = pressCallBack
14         self.longCallBack = longCallBack
15         self.holdCallBack = holdCallBack
16         self.pressed_valve = pressed_valve
17         self.long_valve = long_valve
18         self.holding_valve = holding_valve
19         self.counter = 0
20         self.holding_counter = 0
21         self.current_state = "invalid"
22 
23     def cycle(self):
24         if self.btn.value():
25             if self.counter < self.holding_valve:
26                 self.counter = self.counter + 1
27             else:
28                 if self.holding_counter < self.pressed_valve*10:
29                     self.holding_counter = self.holding_counter + 1
30                 else:
31                     self.holding_counter = 0
32                     self.holdCallBack()
33         else:
34             if self.current_state == "down":
35                 self.pressCallBack()
36             elif (self.current_state == "long") and (self.counter < self.holding_valve):
37                 self.longCallBack()
38             else:
39                 pass
40             self.counter = 0
41             self.holding_counter = 0
42             self.current_state = "invalid"
43         if self.counter == self.pressed_valve:
44             self.current_state="down"
45         elif self.counter == self.long_valve:
46             self.current_state="long"
47         else:
48             pass

 

主程序源代码:

 1 from time import sleep,sleep_ms
 2 from CADT import digitalCube2
 3 from button import BUTTON
 4 from machine import Pin
 5 
 6 counter = 0
 7 disp = digitalCube2(15,4,5,18,19,21,22,23,25,33)
 8 led = Pin(2,Pin.OUT)
 9 
10 def btnDeal():
11     global counter
12     print("btn down")
13     counter = counter +1
14     disp.updateDisplay(counter)
15 
16 def longBtnDeal():
17     global counter
18     led.value(1-led.value())
19     counter = 0
20     disp.updateDisplay(counter)
21 
22 btn = BUTTON(12,btnDeal,longCallBack=longBtnDeal,holdCallBack=btnDeal)
23 
24 #循环计数器
25 i = 0
26 
27 disp.updateDisplay(counter)
28 
29 while True:
30     i = i+1
31     if(i>999):
32         i=0
33     if not (i%10):
34         btn.cycle()
35     disp.display()
36     sleep(0.001)

 

posted on 2022-07-24 10:59  史久超  阅读(82)  评论(0编辑  收藏  举报
知识改变命运