EGo1下板_PWM呼吸灯

嵌入式课上老师提到了单片机实现呼吸灯,那会儿说可以控制亮灭的时间间隔来控制灯的亮灭程度,然后我就下面这样的操作:

// 单片机伪代码意思一下
LED = 1;	Delay(10);		LED = 0;	Delay(10);
LED = 1;	Delay(20);		LED = 0;	Delay(20);
LED = 1;	Delay(30);		LED = 0;	Delay(30);
LED = 1;	Delay(40);		LED = 0;	Delay(40);

LED = 1;	Delay(30);		LED = 0;	Delay(30);
LED = 1;	Delay(20);		LED = 0;	Delay(20);
LED = 1;	Delay(10);		LED = 0;	Delay(10);

太草率了,弄了四组数据
下板之后确实肉眼看到亮灭,但是不流畅,可以这样试一下,就会发现这样不配叫呼吸灯。。。。

一、 PWM工作原理

用渐变的PWM(脉冲宽度调制)信号实现LED呼吸灯。 LED由暗逐渐变亮,再由亮逐渐变暗循环。
**先分频,再设置占空比。**在一个时钟周期内,高电平时长与一个周期的时长的比值叫做占空比,占空比越高,相当于通过led的电流越大,肉眼就觉得很亮。

led高有效
在这里插入图片描述

完全熄灭到完全点亮
在这里插入图片描述

led高电平亮
在每一个T内,如何让低电平的保持时间持续的增长?
当1ms计数器的计数值≤1s计数器的计数值,led就保持高电平,其他时间保持低电平

上面实现的是由完全熄灭到完全点亮,完全点亮到完全熄灭是一个取反的过程,添加一个en使能信号
在这里插入图片描述

三个计数器之间存在倍数关系
当都使用时钟信号计数,1s的计数值是最大的,1ms第二大,1us第三大
如果用1ms针对1us进行计数,1m针对1ms进行计数,这样的计数值最大就是999,可以节省逻辑资源

二、代码实现

100MHz系统时钟
在这里插入图片描述

module breath_led
#(
	parameter		CNT_1US_MAX	=	7'd99,	
	parameter		CNT_1MS_MAX	=	10'd999,
	parameter		CNT_1S_MAX	=	10'd999
)
(
	input		wire			sys_clk,		// 100MHz
	input		wire			sys_rst_n,
	
	output		reg				led
    );

	
	reg		[9:0]	cnt_1s;
	reg		[9:0]	cnt_1ms;
	reg		[6:0]	cnt_1us;
	reg				cnt_en;
	
	always @ (posedge sys_clk or negedge sys_rst_n)
		if (sys_rst_n == 1'b0)
			cnt_1us	<=	6'd0;
		else	if (cnt_1us == CNT_1US_MAX)
			cnt_1us	<=	6'd0;
		else
			cnt_1us	<=	cnt_1us + 1'b1;
			
	always @ (posedge sys_clk or negedge sys_rst_n)
		if (sys_rst_n == 1'b0)
			cnt_1ms	<=	10'd0;
		else	if ( (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX) )
			cnt_1ms	<=	10'd0;
		else	if (cnt_1us == CNT_1US_MAX)
			cnt_1ms	<=	cnt_1ms + 1'b1;
		else
			cnt_1ms	<=	cnt_1ms;

	always @ (posedge sys_clk or negedge sys_rst_n)
		if (sys_rst_n == 1'b0)
			cnt_1s	<=	10'd0;
		else	if ( (cnt_1s == CNT_1S_MAX) && (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX) )
			cnt_1s	<=	10'd0;
		else	if ( (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX) )
			cnt_1s	<=	cnt_1s + 1'b1;
		else
			cnt_1s	<=	cnt_1s;
	
	// 亮灭渐变反转
	always @ (posedge sys_clk or negedge sys_rst_n)
		if (sys_rst_n == 1'b0)
			cnt_en	<=	1'b1;
		else	if ( (cnt_1s == CNT_1S_MAX) && (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX) )
			cnt_en	<=	~cnt_en;
		else
			cnt_en	<=	cnt_en;
	
	// led高有效
	always @ (posedge sys_clk or negedge sys_rst_n)
		if (sys_rst_n == 1'b0)
			led	<=	1'b0;
		else	if ( ((cnt_en == 1'b1) && (cnt_1ms <= cnt_1s))		// 完全熄灭到完全点亮
						|| ((cnt_en == 1'b0) &&  (cnt_1ms > cnt_1s)) )	// 完全点亮到完全熄灭
			led	<=	1'b1;
		else
			led	<=	1'b0;
	
endmodule

在这里插入图片描述
下板之后确实看到期待的现象

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值