終極原理為你而來 ——mini1608電子時鐘(原理篇)
作者 杜洋
今天陽光明媚,今夜多云轉晴,《無線電》的老地方,杜洋靜靜的等候。一個月前,我心潮澎湃的把我最新設計的mini1608電子時鐘與你分享。精簡的制作、漂亮的外觀、強大的功能都深深的吸引了你。你熱情高漲,興沖沖炮制了一個,結果大獲成功。欣喜之后卻變得迷惑起來,這是認真研究、深入思考的結果,當你從制作層面往技術原理層面思考的時候,就會遇見問題,有所不解。欣悉8月杜洋有約,促膝長談mini1608的技術原理,帶你從制作到創作,全面了解并徹底使用它們,為你的DIY事業創造新鮮樂趣。
自力更生——什么是I/O接口的推挽工作方式
上文提到STC11F32XE的每一個I/O接口都有4種工作方式,其中包括推挽輸出。推挽輸出是什么呢?對于沒有使用過增強型8051單片機的朋友,這個名詞是有些陌生的。傳統8051單片機的I/O接口只可以作為標準雙向輸入/輸出接口,如果用其來驅動LED則只能用灌電流的方式或是用三極管外擴驅動電路。灌電流方式是將LED正極接在VCC上,負極接在I/O接口上,當I/O接口為高電平時LED兩極的電平相同,沒有電流,LED為熄滅狀態。當I/O接口為低電平時,電流從VCC流入I/O接口,LED點亮。當把LED正極接在I/O接口,負極接在GND,將I/O接口置于高電平時,LED會點亮,但因為I/O接口上拉能力不足而使亮度不理想。推挽工作方式就是具有強上拉能力的工作方式,它可以實現高電平驅動LED。驚喜出現了,把LED正負極分別接在兩個I/O接口上,然后設置正極的I/O接口為推挽輸出,負極的I/O接口為標準雙向灌電流輸入,結果會怎么樣呢?非常好,我們可以直接用I/O接口驅動LED而不需要VCC和GND。LED點陣屏就是多個LED的陣列連接,只要把LED點陣屏的所有引腳接在I/O接口上,然后根據LED點陣屏的引腳定義,將對應正極的I/O接口設置成推挽,將對應負極的I/O接口設置成標準雙向輸入,余下的就是把將要點亮的LED點陣屏上的點所對應的行列線分別給予高低電平,那么一切就盡在掌握之中。
P1 口設定 (P1.7,P1.6,P1.5,P1.4,P1.3,P1.2,P1.1,P1.0)
(表)
有朋友會問了,推挽工作方式這么好,我們在編程時要如何設置呢?這個問題問得好,其實設置I/O接口的工作方式和設置I/O接口的電平狀態一樣簡單。我們以C語言編程為例,首先要加載STC11Fxx.h的頭文件,因為STC單片機官方給出的頭文件中有I/O接口工作狀態設置的定義。可以在宏晶公司STC單片機的官方網站上找到頭文件,然后把下載到的頭文件放到C:\Keil\C51\INC文件夾里面。下一步就是在程序開始處聲明這個頭文件。注意聲明中的文件名要和INC文件夾中存放的頭文件的名字相同。
#include <STC11Fxx.h> //聲明STC單片機頭文件
P1M0 = 0x01; //設置P1接口工作方式
P1M1 = 0x04; //設置P1接口工作方式
P4M0 = 0x02; //設置P3接口工作方式
P4M1 = 0xf4; //設置P3接口工作方式
P4SW = 0xff; //設置單片機功能引腳作為P4接口使用
例如我們對I/O接口的工作方式做出如下設置:
P1M0 = 0x09; //0000 1001
P1M1 = 0x05; //0000 0101
即表示P1接口中,P1.7到P1.4為標準雙向輸入/輸出接口,P1.3為推挽工作輸出接口,P1.2為高阻態輸入接口,P1.1為標準雙向輸入/輸出接口,P1.0為開漏狀態接口。具體設置可以對照STC單片機的SFR數據表。注意P4SW寄存器對應位設置為1時,則此引腳才可作為P4接口使用。
STC11/10xx 系列8051 單片機 I/O 口 特殊功能寄存器 Port SFRs
(表)
權宜之計——為什么要用逐點掃描
通常我們驅動LED點陣屏都會使用一種習慣的方法,那就是遂列掃描法。把一組I/O接口定義為行,然后依次選通每一列,在選通某列時對應地送入這一列所需要的行數據。也就是說在同一時間里會有至多一列LED被點亮。對于mini1608的電路設計來說,這是不可能實現的。因為數據手冊告訴我們,I/O接口的推挽工作方式也并非萬能。一般情況下推挽工作方式所能輸出的最大電流是20mA,而標準雙向輸入/輸出工作方式也只能灌入20mA的電流。同時,整個單片機在同一時間內所能承受的最大電流為60mA,超過這個電流值,單片機就會有生命危險。遂列掃描時,每一個LED都會消耗10~20mA的電流,讓I/O接口同時驅動8個LED,結果只有死路一條。為了解決這個問題,我們只好采用遂點掃描方式,即在同一時間內只有一個LED被點亮。這樣做既保證了單片機和LED的身體健康,讓單片機I/O接口的推挽能力恰好達到要求,同時又不會出現遂列掃描時LED顯示亮度不均的問題。從這一點上看,這并非被迫之選,而是決佳之計。
技術嚴謹又注意細節的愛好者朋友可能會發現整個電路設計中沒有用到任何電阻,自然也就沒有LED必配的限流電阻。限流電阻是在電路電壓大于LED驅動電壓時,為保持LED在正常工作電流范圍內而使用的。現在整個電路的電壓為5V,mini1608公然省略了限流電路是否會對電路有一定影響呢?我在設計時也認真考慮并做了一些實驗,結果令人愉快。使用I/O接口的推挽方式,并在軟件上使用遂點掃描,不加限流電阻依然可以保證LED工作在正常電流范圍之內。有驚無險,暢通無阻。
層出不窮——怎樣實現LED點陣屏多級顯示亮度
當我第一次把我設計的漸明漸暗LED燈程序演示給一個同學看的時候,他的感覺是好神奇。他奇怪為什么單片機只能輸出高、低電平,怎么會使LED產生漸變的亮度呢?他對單片機性能的了解確實值得肯定,但他忘記了眼睛的雙重間諜身份。當我們以1分鐘為一個周期,在1分鐘內讓LED亮1分鐘,就也是一直亮著,LED的亮度就是最大的亮度。當我們在1分鐘內只讓LED在前30秒鐘點亮,后30秒鐘熄滅,那么LED的亮度就只有原來亮度的一半。當我們在1分鐘內只讓LED在前6秒鐘點亮,那么LED的亮度就只有還來亮度的十分之一,這就是亮度控制的基本原理。現在該有人暴跳如雷地說我騙人了,因為地球人都知道我上面說的現象實際上只會讓LED慢慢地亮熄閃爍,怎么會是亮度的變化呢?是的,如果以1分鐘為一個周期,LED確實只會閃爍,這僅是為了方便大家理解。當我們以1毫秒為一個周期時候,就是我們見證奇跡的時刻,因為我們眼睛的視覺暫留特性,我們已經看不出LED的閃爍,我們的眼睛親眼見證了LED亮度真的不同了。眼睛騙了你,善意的謊言。那么讓單片機控制亮度變化的程序應該怎么寫呢?我反問單片機在1分鐘之內前6秒點亮,后54秒熄滅的程序應該怎么寫呢?問題自有答案。
(圖片)
一箭雙雕——如何用LED點陣屏實現測光
《無線電》2009年第4期的《LED進化史》有一段介紹LED的反向應用,即把LED當作光電二極管使用。當時我只是引用了一個外國網站的資料。從那之后我就一直關注著LED的反向應用,不久前的實驗拉近了我們的距離,將LED反向應用的始末完全呈現在我的眼前。在光線不同的情況下,LED的反向電阻會有所變化,光線強時電阻值變小,光線弱時電阻值變大。如果利用AD轉換功能可以讀出電阻值變化的每一個細節,但我在mini1608上沒有使用AD轉換,而是利用了單片機I/O接口的高阻態輸入功能。Mini1608的LED點陣顯示屏在正常情況下,正極為推挽輸出,負極為標準雙向接口,上文已經講過。當我們要檢測環境光線的時候我們就將LED負極的I/O接口變為推挽高電平輸出,給LED一個反向電壓。LED正極的I/O接口變為高阻態輸入。當環境光線強的時候,LED的反向電阻值變小,LED正極的電壓會變高,當高過I/O接口高電平的最小值時(一般為2V),則單片機識別為高電平輸入。當環境光線弱時,LED反向電阻值變大,LED正極的電壓會變低,當低于I/O接口高電平的最小值時,單片機識別為低電平輸入。雖然只有兩種狀態的判斷,但對于mini1608觀察白天還是晚上已經足夠了。如果想判斷光線強弱的更多種狀態,可以通過讀取反向LED電平變化的時間,如果電平變化時間短,則說明光線強,電平變化時間長,則說明光線弱,完全不需要AD就可以完成測光。白天環境光線強,LED點陣屏本身要亮一些才能看得清楚。晚上環境光線弱,LED點陣屏要變得暗一些才不會讓起夜上廁所的你感覺刺眼。Mini1608變聰明了,也更體貼了。我還會繼續研究LED反向應用的技術,并會在《無線電》雜志上一一與大家分享。
LED測光原理
各大電子技術類雜志都不把源程序代碼算做稿費的一部分,這樣做可以使作者不愿意公開源程序代碼,是一種變向激勵讀者獨立創熱情的方法,對此我也表示支持。在此僅提供HEX文件供感興趣的愛好者朋友仿制。如果你有能力、也有熱情編寫程序,按照上文說明的原理去思考,很快你便有了思路甚至方案。無論是白天還是夜晚,當你閱讀本文的時候,我正端坐在電腦前,面對上千條的程序代碼,對mini1608進行升級。我有熱情和勇氣與mini1608并肩做戰,實現每種奇妙的功能,完成每個不可完成的任務。Mini1608會不會是LED點陣屏電子時鐘的終結者?我們拭目以待。
源碼與詳細制作過程下載:http://www.zg4o1577.cn/bbs/dpj-92154-1.html
|