51单片机PWM信号控制呼吸流水灯

题目要求
1.实现按下K1启动呼吸流水灯,由LED1~LED8依次进行呼吸,再按下一次K1,流水的方向从当前正在呼吸的LED开始逆向流水变化。
2.按下K1不松手,停止流水变化和当前正在呼吸的LED的亮度不变,松手后继续呼吸和流水变化。
3.每个LED灯,缓慢点亮0.5秒,缓慢熄灭0.5秒。
【注】 题目要求和程序的部分思路参考自小蜜蜂老师
原文链接:https://blog.csdn.net/ohy3686/article/details/88372244

本例采用普中的51开发板测试
【程序】

#include <REGX52.H>
#include <INTRINS.H>
sbit K1=P3^1;

unsigned int count_Breath;//用于呼吸时长的计数
unsigned char count_pwm;//用于占空比的计数
unsigned char pwm_duty;//占空比
unsigned char breath_Direct;//控制是‘呼’还是‘吸’
unsigned char led_index;//保存当前进行呼吸的LED下标
unsigned char led_run_direct;//流水灯的方向。1为LED1-LED8,0为LED8-LED1
unsigned char K1_Keep_flag;//K1持续按下的标志,K1按下不松手时将其置1

void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

void Timer0_init(void)//12MHz@1ms
{
	TMOD = 0x01;
	TH0 = (65535 - 1000) / 256;			
	TL0 = (65535 - 1000) % 256;
	
	ET0 = 1;
	EA = 1;
	
}

void Timer0_routine(void) interrupt 1
{
	TH0 = (65535 - 1000) / 256;			
	TL0 = (65535 - 1000) % 256;
	//当K1按下不松手时,K1_Keep_flag=1,此时就不会执行K1_Keep_flag++,那么就可以实现按住K1停止呼吸和流水变化了
	if(K1_Keep_flag==0)
	{
		count_Breath++;	
	}

	count_pwm++;
	count_pwm%=10;//将pwm分成10份

	if(count_pwm<pwm_duty)
	{
		P2=~(0x01<<led_index);
	}
	else 
	{
		P2=0xFF;
	}
	if(count_Breath>=50 && breath_Direct==1)//占空比增加
	{
		pwm_duty++;
		count_Breath=0;
		if(pwm_duty>=10)
		{
			breath_Direct=0;
			pwm_duty=9;
		}
	}
	if(count_Breath>=50 && breath_Direct==0)//占空比减小
	{
		pwm_duty--;
		count_Breath=0;
		if(pwm_duty==255)
		{
			breath_Direct=1;
			pwm_duty=0;
			//当一个LED执行完一次呼吸以后跳转到下一个LED
			if(led_run_direct==1)
			{
				led_index++;
				led_index%=8;
			}
			else if(led_run_direct==0)
			{
				led_index--;
				if(led_index==255)//已经溢出了
				{
					led_index=7;
				}
			}
		}
		
	}
}

//按键扫描,通过按键K1控制流水灯的方向
void alone_key_scan(void)
{
	if(K1==0)
	{
		Delay(5);
		while(K1==0)//当K1按下不松手时,保持当前的正在呼吸的LED和它的亮度不变
		{
			K1_Keep_flag=1;
		}
		Delay(5);
		K1_Keep_flag=0;
		TR0 = 1;//上电以后要按下K1才开始流水呼吸灯
		led_run_direct=!led_run_direct;
	}
}

void main()
{
	Timer0_init();
	while(1)
	{
		alone_key_scan();
	}
}
  • 5
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值