1.8.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)
----*----*----*----*----*----*----*----*----*----*----*----
史久超
email:shijiuchao1983@163.com
tel:15999550975 微信同号
qq:157185173 经常不在线,尽量微信