在電路設計中,我們經常需要讀取外部的電平信號。比如,在項目中,我們需要通過按鍵來輸入一些數據,那么就需要檢測按鍵是否被按下。電平分為高電平讀取和低電平讀取,讀取高電平,需要設置IO為下拉電阻輸入模式,反之,設置IO為上拉電阻輸入模式。
S4按下時,單片機IO為高電平,S1-S3按下時,為低電平。我們設置S1為上拉輸入模式,S4為下拉輸入模式。本節使用按鍵實現2個功能:
S1短按一次,LED2點亮,S1再短按一次,LED2熄滅。S1長按,LED1點亮,S1再長按,LED1熄滅。這種方式可以用來實現短按調節菜單,長按保存參數。
S4短按一次,LED4點亮,S4再短按一次,LED4熄滅。S4長按且不松手,LED4閃爍。這種方式可以用來實現短按調節數字,長按快速調節數字。在下一節,我們講解數碼管數字顯示時,再來實現數字慢調和快調這個功能。下圖是程序的大概流程思路以及框架:
關于IO輸入輸出初始化,上一節講過如何配置。這里按鍵設置上拉輸入和下拉輸入,LED設置推挽低速輸出。一般來說,我們會把應用代碼寫在單獨的一個文件里,比如按鍵檢測就是KEY.c,然后其他文件用到的函數和宏定義,可以直接寫在對應的頭文件里KEY.h。在哪個文件里使用,就在該文件里include頭文件即可。每個外設電路都由一組C文件和H文件組成,一般來說,在復雜的項目中,在USER.c文件里調用外設函數編寫用戶程序,在主函數里調用用戶函數即可。下圖就是一個按鍵的頭文件。
下圖列出了一些按鍵檢測的核心代碼,KEY.c部分代碼:
ScanKey()函數中的if語句是用來判斷鍵值是否變化的,如果鍵值變化,則執行按鍵處理函數keyDeal();
按鍵鍵值讀取的思路:while語句每循環一次所需時間是已知的,假設是100us,按鍵在被按下的過程中,IO的電平是劇烈變化的,只有完全按下時,IO的電平才會穩定。因此,當檢測到低電平時,開始計數,每100us檢測一次,假設檢測了100次都是低電平,那么就可以確定按鍵真的被按下了。這里千萬別采用長延時,防止程序被堵塞,一直空等待。
有的人是這樣設計的,當檢測到低電平時,就開始延遲100ms,然后再次檢測到低電平,就認為按鍵被按下一次。這種方式是不合理的,在這100ms延時期間,CPU什么也沒干,一直在那空運行,以至于其他程序無法被執行。而我們現在采用的策略是,while循環體里一般會有一些程序要被執行,這些程序執行是需要花時間的,那么循環一次花的時間,乘以循環次數,就可以達到延遲的目的。這樣做,既可以延遲,也不影響其他程序執行。下面列出一些按鍵檢測的核心代碼。
關于長按,短按,是根據不同的循環次數來區分的。當達到長循環次數時,就認為長按,在鍵值上加上長按標志。如果松手后,循環次數沒有達到長按次數,就認為是短按。如果檢測到長按,就在長按執行代碼里,設置另一個變量,每循環幾次就執行數字遞增或者遞減。這就是長按快速計數的原理。
如果長按用來實現數據保存,那么,就直接在長按執行代碼里設置保存標志位或者直接保存數據。這里KEY4按鍵長按LED閃爍是在按鍵檢測函數里直接執行的,而短按是在鍵值處理函數里執行的。之所以這么做,是因為按鍵長按不松手,鍵值一直不變,按鍵處理函數只會被執行一次,請看前文的ScanKey函數。KEY1長按,短按都是在鍵值處理函數里執行的。
在按鍵處理函數中,首先分離出長按標志位,然后根據鍵值去匹配是哪個按鍵被按下。在鍵值處理代碼段里,根據長按標志位來判斷執行短按操作還是長按操作。
-
上拉電阻
+關注
關注
5文章
363瀏覽量
30734 -
下拉電阻
+關注
關注
4文章
147瀏覽量
20595 -
led燈
+關注
關注
22文章
1592瀏覽量
108419 -
STM32單片機
+關注
關注
59文章
549瀏覽量
58823
發布評論請先 登錄
相關推薦
評論