呼吸灯实验
& x- a! }3 j6 J# T呼吸灯最早由苹果公司发明并应用于笔记本睡眠提示上,其一经展出,立刻吸引众多科技厂商争相效仿,并广泛用于各种电子产品中,尤其是智能手机。呼吸灯其实是在微处理器的控制下,由暗渐亮、然后再由亮渐暗,模仿人呼吸方式的LED灯。* {7 G4 [3 I% r: I( \
|/ }' t3 x" a9 N7 I, s1.1 呼吸灯简介
" Y {9 K" g; a' Y+ S0 \8 x0 M; Y0 W4 B呼吸灯采用PWM的方式,在固定的频率下,通过调整占空比的方式来控制LED灯亮度的变化。PWM(Pulse Width Modulation),即脉冲宽度调制,它利用微处理器输出的PWM信号,实现对模拟电路控制的一种非常有效的技术,广泛应用于测量、通信、功率控制等领域。4 k" C9 F4 L. l. G: r4 w, @& X
在由计数器产生的固定周期的PWM信号下,如果其占空比为0,则LED灯不亮;如果其占空比为100%,则LED灯最亮。所以将占空比从0到100%,再从100%到0不断变化,就可以实现LED灯的“呼吸”效果。
! n% C! S. p1 d9 q. u4 @PWM占空比调节示意图如下图所示:
! _6 q5 C8 {0 Z7 }7 m! ^7 ?" e
" r9 W# T6 m% }9 u" `5 F6 W/ _
- k; {4 P9 |) W, r* V
% g, f' c, r9 L+ Y# s+ _图 7.5.13.1 呼吸灯PWM占空比示意图
# d) Z7 s+ K6 Q9 ^由上图可知,LED高电平的时间由长渐渐变短,再由短渐渐变长,如果LED灯是高电平点亮,则LED灯会呈现出亮度由亮到暗,再由暗到亮的过程。& m2 S) }# ]' l) a" \- }& l4 g
1.2 实验任务
/ Y( c, Q3 k7 I7 B本节实验任务是使用正点原子ZYNQ开发板(核心板)上的PL LED,实现呼吸灯的效果,即由灭渐亮,然后再由亮渐灭。, d. i2 X% ]8 x" M) S
& O4 B1 j& B) r( L1.3 硬件设计
+ f7 M, H5 g3 _5 M9 I1 m2 F发光二极管的原理图如下图所示,PL LED发光二极管位于核心板上,其阴极通过330欧姆的电阻连到地(GND),阳极与ZYNQ的IO相连,LED与地之间的电阻起到限流作用。当PL_LED输出高电平时,点亮LED灯,当PL LED输出低电平时,LED灯熄灭。) r0 B, q) h: C& M* f$ ]* a* J( }# y) o
4 E: ^3 ?: ?4 f( H7 ^
0 {6 ?- u' i, n7 ~
9 p5 J' i) }4 W$ G. E5 R4 R
图 7.5.13.1 呼吸灯硬件原理图
' f0 g. y1 }4 j! N0 Q! ~* a! ]* `本实验中,系统时钟、按键复位以及LED端口的管脚分配如下表所示: j, Y! ~- Y$ [" d* p6 ]) m
表 12.3.1 呼吸灯实验管脚分配
2 f; o8 ~( W0 {# M1 H) j! J: S信号名 方向 管脚 端口说明 电平标准* E# @' c" [+ J; `! {8 M/ ~& W
sys_clk input U18 系统时钟,50MHz LVCMOS33% w. i' e7 x+ {/ n8 |. W
sys_rst_n input N16 系统复位按键,低电平有效 LVCMOS33
1 x F, y: p D4 mled output J16 PL LED(核心板) LVCMOS33
0 A. H0 p4 z: y% G9 W0 n对应的XDC约束语句如下所示:
0 x% s: _* V4 `+ J- {6 a#IO管脚约束8 i" O4 }: F* h+ c- e3 ^* {# M: a
- set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports sys_clk]' ^; u3 L5 _( q
- set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]! ?& o; ]' {0 F7 m
- set_property -dict {PACKAGE_PIN J16 IOSTANDARD LVCMOS33} [get_ports led]
复制代码 + f, u' d, M. ?6 `2 R
1.4 程序设计
; i; g. u. y$ V本次实验的模块端口及结构框图如下图所示。
$ \* Y. m9 [# u图 7.5.13.1 模块端口及信号连接图% X# O- T) s, u9 m- E
周期信号计数器用于产生驱动LED的脉冲信号,本次实验的周期信号频率为1Khz,其占空比由后级逻辑在每个周期之后进行递增或递减,最后再对当前计数值和占空比计数值进行比较,以输出占空比可调的脉冲信号。
, D( V( @; H, \呼吸灯代码如下:) S [& h7 n$ L- M5 R
1 c" e5 D2 J0 t+ ^3 D, R% Z
- 1 module breath_led(1 a; E3 u* o8 j7 j b7 I3 [8 p j1 L
- 2 input sys_clk , //时钟信号50Mhz% L% G- W: H" c9 \
- 3 input sys_rst_n , //复位信号1 K9 `2 Z5 G8 ?8 V
- 4 $ J7 L i7 S- d% \1 }* K2 n, F
- 5 output led //LED8 n; s+ k- \% Z; S3 f. Q
- 6 );3 P, D( x3 A% z k! ^! O8 e; c; P
- 7 2 r0 Y4 f" z/ R' S* b j
- 8 //reg define
$ `3 u1 k7 G& R - 9 reg [15:0] period_cnt ; //周期计数器频率:1khz 周期:1ms 计数值:1ms/20ns=50000
2 l$ f* `1 J+ t! S' G- J - 10 reg [15:0] duty_cycle ; //占空比数值+ W: A# i) ~/ {3 q# {1 U1 K! i7 G( y
- 11 reg inc_dec_flag ; //0 递增 1 递减# h4 [8 I9 |1 e, s! r4 s
- 12
) m( i8 Q) Y/ l1 G, ~ - 13 //*****************************************************( _9 b* ~3 [/ L/ F8 G2 _( N
- 14 //** main code
0 W k% j3 q2 h( v - 15 //*****************************************************
. x9 G* l! W5 B# O: y: y - 16
& W7 E2 A+ T( V3 A' V; I - 17 //根据占空比和计数值之间的大小关系来输出LED9 ~3 \# U. b8 D! d6 t, h3 R
- 18 assign led = (period_cnt >= duty_cycle) ? 1'b1 : 1'b0;
Y& q8 C+ _% ~* W - 19 8 ]; U+ }- H" I4 F; w' o3 S2 W
- 20 //周期计数器
5 G" s7 p' {3 P) N; R& E! z - 21 always @(posedge sys_clk or negedge sys_rst_n) begin, O3 b$ t5 n# d
- 22 if(!sys_rst_n)( L0 I( i/ P& C6 x& j* Y4 v A1 U& M
- 23 period_cnt <= 16'd0;1 K7 ?$ B, t8 L1 D
- 24 else if(period_cnt == 16'd50000)
D, Y9 D; L: @; f ]' ] - 25 period_cnt <= 16'd0;
& k* y7 Q- D3 O) u. b - 26 else8 a' ]2 C; P9 Z1 c
- 27 period_cnt <= period_cnt + 1'b1;
% V3 `2 [5 y" R1 V7 J* ? - 28 end; ]+ F1 B+ ^( V+ ^
- 29
- b2 l$ [, t1 M$ r+ Y, T7 ?* V/ \ - 30 //在周期计数器的节拍下递增或递减占空比
n1 Q& v+ `$ X, g# Q& G/ ? - 31 always @(posedge sys_clk or negedge sys_rst_n) begin
! d& }9 D4 _) W4 [# r) h* @ - 32 if(!sys_rst_n) begin
6 k R1 I. D2 u - 33 duty_cycle <= 16'd0;" g3 }; V8 c1 g
- 34 inc_dec_flag <= 1'b0;6 ~8 `2 ?) \5 g. h0 l" K$ B7 m
- 35 end3 d; h/ E h+ d
- 36 else begin
/ {6 a' [" M) k& o; H2 @ - 37 if(period_cnt == 16'd50000) begin //计满1ms
" j! B0 z7 N" D8 K, _" A: v - 38 if(inc_dec_flag == 1'b0) begin //占空比递增状态: ?3 O' ~- m! R) p# I
- 39 if(duty_cycle == 16'd50000) //如果占空比已递增至最大
( p6 H' q( l0 N. w - 40 inc_dec_flag <= 1'b1; //则占空比开始递减
8 J$ d' L% `! f' P5 L - 41 else //否则占空比以25为单位递增; \/ Q& \' i" m$ n0 F3 U% S6 x
- 42 duty_cycle <= duty_cycle + 16'd25;
6 d2 ^5 X9 D0 n) O - 43 end
+ r; N% f) ?; r# B' f - 44 else begin //占空比递减状态0 n- h S# [1 `6 {( ^( ]
- 45 if(duty_cycle == 16'd0) //如果占空比已递减至0
' ^1 j$ [+ g) }* |+ p& W - 46 inc_dec_flag <= 1'b0; //则占空比开始递增
6 l/ }- s' y" y$ @; }0 ? - 47 else //否则占空比以25为单位递减 [: s; G7 G1 }& q: B+ W) V
- 48 duty_cycle <= duty_cycle - 16'd25;+ C& q9 r2 Q/ I/ W+ z) S5 |
- 49 end( ^3 M" l" q& x; j' B3 C
- 50 end
! `$ l' D+ N3 [5 W0 V! I - 51 end! N" g8 {' Y6 V. l2 T
- 52 end
4 ~) s( [7 b9 } - 53 j& b6 `$ K, M7 R
- 54 endmodule
复制代码 * b, W& v w; |
第21-28行是1KHz周期信号的计数器,用于产生1KHz的LED驱动信号。第31-52行的always块为占空比设定模块,每次计数完了一个周期,就根据递增/递减标志来对占空比计数值(duty_cycle)进行递增/递减25个计数值,这个递增或者递减的数值大小可以用来控制呼吸灯的呼吸频率。( t0 R- z+ r' \2 T
如果占空比计数值(duty_cycle)已经递增到了最大,则呼吸灯已经处于最亮的状态,接下来开始递减;反之,如果占空比计数至已经递减到了最小,即0,则呼吸灯处于熄灭的状态,接下来开始递增;如此循环往复,最终实现了流水灯的效果。
. w! j' b% ^4 b; X4 e在代码的第18行通过组合逻辑把当前的周期计数值和占空比计数值进行比较,来判断LED的输出电平。在一个周期内,如果当前的周期计数值小于等于占空比计数值,则LED输出高电平,即点亮;如果当前的周期计数值大于占空比计数值,则LED输出低电平,即熄灭。5 |& ^4 z6 ?( P! L/ ?) {
! ?. O6 Q& j* a1.5 下载验证
1 I+ d& _9 {2 Q; b5 y8 N编译工程并生成比特流.bit文件。将下载器一端连接电脑,另一端与开发板上的JTAG下载口连接,连接电源线,并打开开发板的电源开关。
* R; R4 s' t" a) h" b点击Vivado左侧“Flow Navigator”窗口最下面的“Open Hardware Manager”,此时Vivado软件识别到下载器,点击“Hardware”窗口中“Progam Device”下载程序,在弹出的界面中选择“Program”下载程序。4 a4 k5 n7 t% d% X+ J7 j
程序下载完成后,可以看到核心板的PL LED灯由暗慢慢变亮,再由亮慢慢变暗,即呈现出“呼吸”的效果,如下图所示:
3 g. F6 }0 z: | j" n在这里插入图片描述
( K* F$ V% j, a7 h8 |) S
4 V: `2 J8 k; x' p. t( k
0 w4 A% H4 b8 T. A, [( o) R6 R6 J" S0 u, z/ I" p) b; C
图 7.5.13.1 开发板实验现象
+ D: j! p3 j# z; Z0 o————————————————: X) h) _9 h J$ J* _
版权声明:正点原子! M1 K% f% v8 m+ m, Q
' c8 w. n6 W/ I) E' T6 |
, K2 P# b5 s; n# y
|