第四章為面向接口的編程,本文內容包括:4.3 LED 數碼管。
4.3 LED 數碼管
>>> 4.3.1 靜態顯示
如圖4.10 所示是由2 個共陽極的LN3161BS 組成的LED 數碼管電路,R1~R8 為限流電阻,c1 和c2在內部并聯連接。如果將段選端a~dp 與位選端com0、com1 連接到AM824-Core 的PIO0_8~PIO0_15 與PIO0_17、PIO0_23,則通過程序即可控制筆段的亮滅。由于數碼管的8 個段選端全部都要經過com 口才能得到供電,因此需要增加三極管提高com 口的驅動電流,以彌補LPC824 GPIO 驅動電流的不足。當com 為低電平時三極管導通,則數碼管的c1、c2 為高電平,即選通數碼管。此時只要數碼管的任一段選端為低電平,則點亮數碼管相應的筆段。
圖4.10 LED 顯示器電路圖
MiniPort-View 數碼管模塊通過MiniPort B(排母)與AM824-core 相連,同時將其余不使用的I/O 通過MiniPort A(排針)引出,實現模塊的橫向堆疊,其對應AM824-Core 的MiniPort 接口J4的功能定義詳見圖4.11。
圖4.11 數碼管模塊實物與接口定義
“日”形數字顯示除了能夠顯示10 進制數字0~9,有時也用于顯示16 進制字母AbCdEF 或其它一些非常簡單的符號。按照二進制的計算方法,8 段顯示有256 種組合,去掉“點(dp)”的顯示,其筆段的組合為128 種(27),而數字0~9 只有10 個符號,因此要想得到我們希望的顯示符就必須對顯示段進行編碼。顯然,如果要想點亮數碼管的某一個筆段,則只需將對應的筆段置0就可以了。即輸出低電平至com0 端,同時輸出低電平至b、c 段,點亮LED 得到字符“1”。由此可見,按照數字的筆畫排列,則很容易得到10 個數字0~9 共10 個顯示字符,七段共陽數碼管10 個數字段碼表詳見表4.2。
表4.2 七段共陽極數碼管段碼表
如果以8 位數值表示段碼,當其相應位為0 時,則表示對應的段點亮。bit7~0 分別與dp~a 對應,假設bit0 為0,即點亮a。為了方便訪問,不妨將段碼存放到一個數組中。即:
AMetal 軟件包提供了熄滅所有數碼管的板級初始化函數、段碼傳送函數、位碼傳送函數和數字顯示掃描函數,其函數接口詳見程序清單4.10。
程序清單4.10 digitron0.h 接口
其中,code 為待顯示數字0~9 所對應的段碼,pos 為com0 或com1 對應的數字下標(0~1),num 為待顯示的數字0~9。當后續調用這些函數時,則只需要“#include "digitron0.h"”就可以了。比如,在com0 數碼管上顯示數字1,詳見程序清單4.11。
程序清單4.11 靜態顯示數字1 范例程序
如果讓單個數碼管循環顯示0~9,且循環的時間為1s,顯然顯示時間也是1s,那么這就是一個簡單的秒計數器,詳見程序清單4.12。
程序清單4.12 秒計數器范例程序
當你看到程序清單4.12(9)中的“i = (i + 1) % 10;”代碼時,是否有一種似曾相識的感覺呢?這行代碼是從LED 流水燈實驗中提煉出來的。如果需要倒計時呢?則將其修改為“i= ((i – 1) + 10) % 10;”。如果要從9 開始倒計數呢?那就將i 的初始值修改為9。至此已經實現了0~9 的循環顯示,能否循環顯示0~99 呢?這就是下面將要介紹的數碼管動態掃描顯示。
>>> 4.3.2 動態顯示
如果要顯示多位數字,則需將多個數碼管并接在一起使用。此時將會出現一大堆段選端的問題,比如,兩位數碼管需要2×8=16 個段選信號,而LPC824 一共才16 個I/O,無法滿足需求,同時管腳使用越多,連線也會變得越復雜。所以為避免使用過多的管腳而造成資源浪費和連線復雜,人們發明了一種動態掃描方式來實現多個數碼管的顯示。
由于數碼管的段碼是連接在一起的,那么同一時刻兩個數碼管的段碼必然是相同的,如果簡單地使2 個公共端(com)均有效來實現2 個數碼管的顯示,那么必然都會顯示相同的內容。怎么辦?分時顯示,即一段時間數碼管0 正常顯示(com0 有效,com1 無效,段碼為數碼管0 需要顯示的圖形),另外一段時間數碼管1 正常顯示(com1 有效,com0 無效,段碼為數碼管1 需要顯示的圖形)。如要顯示一個數值12?即在com0 顯示1,在com1 管顯示2,詳見程序清單4.13。
程序清單4.13 顯示數值12 范例程序
雖然在實際的操作過程中數字是輪流顯示的,但只要輪流操作的速度達到一定的范圍,那么在人眼看起來就能達到和整體顯示的效果一樣,就像我們經常看的電影技術一樣。
再細心觀察一下實驗現象可以發現,雖然顯示的數字是12,但是數碼管顯示的1 和2 都會有另外一個數字的影子。com0 顯示的是1,但也能看到2 的影子。
digitron_disp_num()就是digitron_com_sel ()和digitron_segcode_set()的一個簡單組合。其顯示過程是先傳送位碼、后傳送段碼,于是在傳送位碼和傳送段碼之間就產生了時間間隙。當新的com 端有效時,仍然還在使用此前的段碼,所以出現了短暫的錯誤現象。怎么辦?可以在這段時間內熄滅所有的數碼管,避免錯誤顯示。即:
那如何循環顯示0 ~ 59 呢?即將要顯示的數值加1,詳見程序清單4.14。
程序清單4.14 0~59 秒計數器范例程序(1)
程序還可以繼續優化嗎?現在的問題是,為了顯示一個數據,即便數據沒有改變,也必須動態掃描數碼管,否則無法顯示。首先將待顯示的數據存放到緩沖區(存儲單元),然后每隔一段時間從緩沖區讀取待顯示的數據。即:
讀緩沖區的數據實現動態掃描的函數詳見程序清單4.15。
程序清單4.15 動態掃描顯示函數
由此可見,緩沖區的段碼就是當前要顯示的數據,當再次切換時,則繼續調用該函數,則在下一個位顯示數據,以此類推。由于位選變量pos 每次都是在上一次顯示的位的基礎上變化的,因此必須將其聲明為靜態變量。顯然,只要將顯示的內容存放到緩沖區中,同時保證以一定的時間間隔(各個數碼管顯示后的延時)調用該函數,即可實現動態掃描。
為了便于復用數碼管程序,則將上述代碼全部存放到digitron1.c 文件,函數聲明放到digitron1.h 文件。其接口如下:
(1) digitron_init():初始化相關引腳;
(2) digitron_disp_scan():動態掃描函數。
由于要將待顯示內容存放到緩沖區,同時還可能訪問段碼表,因此不允許調用者直接操作其中的變量、數組等,基于此增加3 個接口函數,其分別為傳送段碼到顯示緩沖區,傳送數字0~9 到顯示緩沖區與獲取待顯示數字的段碼,其相應的代碼詳見程序清單4.16。
程序清單4.16 操作緩沖區和段碼表接口函數
如果要在com0 顯示“3.”,則可以直接這樣使用:
最后將這些接口全部聲明在程序清單4.17 所示的digitron1.h 文件中,相關的實現代碼詳見“深入淺出AMetal——動態顯示”介紹的digitron1.c 文件。
程序清單4.17 digitron1.h 文件內容
注意,在digitron1.h 接口中,已經使用digitron_disp_num_set ()和digitron_disp_code_set()替代digitron_disp_num()和digitron_disp_code(),程序清單4.18 就是通過迭代后的循環顯示0~59 秒計數器范例程序。
程序清單4.18 0~59 秒計數器范例程序(2)
>>> 4.3.3 閃爍處理
在顯示過程中,有時為了修改某位數碼管的值,需要對數碼管進行閃爍處理。在溫度采集場合,當溫度超過一定的值后,可以將顯示的溫度值做全閃處理,以引起觀察者注意。
實際上,只要讓數碼管顯示一段時間,熄滅一段時間,就產生了閃爍的效果,顯然只要直接操作緩沖區就可以了。假設每秒閃爍2 次,在個位不斷閃爍,詳見程序清單4.19。
程序清單4.19 實現秒計數器個位閃爍(1)
在程序中,1s 閃爍2 次,每次閃爍占用500ms,即顯示250ms,熄滅250ms。每秒結束后,秒計數器加1,顯然用同樣的方法也可以使秒計數器的十位閃爍,由此可見,實現閃爍僅需交替傳送正常顯示的段碼和熄滅顯示的段碼即可。由于熄滅顯示的段碼非常特殊,固定為0xFF。因此,只要在合適的時間傳送相應段碼即可,段碼傳送函數digitron_segcode_set()是在digitron_disp_scan()函數中調用的。通過修改該函數,使其在一段時間內傳送緩沖區中正常顯示的段碼,一段時間內傳送熄滅顯示的段碼0xFF,也能實現閃爍,詳見程序清單4.20。
程序清單4.20 帶閃爍功能的digitron_disp_scan()函數(1)
程序將時間分隔為500ms 的時間片,當需要閃爍時,顯示250ms,熄滅250ms,每隔5ms 調用一次digitron_disp_scan(),cnt 循環計數+1。如何讓秒計數器十位閃爍呢?直接將if(pos == 1)修改為if(pos == 0)。
顯然,數碼管的閃爍狀態和顯示狀態可以用一個標志位來表示,即0 表示顯示,1 表示閃爍,bit0 和bit1 分別表示com0 和com1 的狀態。定義一個全局變量如下:
如果bit1 閃爍,則將bit1 的初始值設置為1。即:
這樣一來,即可需要根據該變量的值來獲取需要閃爍的位,詳見程序清單4.21。顯然,只要將g_blink_flag 對應的位置1 就能實現閃爍,否則將其對應位清0。
程序清單4.21 帶閃爍功能的digitron_disp_scan()函數(2)
為了提高程序的可閱讀性,則進一步優化兩個if-else 語句,詳見程序清單4.22。
程序清單4.22 帶閃爍功能的digitron_disp_scan()函數(3)
由于g_blink_flag 變量定義在實現代碼中,不能直接將該變量提供給用戶修改,因此必須提供一個接口函數用于設定閃爍位,其相應的代碼詳見程序清單4.23。
程序清單4.23 digitron_disp_blink_set()函數
digitron_disp_blink_set()的pos 用于指定設置閃爍屬性的數碼管位置,isblink 設置閃爍屬性,值為AM_TRUE 表示閃爍,AM_FALSE 表示不需要閃爍。am_bool_t 是AMetal 在am_types.h 文件中自定義的類型,該類型數據的值只可能為AM_TRUE(真)或AM_FALSE(假),設定com0 閃爍的方法如下:
設定com0 停止閃爍的方法如下:
添加digitron_disp_blink_set()的接口函數,詳見程序清單4.24 所示的digitron1.h。
程序清單4.24 digitron1.h 文件內容
有了該接口函數后,實現閃爍就很容易了,程序清單4.25 實現了秒計數器個位閃爍。
程序清單4.25 實現秒計數器個位閃爍(2)
由此可見,與程序清單4.18 相比,僅增加了一行代碼就實現了閃爍功能,顯然接口的設計非常重要。
-
led
+關注
關注
242文章
23308瀏覽量
661595
原文標題:周立功:面向接口的編程——LED 數碼管
文章出處:【微信號:Zlgmcu7890,微信公眾號:周立功單片機】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論