本文為明德?lián)P原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處!
呼吸燈是指燈光在微電腦的控制之下完成由亮到暗的逐漸變化,感覺好像是人在呼吸。其廣泛應(yīng)用于手機(jī)、電腦等電子產(chǎn)品之上,并成為各大品牌新款手機(jī)的賣點(diǎn)之一,起到一個(gè)通知提醒的作用。每個(gè)人都應(yīng)該使用過帶有呼吸燈的手機(jī),看著燈光由暗淡逐漸一點(diǎn)點(diǎn)變亮,繼而在最亮的時(shí)刻開始逐漸變暗、熄滅最后歸于虛無,就像酣睡中隨著人的呼吸而起伏的胸膛。每當(dāng)看到手機(jī)屏幕上的呼吸燈閃爍時(shí),你是否想過,如何自己設(shè)計(jì)一個(gè)呼吸燈,讓它伴隨著你的呼吸變亮變暗。沒有做過呼吸燈的同學(xué)不要緊,我將會(huì)為大家展示一個(gè)使用清晰整潔的代碼設(shè)計(jì)出來的呼吸燈。認(rèn)真看完這篇文章,我可以保證你能夠真正了解呼吸燈是使用怎樣的原理設(shè)計(jì)的,并且可以自己獨(dú)立設(shè)計(jì)出自己的呼吸燈。快去點(diǎn)亮它吧!
介紹一下呼吸燈設(shè)計(jì)的基本原理:
呼吸燈是通過控制led燈閃爍的頻率來控制其亮度的。什么是閃爍的頻率?比如我們讓led燈在1s內(nèi)持續(xù)為亮,那么這個(gè)led燈將會(huì)一直以最大的亮度閃亮,亮的頻率就是1;當(dāng)我們讓led燈在1s內(nèi)持續(xù)為暗,那么led燈將會(huì)一直熄滅,亮的頻率就是0;若是我們讓led燈在1s中前0.5s內(nèi)為亮、后0.5s內(nèi)為滅,那么led燈將會(huì)一直一閃一滅,持續(xù)下去...我們可以大膽的想象一下,如果我們能夠控制led燈在1s內(nèi)一開始亮的頻率為0,然后一點(diǎn)一點(diǎn)的增大亮的頻率直至為1,那么led燈是否就可以由暗慢慢變到最亮。道理已經(jīng)明白了,那么我們要怎樣控制led燈亮的頻率?通過控制led燈亮的時(shí)間長(zhǎng)度。怎樣控制燈亮的時(shí)間?通過計(jì)數(shù)FPGA的時(shí)鐘個(gè)數(shù)。該怎樣計(jì)數(shù)FPGA的時(shí)鐘個(gè)數(shù)?
下面講一下本設(shè)計(jì)的基本思想:
我們讓led燈在1s內(nèi)由暗慢慢點(diǎn)亮,那么我們不妨將1s先分成1000等份,每一等份就是1ms,用一個(gè)計(jì)數(shù)ms個(gè)數(shù)的計(jì)數(shù)器cnt_ms來計(jì)數(shù)。1ms分成1000等份,每一等份就是1us,用計(jì)數(shù)器cnt_us來標(biāo)示。由于MP801開發(fā)板的FPGA時(shí)鐘頻率是20ns,那么我們就將1us分成50份,每一份就是20ns,即一個(gè)時(shí)鐘周期。通過計(jì)數(shù)時(shí)鐘周期的個(gè)數(shù),計(jì)數(shù)到第50個(gè)時(shí),就到達(dá)了1us,計(jì)數(shù)器cnt_us就開始加1;cnt_us計(jì)數(shù)到1000個(gè)時(shí),就到達(dá)了1ms,接著計(jì)數(shù)到1s...時(shí)間已經(jīng)劃分好了,那么我們?cè)撛趺纯刂苐ed燈亮的時(shí)間?
通過PWM原理來控制led亮滅。不了解PWM原理不重要,只要能讀懂下面一句話即可:
在0-1S內(nèi):讓led燈在第0-1ms之間亮的時(shí)間為0us;在第1-2ms內(nèi)亮1us,在第2-3ms內(nèi)亮2us...在第999-1000Ms內(nèi)亮999us。
思路已經(jīng)很清晰了,接下來我們就可以進(jìn)行電路設(shè)計(jì)。
信號(hào)列表:
信號(hào)名稱 |
信號(hào)類型 |
位寬 |
功能描述 |
clk |
I |
1 |
時(shí)鐘信號(hào) |
rst_n |
I |
1 |
復(fù)位信號(hào) |
led |
O |
1 |
輸出led信號(hào) |
|
|||
led_bright |
wire |
1 |
控制led亮滅 |
cnt_ns |
reg |
10 |
用來計(jì)數(shù)20ns的時(shí)鐘周期數(shù),計(jì)數(shù)到50個(gè)即到達(dá)1us,計(jì)數(shù)器清零 |
add_cnt_ns |
wire |
1 |
計(jì)數(shù)器cnt_ns加一指示信號(hào),一直為1 |
end_cnt_ns |
wire |
1 |
計(jì)數(shù)器cnt_ns清零指示信號(hào),當(dāng)cnt_ns計(jì)數(shù)到第50時(shí)為1 |
cnt_us |
reg |
10 |
用來計(jì)數(shù)產(chǎn)生1us的個(gè)數(shù) |
add_cnt_us |
wire |
1 |
計(jì)數(shù)器cnt_us加一指示信號(hào),end_cnt_ns拉高時(shí)有效 |
end_cnt_us |
wire |
1 |
計(jì)數(shù)器cnt_us清零指示信號(hào),cnt_us計(jì)數(shù)到第1000個(gè)時(shí)拉高 |
cnt_ms |
reg |
10 |
用來計(jì)數(shù)1ms的個(gè)數(shù),加一條件是end_cnt_us有效 |
add_cnt_ms |
wire |
1 |
cnt_ms加一指示信號(hào),end_cnt_us拉高時(shí)有效 |
end_cnt_ms |
wire |
1 |
計(jì)數(shù)器cnt_ms清零指示信號(hào),當(dāng)cnt_ms計(jì)數(shù)到第1000個(gè)時(shí)拉高 |
cnt_s |
reg |
1 |
用來計(jì)數(shù)1s的個(gè)數(shù) |
cdd_cnt_s |
wire |
1 |
cnt_s加一指示信號(hào),當(dāng)end_cnt_ms拉高有效 |
cnd_cnt_s |
wire |
1 |
計(jì)數(shù)器Cnt_s清零指示信號(hào),cnt_s計(jì)數(shù)到2拉高 |
計(jì)數(shù)us信號(hào):
計(jì)數(shù)ms信號(hào):
控制led亮的指示信號(hào):
按照我上面的設(shè)計(jì)思想,在100ms內(nèi),控制亮的時(shí)間不大于100us;在200ms內(nèi),控制亮的時(shí)間不大于200us。
led輸出信號(hào):
在亮的時(shí)間區(qū)域內(nèi)led給低電平,led亮;其他時(shí)間給led高電平,led滅。
OK,將工程綜合編譯,分配好管腳,燒錄到MP801開發(fā)板中,即可觀察到屬于你自己的呼吸燈。
可以看出,使用至簡(jiǎn)設(shè)計(jì)法設(shè)計(jì)出的代碼,思路清晰,代碼簡(jiǎn)潔干凈、有跡可循,只要設(shè)計(jì)的思路清晰,設(shè)計(jì)出的代碼也同樣是易讀易懂,每個(gè)信號(hào)都有其特定的功能。因此FPGA設(shè)計(jì)的核心是設(shè)計(jì)思路,而不是設(shè)計(jì)代碼,代碼只是用來告訴編譯器我們的設(shè)計(jì)思路,再由編譯器綜合成硬件電路。使用一種規(guī)范簡(jiǎn)潔的代碼設(shè)計(jì)方法可以幫助我們更好的表現(xiàn)出我們的設(shè)計(jì)思路,這在我們進(jìn)行FPGA設(shè)計(jì)過程中可以極大提高我們的設(shè)計(jì)效率。
以上就是設(shè)計(jì)呼吸燈的思考與步驟,需要此工程明德?lián)P設(shè)計(jì)的源碼的朋友可以加我的QQ:3358622769無償獲取,也歡迎大家與我進(jìn)行深入討論,期待與大家一起學(xué)習(xí)進(jìn)步!