同时实现LED灯流水和呼吸效果

本文为在不使用PWM输出的情况下,同时实现LED流水和呼吸效果提供一种简单思路,当单片机需要同时控制很多个灯的时候,PWM输出引脚很明显是不够的,所以尝试用普通IO口尝试完成这个功能。(实验代码是使用的HAL库中的通用函数)

一、流水灯

流水灯的实现比较简单,点亮一个灯之后稍微做一个延时,再熄灭这个灯,同时点亮下一个灯即可。

  HAL_GPIO_WritePin(LED7_GPIO_Port,LED7_Pin,1);
  HAL_Delay(300);
  HAL_GPIO_WritePin(LED7_GPIO_Port,LED7_Pin,0);
  HAL_GPIO_WritePin(LED6_GPIO_Port,LED6_Pin,1);
  HAL_Delay(300);
  HAL_GPIO_WritePin(LED9_GPIO_Port,LED9_Pin,0);

在此便不在过多赘述。

二、呼吸灯

呼吸灯就是让LED灯实现渐亮和渐灭,我们首先想到的就是控制电压,但对于单片机而言,它的输出只有0和1两种状态,并不能调节电压大小。所以呼吸灯的实现是通过闪烁实现的,具体就是在一个极短的周期内,控制LED灯亮灭的时间比。比如,设置周期为1ms,在这1ms内,亮的时间为500us,灭的时间为500us,然后不断循环这个周期,从视觉上来看就是灯的亮度会降低一半。PWM输出就是输出一个方波,改变高电平的占比(即占空比),来控制LED灯的亮度。这里可以简单理解为改变的是LED灯的平均电压。
但PWM输出需要定时器,一个单片机的定时器数量并不是很多,没办法独立控制很多的灯,本文在这里使用延时函数来进行模拟PWM输出,也能实现控制LED灯的亮度。

	for(int i=1;i<1000;i++)
	{
		if(i<1000)
		{
			HAL_GPIO_WritePin(LED7_GPIO_Port,LED7_Pin,1);
			delay_us(1000-i);
			HAL_GPIO_WritePin(LED7_GPIO_Port,LED7_Pin,0);
			delay_us(i);
		}
	}

delay_us是一个微秒延时函数

void delay(int d)
{
	 uint32_t Delay = d * 8/4;	//8是时钟频率
	 do
	 {
	  __NOP();
	 }
	 while (Delay --);
}

这样就能实现一个渐变灯。

三、流水+呼吸

最简单的办法其实只要将多个呼吸灯排列起来就行,但总有一些特殊需求,需要几个灯同时呼吸,但呼吸阶段不同。本文介绍的是当第一个灯呼吸到一半亮度时,第二个灯开始呼吸,第一个灯呼吸结束时,第二个灯呼吸一半,同时,第三个灯开始亮,以此类推。这样可以让流水灯之间的流淌更加舒缓连续。

for(int i=1;i<4000;i++)	//每单个周期是2ms,这里是一共8s让所有灯亮起来
{
	if(i<1000)	//第一阶段,LED1亮一半之前的时间
	{
		HAL_GPIO_WritePin(LED7_GPIO_Port,LED7_Pin,1);
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,1);
		delay(2000-i);
		HAL_GPIO_WritePin(LED7_GPIO_Port,LED7_Pin,0);
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,0);
		delay(i);	//两个延时加起来是2000
	}
	if(1000<=i&&i<=2000)	//第二阶段,LED1亮一半之后,LED2亮一半之前
	{
		HAL_GPIO_WritePin(LED7_GPIO_Port,LED7_Pin,1);
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,1);
		delay(2000-i);
		HAL_GPIO_WritePin(LED7_GPIO_Port,LED7_Pin,0);
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,0);
		delay(1000);
		HAL_GPIO_WritePin(LED6_GPIO_Port,LED6_Pin,0);
		HAL_GPIO_WritePin(LED9_GPIO_Port,LED9_Pin,0);
		delay(i-1000);	//三个延时时间之和是2000
		HAL_GPIO_WritePin(LED6_GPIO_Port,LED6_Pin,1);
		HAL_GPIO_WritePin(LED9_GPIO_Port,LED9_Pin,1);
	}
	if(2000<=i&&i<=3000)	//第三阶段,LED2亮一半之后,LED3亮一半之前
	{
		HAL_GPIO_WritePin(LED6_GPIO_Port,LED6_Pin,1);
		HAL_GPIO_WritePin(LED9_GPIO_Port,LED9_Pin,1);
		delay(3000-i);
		HAL_GPIO_WritePin(LED6_GPIO_Port,LED6_Pin,0);
		HAL_GPIO_WritePin(LED9_GPIO_Port,LED9_Pin,0);
		delay(1000);
		HAL_GPIO_WritePin(LED5_GPIO_Port,LED5_Pin,0);
		HAL_GPIO_WritePin(LED10_GPIO_Port,LED10_Pin,0);
		delay(i-2000);	//三个延时之和为2000
		HAL_GPIO_WritePin(LED5_GPIO_Port,LED5_Pin,1);
		HAL_GPIO_WritePin(LED10_GPIO_Port,LED10_Pin,1);
	}
	if(i>3000)	//最后阶段,LED3亮一半之后
	{
		HAL_GPIO_WritePin(LED5_GPIO_Port,LED5_Pin,1);
		HAL_GPIO_WritePin(LED10_GPIO_Port,LED10_Pin,1);
		delay(4000-i);
		HAL_GPIO_WritePin(LED5_GPIO_Port,LED5_Pin,0);
		HAL_GPIO_WritePin(LED10_GPIO_Port,LED10_Pin,0);
		delay(i-2000);	//延时之和为2000
	}
}

以上的逻辑作为一种参考,可以通过调整延时函数来实现对LED的不同状态的控制,但控制过程中会占用CPU,在此期间不能执行其他程序,比较鸡肋,在此只作娱乐。
本文所提供的这种方法,比较笨拙,只能设计流水灯带等类似的小玩具,流水渐变效果还是比较不错的。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值