EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
【教程】看完就懂!运用至简设计法进行呼吸灯设计 % G- _5 c) W: v3 `* a6 z
作者:鱼丸粗面
# @$ F9 Y/ w' i( c, j; H3 U本文为明德扬原创文章,转载请注明出处! ( u6 M& \0 u1 t9 n9 C1 m
呼吸灯是指灯光在微电脑的控制之下完成由亮到暗的逐渐变化,感觉好像是人在呼吸。其广泛应用于手机、电脑等电子产品之上,并成为各大品牌新款手机的卖点之一,起到一个通知提醒的作用。每个人都应该使用过带有呼吸灯的手机,看着灯光由暗淡逐渐一点点变亮,继而在最亮的时刻开始逐渐变暗、熄灭最后归于虚无,就像酣睡中随着人的呼吸而起伏的胸膛 每当看到手机屏幕上的呼吸灯闪烁时,你是否想过,如何自己设计一个呼吸灯,让它伴随着你的呼吸变亮变暗。没有做过呼吸灯的同学不要紧,我将会为大家展示一个使用清晰整洁的代码设计出来的呼吸灯。 认真看完这篇文章,我可以保证你能够真正了解呼吸灯是使用怎样的原理设计的,并且可以自己独立设计出自己的呼吸灯。快去点亮它吧! 首先介绍一下呼吸灯设计的基本原理: 呼吸灯是通过控制led灯闪烁的频率来控制其亮度的。 5 o* Z* u1 M; T( u6 M! O
Q1:什么是闪烁的频率?
2 \( |) M! m& a+ R比如我们让led灯在1s内持续为亮,那么这个led灯将会一直以最大的亮度闪亮,亮的频率就是1;当我们让led灯在1s内持续为暗,那么led灯将会一直熄灭,亮的频率就是0;若是我们让led灯在1s中前0.5s内为亮、后0.5s内为灭,那么led灯将会一直一闪一灭,持续下去...我们可以大胆的想象一下,如果我们能够控制led灯在1s内一开始亮的频率为0,然后一点一点的增大亮的频率直至为1,那么led灯是否就可以由暗慢慢变到最亮。道理已经明白了? Q2:那么我们要怎样控制led灯亮的频率呢?
; }' y5 Z& N }4 |' |. k4 i 2 C0 L" v# [1 `7 H% }1 A7 i
通过控制led灯亮的时间长度。 + Y1 f4 N+ C* `
Q3:怎样控制灯亮的时间?
) z; C: O0 q: A+ \7 [
z& z) Q4 x, h) ?% s5 J0 mQ4:该怎样计数FPGA的时钟个数?
6 }& c# O9 q* I, Q1 O3 R1 ^. ^% U本设计的基本思想:
* l) l" p% A; z8 n8 ?我们让led灯在1s内由暗慢慢点亮,那么我们不妨将1s先分成1000等份,每一等份就是1ms,用一个计数ms个数的计数器cnt_ms来计数。1ms分成1000等份,每一等份就是1us,用计数器cnt_us来标示。由于MP801开发板的FPGA时钟频率是20ns,那么我们就将1us分成50份,每一份就是20ns,即一个时钟周期。通过计数时钟周期的个数,计数到第50个时,就到达了1us,计数器cnt_us就开始加1;cnt_us计数到1000个时,就到达了1ms,接着计数到1s...
$ R( `1 g! s& P+ dQ5:时间已经划分好了,那么我们该怎么控制led灯亮的时间?
; h& v8 Y( }# p7 s3 i通过PWM原理来控制led亮灭。
3 w" ?6 M9 p' O0 V/ N R" U- I, `' G不了解PWM原理不重要,只要能读懂下面一句话即可:
9 v6 t0 H% r( j$ t" [; l: L) p在0-1S内:让led灯在第0-1ms之间亮的时间为0us;在第1-2ms内亮1us,在第2-3ms内亮2us...在第999-1000Ms内亮999us。
$ \5 s( G# T3 ^0 \. v! U思路已经很清晰了,接下来我们就可以进行电路设计。 ( N% _ m( I: R" X. ]6 D0 H- L
信号列表: 4 w! Q9 c h1 l; p3 g
信号名称 | 信号类型 | 位宽 | 功能描述 | clk | I | 1 | 时钟信号 | rst_n | I | 1 | 复位信号 | led | O | 1 | 输出led信号 | led_bright | wire | 1 | 控制led亮灭 | cnt_ns | reg | 10 | 用来计数20ns的时钟周期数,计数到50个即到达1us,计数器清零 | add_cnt_ns | wire | 1 | 计数器cnt_ns加一指示信号,一直为1 | end_cnt_ns | wire | 1 | 计数器cnt_ns清零指示信号,当cnt_ns计数到第50时为1 | cnt_us | reg | 10 | 用来计数产生1us的个数 | add_cnt_us | wire | 1 | 计数器cnt_us加一指示信号,end_cnt_ns拉高时有效 | end_cnt_us | wire | 1 | 计数器cnt_us清零指示信号,cnt_us计数到第1000个时拉高 | cnt_ms | reg | 10 | 用来计数1ms的个数,加一条件是end_cnt_us有效 | add_cnt_ms | wire | 1 | cnt_ms加一指示信号,end_cnt_us拉高时有效 | end_cnt_ms | wire | 1 | 计数器cnt_ms清零指示信号,当cnt_ms计数到第1000个时拉高 | cnt_s | reg | 1 | 用来计数1s的个数 | cdd_cnt_s | wire | 1 | cnt_s加一指示信号,当end_cnt_ms拉高有效 | cnd_cnt_s | wire | 1 | 计数器Cnt_s清零指示信号,cnt_s计数到2拉高 | / o- W$ U/ S+ {: a
计数us信号:
7 T f4 q" q1 S' H5 j- l& t计数ms信号:
@+ {2 y& J5 W控制led亮的指示信号: 按照我上面的设计思想,在100ms内,控制亮的时间不大于100us;在200ms内,控制亮的时间不大于200us。
! ?6 c& a: z' M2 aled输出信号: 在亮的时间区域内led给低电平,led亮;其他时间给led高电平,led灭。
- \/ v9 v ]; t1 s0 ]: j OK,将工程综合编译,分配好管脚,烧录到MP801开发板中,即可观察到属于你自己的呼吸灯。 7 q) D `8 M0 k9 e6 }. j8 P# S' S
* I5 z. Y# _/ X3 M
可以看出,使用至简设计法设计出的代码,思路清晰,代码简洁干净、有迹可循,只要设计的思路清晰,设计出的代码也同样是易读易懂,每个信号都有其特定的功能。
4 o0 Q' J( }) s% K" p8 I 因此FPGA设计的核心是设计思路,而不是设计代码,代码只是用来告诉编译器我们的设计思路,再由编译器综合成硬件电路。使用一种规范简洁的代码设计方法可以帮助我们更好的表现出我们的设计思路,这在我们进行FPGA设计过程中可以极大提高我们的设计效率。
$ {+ Z: b& e4 r1 r1 }' J; ?' u- Q3 y/ t- w$ s
: {" X' A2 j7 E) _
# ]- ?; Z* v: F( `- H g: e |