本文隸屬於AVR單片機教程系列。html
很久沒寫這個系列了。今天講講旋轉編碼器。網絡
旋轉編碼器好像不是單片機玩家很經常使用的器件,可是咱們的開發板上有,緣由以下:函數
旋轉編碼器挺好用的。電位器能旋轉的角度有限,旋轉編碼器能夠無限圈旋轉;旋轉時不連續,有卡點,適合對應離散數據。ui
開發板上選用的旋轉編碼器,使用起來簡單、方便。編碼
原本旁邊的電位器(旋鈕,之後會講)一枝獨秀,挺孤單的,我就配一個高度大體相同的旋轉編碼器陪伴它。code
今天我想寫旋轉編碼器,因而在網絡上搜索了一下,相關資料不多。最基本地,旋轉編碼器的做用是將角位移、角速度等機械量轉換爲電信號。本文不求成爲旋轉編碼器的百科全書,但會把 觸點電刷式 增量式 旋轉編碼器的原理講清楚。這裏出現了兩個定語,是對類別的限定;關於旋轉編碼器的分類,請自行百度。htm
開發板上的旋轉編碼器是從淘寶買的,淘寶商家提供了資料,這是本講的主題。爲避免廣告嫌疑,我不能放連接上來,因此我就把它轉換成圖片放在文章裏(請在新頁面中查看):blog
咱們從旋轉編碼器的原理開始。旋轉編碼器的內部是觸點與電刷,能夠看做按鍵:當二者接觸時,開關閉合;反之斷開。實際上它們的本質是同樣的。在旋轉時,按鍵會週期性地閉合、斷開;若是一端接地,另外一端接上拉電阻,就會有周期性高、低電平的脈衝信號產生。咱們使用的旋轉編碼器每轉過一圈會輸出24個脈衝。教程
經過對脈衝進行計數,能夠知道編碼器轉過的角度。若是無論方向,測量角度或角加速度等,用一個輸出就夠了。可是若是考慮方向,不管是順時針仍是逆時針轉動,電平都是「高低高低高……」。爲了得到方向的信息,須要使用兩個輸出,它們的相位相差90°,如圖所示:圖片
A和B是兩個輸出端,C端接地。當程序檢測到A端由高電平變爲低電平時(方法在按鍵那裏講過了),若是檢測到B端是高電平(這就更簡單了),那就是順時針旋轉;若是是低電平,那就是逆時針旋轉。實際上不必定要檢測A端的降低沿,只要按照這張圖來,怎麼都對。
庫函數使用的檢測方法是:A、B端由低低變爲高低時,判爲順時針轉過一格;由低低變爲低高時,判爲逆時針轉過一格。這不是最好的方法(你能夠想一下怎樣改進,可是不要低估它的難度),但從實際使用上來看,只要用戶不故意在兩個卡點之間扭來扭去,這種方法是能夠勝任的。
咱們寫一個用旋轉編碼器控制數碼管顯示數字的程序,也能夠理解爲對旋轉編碼器進行計數並用數碼管顯示。旋轉編碼器A和B端分別鏈接端口4和5,數碼管鏈接6和7。程序的思路是:每隔一毫秒調用rotary_rotated
(它和button_pressed
函數相似——若是你還記得的話)檢測編碼器是否被轉動以及轉動的方向,並根據方向對計數器變量num
進行增減。(爲何讓num
爲uint8_t
類型?)爲了凸顯旋轉編碼器的主題,數碼管就用segment_auto
來解決了。
#include <ee1/delay.h> #include <ee1/rotary.h> #include <ee1/segment.h> int main() { rotary_init(PIN_4, PIN_5); segment_init(PIN_6, PIN_7); segment_auto(); uint8_t num = 0; while (1) { switch (rotary_rotated()) { case ROTARY_CW: ++num; break; case ROTARY_ACW: --num; break; default: break; } segment_hex(num); delay(1); } }
注意相鄰卡點之間擠了4個AB端口的狀態,所以延時不能過長。你能夠試試更長的間隔。
做業:對於旋轉編碼器,直接檢測IO口電平;對於數碼管,使用「原始」的動態掃描,即不要用segment_auto()
;重寫樣例。(提示:你能夠分別完成兩個要求,而後合併。)